diff --git a/pkg/target/complexcomposition_test.go b/pkg/target/complexcomposition_test.go index a5d3a5eb068..6b582e075b3 100644 --- a/pkg/target/complexcomposition_test.go +++ b/pkg/target/complexcomposition_test.go @@ -224,7 +224,7 @@ resources: t.Fatalf("Expected resource accumulation error") } if !strings.Contains( - err.Error(), "already registered id: apps_v1_StatefulSet|~X|my-sts") { + err.Error(), "conflict between") { t.Fatalf("Unexpected err: %v", err) } @@ -283,7 +283,7 @@ resources: t.Fatalf("Expected resource accumulation error") } if !strings.Contains( - err.Error(), "already registered id: apps_v1_StatefulSet|~X|my-sts") { + err.Error(), "conflict between") { t.Fatalf("Unexpected err: %v", err) } diff --git a/pkg/target/diamondcomposition_test.go b/pkg/target/diamondcomposition_test.go index 137f2e21cbf..acb981e4122 100644 --- a/pkg/target/diamondcomposition_test.go +++ b/pkg/target/diamondcomposition_test.go @@ -62,17 +62,49 @@ func writeDeploymentBase(th *kusttest_test.KustTestHarness) { th.WriteK("/app/base", ` resources: - deployment.yaml +patchesStrategicMerge: +- dep-patch.yaml `) th.WriteF("/app/base/deployment.yaml", ` apiVersion: apps/v1 kind: Deployment +metadata: + name: my-deployment +spec: + template: + spec: + containers: + - name: my-deployment + image: my-image +`) + + th.WriteF("/app/base/dep-patch.yaml", ` +apiVersion: apps/v1 +kind: Deployment metadata: name: my-deployment spec: template: spec: dnsPolicy: "None" +`) +} + +func writeDeploymentBaseNoPatch(th *kusttest_test.KustTestHarness) { + th.WriteK("/app/base", ` +resources: +- deployment.yaml +`) + + th.WriteF("/app/base/deployment.yaml", ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-deployment +spec: + template: + spec: containers: - name: my-deployment image: my-image @@ -122,7 +154,11 @@ patchesStrategicMerge: // \ | / // base // -func TestIssue1251_CompositeDiamond_Failure(t *testing.T) { + +// In the case, the DeploymentBase is setting the DnsPolicy to None. +// Kustomize detects a merge conflict when merging probe, dns and restart +// into composite. +func TestIssue1251_CompositeDiamond_ProbeDnsRestart_MergeConflict(t *testing.T) { th := kusttest_test.NewKustTestHarness(t, "/app/composite") writeDeploymentBase(th) writeProbeOverlay(th) @@ -141,7 +177,55 @@ resources: t.Fatalf("Expected resource accumulation error") } if !strings.Contains( - err.Error(), "already registered id: apps_v1_Deployment|~X|my-deployment") { + err.Error(), "conflict between") { + t.Fatalf("Unexpected err: %v", err) + } +} + +func TestIssue1251_CompositeDiamond_ProbeRestartDns_MergeConflict(t *testing.T) { + th := kusttest_test.NewKustTestHarness(t, "/app/composite") + writeDeploymentBase(th) + writeProbeOverlay(th) + writeDNSOverlay(th) + writeRestartOverlay(th) + + th.WriteK("/app/composite", ` +resources: +- ../probe +- ../restart +- ../dns +`) + + _, err := th.MakeKustTarget().MakeCustomizedResMap() + if err == nil { + t.Fatalf("Expected resource accumulation error") + } + if !strings.Contains( + err.Error(), "conflict between") { + t.Fatalf("Unexpected err: %v", err) + } +} + +func TestIssue1251_CompositeDiamond_DnsProbeRestart_MergeConflict(t *testing.T) { + th := kusttest_test.NewKustTestHarness(t, "/app/composite") + writeDeploymentBase(th) + writeProbeOverlay(th) + writeDNSOverlay(th) + writeRestartOverlay(th) + + th.WriteK("/app/composite", ` +resources: +- ../dns +- ../probe +- ../restart +`) + + _, err := th.MakeKustTarget().MakeCustomizedResMap() + if err == nil { + t.Fatalf("Expected resource accumulation error") + } + if !strings.Contains( + err.Error(), "conflict between") { t.Fatalf("Unexpected err: %v", err) } } @@ -165,6 +249,51 @@ spec: restartPolicy: Always ` +// Same test except that there no conflict to be detected in during +// the merge +func TestIssue1251_CompositeDiamond_ProbeRestartDns(t *testing.T) { + th := kusttest_test.NewKustTestHarness(t, "/app/composite") + writeDeploymentBaseNoPatch(th) + writeProbeOverlay(th) + writeDNSOverlay(th) + writeRestartOverlay(th) + + th.WriteK("/app/composite", ` +resources: +- ../probe +- ../dns +- ../restart +`) + + m, err := th.MakeKustTarget().MakeCustomizedResMap() + if err != nil { + t.Fatalf("Err: %v", err) + } + th.AssertActualEqualsExpected(m, expectedPatchedDeployment) +} + +// Identical test. Validate that ordering of resources as no effect. +func TestIssue1251_CompositeDiamond_ProbeDnsRestart(t *testing.T) { + th := kusttest_test.NewKustTestHarness(t, "/app/composite") + writeDeploymentBaseNoPatch(th) + writeProbeOverlay(th) + writeDNSOverlay(th) + writeRestartOverlay(th) + + th.WriteK("/app/composite", ` +resources: +- ../probe +- ../restart +- ../dns +`) + + m, err := th.MakeKustTarget().MakeCustomizedResMap() + if err != nil { + t.Fatalf("Err: %v", err) + } + th.AssertActualEqualsExpected(m, expectedPatchedDeployment) +} + // This test reuses some methods from TestIssue1251_CompositeDiamond, // but overwrites the kustomization files in the overlays. func TestIssue1251_Patches_Overlayed(t *testing.T) { diff --git a/pkg/target/diamonds_test.go b/pkg/target/diamonds_test.go index be675536547..4ab821f45d1 100644 --- a/pkg/target/diamonds_test.go +++ b/pkg/target/diamonds_test.go @@ -222,3 +222,244 @@ metadata: name: prod-t-federation `) } + +// This example demonstrate a simple sharing +// of a configmap and variables between +// component1 and component2 before being +// aggregated into myapp +// +// myapp +// / | \ +// component1 | component2 +// \ | / +// common +// + +type diamonImportTest struct{} + +func (ut *diamonImportTest) writeKustCommon(th *kusttest_test.KustTestHarness) { + th.WriteK("/diamondimport/common/", ` +resources: +- configmap.yaml + +vars: +- name: ConfigMap.global.data.user + objref: + apiVersion: v1 + kind: ConfigMap + name: global + fieldref: + fieldpath: data.user +`) +} +func (ut *diamonImportTest) writeKustComponent2(th *kusttest_test.KustTestHarness) { + th.WriteK("/diamondimport/component2/", ` +resources: +- ../common +- deployment.yaml +`) +} +func (ut *diamonImportTest) writeKustComponent1(th *kusttest_test.KustTestHarness) { + th.WriteK("/diamondimport/component1/", ` +resources: +- ../common +- deployment.yaml +`) +} +func (ut *diamonImportTest) writeKustMyApp(th *kusttest_test.KustTestHarness) { + th.WriteK("/diamondimport/myapp/", ` +resources: +- ../common +- ../component1 +- ../component2 +`) +} +func (ut *diamonImportTest) writeCommonConfigMap(th *kusttest_test.KustTestHarness) { + th.WriteF("/diamondimport/common/configmap.yaml", ` +apiVersion: v1 +kind: ConfigMap +metadata: + name: global +data: + settings: | + database: mydb + port: 3000 + user: myuser +`) +} +func (ut *diamonImportTest) writeComponent2(th *kusttest_test.KustTestHarness) { + th.WriteF("/diamondimport/component2/deployment.yaml", ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: component2 + labels: + app: component2 +spec: + replicas: 1 + selector: + matchLabels: + app: component2 + template: + metadata: + labels: + app: component2 + spec: + containers: + - name: component2 + image: k8s.gcr.io/busybox + env: + - name: APP_USER + value: $(ConfigMap.global.data.user) + command: [ "/bin/sh", "-c", "cat /etc/config/component2 && sleep 60" ] + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + name: global + items: + - key: settings + path: component2 +`) +} +func (ut *diamonImportTest) writeComponent1(th *kusttest_test.KustTestHarness) { + th.WriteF("/diamondimport/component1/deployment.yaml", ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: component1 + labels: + app: component1 +spec: + replicas: 1 + selector: + matchLabels: + app: component1 + template: + metadata: + labels: + app: component1 + spec: + containers: + - name: component1 + image: k8s.gcr.io/busybox + env: + - name: APP_USER + value: $(ConfigMap.global.data.user) + command: [ "/bin/sh", "-c", "cat /etc/config/component1 && sleep 60" ] + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + name: global + items: + - key: settings + path: component1 +`) +} +func TestSimpleDiamondImport(t *testing.T) { + ut := &diamonImportTest{} + th := kusttest_test.NewKustTestHarness(t, "/diamondimport/myapp") + ut.writeKustCommon(th) + ut.writeKustComponent1(th) + ut.writeKustComponent2(th) + ut.writeKustMyApp(th) + ut.writeCommonConfigMap(th) + ut.writeComponent1(th) + ut.writeComponent2(th) + m, err := th.MakeKustTarget().MakeCustomizedResMap() + if err != nil { + // Error before this Resource.Append fix. + // may not add resource with an already registered id: ~G_v1_ConfigMap|~X|global + t.Fatalf("Err: %v", err) + } + th.AssertActualEqualsExpected(m, ` +apiVersion: v1 +data: + settings: | + database: mydb + port: 3000 + user: myuser +kind: ConfigMap +metadata: + name: global +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: component1 + name: component1 +spec: + replicas: 1 + selector: + matchLabels: + app: component1 + template: + metadata: + labels: + app: component1 + spec: + containers: + - command: + - /bin/sh + - -c + - cat /etc/config/component1 && sleep 60 + env: + - name: APP_USER + value: myuser + image: k8s.gcr.io/busybox + name: component1 + volumeMounts: + - mountPath: /etc/config + name: config-volume + volumes: + - configMap: + items: + - key: settings + path: component1 + name: global + name: config-volume +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: component2 + name: component2 +spec: + replicas: 1 + selector: + matchLabels: + app: component2 + template: + metadata: + labels: + app: component2 + spec: + containers: + - command: + - /bin/sh + - -c + - cat /etc/config/component2 && sleep 60 + env: + - name: APP_USER + value: myuser + image: k8s.gcr.io/busybox + name: component2 + volumeMounts: + - mountPath: /etc/config + name: config-volume + volumes: + - configMap: + items: + - key: settings + path: component2 + name: global + name: config-volume +`) +} diff --git a/pkg/target/variableref_test.go b/pkg/target/variableref_test.go index e4ba55aa4b1..9e9c54ccc53 100644 --- a/pkg/target/variableref_test.go +++ b/pkg/target/variableref_test.go @@ -295,6 +295,140 @@ spec: `) } +func TestVarUnresolvedUp(t *testing.T) { + th := kusttest_test.NewKustTestHarness(t, "/app/overlay") + th.WriteK("/app/base", ` +vars: +- name: POD_NAME1 + objref: + apiVersion: v1 + kind: Pod + name: kelley + fieldref: + fieldpath: metadata.name +- name: POD_NAME2 + objref: + apiVersion: v1 + kind: Pod + name: grimaldi + fieldref: + fieldpath: metadata.name +`) + + th.WriteK("/app/overlay", ` +resources: +- pod1.yaml +- pod2.yaml +- composite.yaml +- ../base +`) + + th.WriteF("/app/overlay/pod1.yaml", ` +apiVersion: v1 +kind: Pod +metadata: + name: kelley +spec: + containers: + - name: smile + image: smile + command: + - echo + - "$(POD_NAME1)" + env: + - name: FOO + value: "$(POD_NAME1)" +`) + th.WriteF("/app/overlay/pod2.yaml", ` +apiVersion: v1 +kind: Pod +metadata: + name: grimaldi +spec: + containers: + - name: dance + image: dance + command: + - echo + - "$(POD_NAME2)" + env: + - name: FOO + value: "$(POD_NAME2)" +`) + th.WriteF("/app/overlay/composite.yaml", ` +apiVersion: v1 +kind: Pod +metadata: + name: circus +spec: + containers: + - name: ring + image: ring + command: + - echo + - "$(POD_NAME1)" + - "$(POD_NAME2)" + env: + - name: P1 + value: "$(POD_NAME1)" + - name: P2 + value: "$(POD_NAME2)" +`) + m, err := th.MakeKustTarget().MakeCustomizedResMap() + if err != nil { + t.Fatalf("Err: %v", err) + } + th.AssertActualEqualsExpected(m, ` +apiVersion: v1 +kind: Pod +metadata: + name: kelley +spec: + containers: + - command: + - echo + - kelley + env: + - name: FOO + value: kelley + image: smile + name: smile +--- +apiVersion: v1 +kind: Pod +metadata: + name: grimaldi +spec: + containers: + - command: + - echo + - grimaldi + env: + - name: FOO + value: grimaldi + image: dance + name: dance +--- +apiVersion: v1 +kind: Pod +metadata: + name: circus +spec: + containers: + - command: + - echo + - kelley + - grimaldi + env: + - name: P1 + value: kelley + - name: P2 + value: grimaldi + image: ring + name: ring +`) +} + // Not so much a bug as a desire for local variables // with less than global scope. Currently all variables // are global. So if a base with a variable is included @@ -372,7 +506,7 @@ spec: if err == nil { t.Fatalf("should have an error") } - if !strings.Contains(err.Error(), "var 'POD_NAME' already encountered") { + if !strings.Contains(err.Error(), "(unable to disambiguate)") { t.Fatalf("unexpected err: %v", err) } }