From 47a04f2648173b42c8c5296e24389c16ccd682fb Mon Sep 17 00:00:00 2001 From: Jeffrey Regan Date: Tue, 18 Dec 2018 09:50:08 -0800 Subject: [PATCH] More fully in-memory integration tests. --- .../base/kustomization.yaml | 7 - .../base/rolebinding.yaml | 11 -- .../base/serviceaccount.yaml | 4 - .../combined/kustomization.yaml | 5 - .../overlays/a/kustomization.yaml | 10 -- .../overlays/a/serviceaccount.yaml | 4 - .../overlays/b/kustomization.yaml | 7 - .../testcase-multibases-conflict/test.yaml | 4 - .../base/kustomization.yaml | 7 - .../base/rolebinding.yaml | 11 -- .../base/serviceaccount.yaml | 4 - .../combined/kustomization.yaml | 5 - .../expected.yaml | 33 ---- .../overlays/a/kustomization.yaml | 7 - .../overlays/b/kustomization.yaml | 7 - .../testcase-multibases-nonconflict/test.yaml | 4 - ...r_test.go => baseandoverlaymedium_test.go} | 124 ++++++++++++-- pkg/target/kusttarget_test.go | 97 +++-------- pkg/target/resourceconflict_test.go | 153 ++++++++++++++++++ pkg/target/utils_for_test.go | 131 +++++++++++++++ 20 files changed, 422 insertions(+), 213 deletions(-) delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/base/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/base/rolebinding.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/base/serviceaccount.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/combined/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/serviceaccount.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/overlays/b/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-conflict/test.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/base/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/base/rolebinding.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/base/serviceaccount.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/combined/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/expected.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/a/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/b/kustomization.yaml delete mode 100644 pkg/commands/build/testdata/testcase-multibases-nonconflict/test.yaml rename pkg/target/{bigger_test.go => baseandoverlaymedium_test.go} (67%) create mode 100644 pkg/target/resourceconflict_test.go create mode 100644 pkg/target/utils_for_test.go diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/base/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/base/kustomization.yaml deleted file mode 100644 index c2659b3ba..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/base/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Kustomization -resources: -- serviceaccount.yaml -- rolebinding.yaml -namePrefix: base- -nameSuffix: -suffix diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/base/rolebinding.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/base/rolebinding.yaml deleted file mode 100644 index c74e189ce..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/base/rolebinding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: role -subjects: -- kind: ServiceAccount - name: serviceaccount diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/base/serviceaccount.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/base/serviceaccount.yaml deleted file mode 100644 index f1fff56b2..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/base/serviceaccount.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: serviceaccount diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/combined/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/combined/kustomization.yaml deleted file mode 100644 index baab2a316..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/combined/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: Kustomization -bases: -- ../overlays/a -- ../overlays/b diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/kustomization.yaml deleted file mode 100644 index 30ea303c2..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Kustomization -bases: -- ../../base/ - -namePrefix: a- -nameSuffix: -suffixA - -resources: -- serviceaccount.yaml diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/serviceaccount.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/serviceaccount.yaml deleted file mode 100644 index f1fff56b2..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/a/serviceaccount.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: serviceaccount diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/b/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/b/kustomization.yaml deleted file mode 100644 index fe87bd2fa..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/overlays/b/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Kustomization -bases: -- ../../base/ - -namePrefix: b- -nameSuffix: -suffixB diff --git a/pkg/commands/build/testdata/testcase-multibases-conflict/test.yaml b/pkg/commands/build/testdata/testcase-multibases-conflict/test.yaml deleted file mode 100644 index 334c5f957..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-conflict/test.yaml +++ /dev/null @@ -1,4 +0,0 @@ -description: multibases with name reference -args: [] -filename: testdata/testcase-multibases-conflict/combined -expectedError: Multiple matches for name ~G_v1_ServiceAccount diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/kustomization.yaml deleted file mode 100644 index c2659b3ba..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Kustomization -resources: -- serviceaccount.yaml -- rolebinding.yaml -namePrefix: base- -nameSuffix: -suffix diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/rolebinding.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/rolebinding.yaml deleted file mode 100644 index c74e189ce..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/rolebinding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: role -subjects: -- kind: ServiceAccount - name: serviceaccount diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/serviceaccount.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/serviceaccount.yaml deleted file mode 100644 index f1fff56b2..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/base/serviceaccount.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: serviceaccount diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/combined/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/combined/kustomization.yaml deleted file mode 100644 index baab2a316..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/combined/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: Kustomization -bases: -- ../overlays/a -- ../overlays/b diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/expected.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/expected.yaml deleted file mode 100644 index f1df1b22c..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/expected.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: a-base-serviceaccount-suffix-suffixA ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: b-base-serviceaccount-suffix-suffixB ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: a-base-rolebinding-suffix-suffixA -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: role -subjects: -- kind: ServiceAccount - name: a-base-serviceaccount-suffix-suffixA ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: b-base-rolebinding-suffix-suffixB -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: role -subjects: -- kind: ServiceAccount - name: b-base-serviceaccount-suffix-suffixB diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/a/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/a/kustomization.yaml deleted file mode 100644 index 29909bf3f..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/a/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Kustomization -bases: -- ../../base/ - -namePrefix: a- -nameSuffix: -suffixA diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/b/kustomization.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/b/kustomization.yaml deleted file mode 100644 index fe87bd2fa..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/overlays/b/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Kustomization -bases: -- ../../base/ - -namePrefix: b- -nameSuffix: -suffixB diff --git a/pkg/commands/build/testdata/testcase-multibases-nonconflict/test.yaml b/pkg/commands/build/testdata/testcase-multibases-nonconflict/test.yaml deleted file mode 100644 index cbbcc93ba..000000000 --- a/pkg/commands/build/testdata/testcase-multibases-nonconflict/test.yaml +++ /dev/null @@ -1,4 +0,0 @@ -description: multibases with name reference -args: [] -filename: testdata/testcase-multibases-nonconflict/combined -expectedStdout: testdata/testcase-multibases-nonconflict/expected.yaml diff --git a/pkg/target/bigger_test.go b/pkg/target/baseandoverlaymedium_test.go similarity index 67% rename from pkg/target/bigger_test.go rename to pkg/target/baseandoverlaymedium_test.go index 728b21c7d..8469a2f53 100644 --- a/pkg/target/bigger_test.go +++ b/pkg/target/baseandoverlaymedium_test.go @@ -84,7 +84,6 @@ spec: ports: - containerPort: 80 `) - } func TestBigBase(t *testing.T) { @@ -101,7 +100,7 @@ func TestBigBase(t *testing.T) { if err != nil { t.Fatalf("Err: %v", err) } - expected := `apiVersion: v1 + assertExpectedEqualsActual(t, s, `apiVersion: v1 kind: Service metadata: annotations: @@ -147,11 +146,7 @@ spec: name: nginx ports: - containerPort: 80 -` - if string(s) != expected { - t.Fatalf("Actual results:\n%s\nnot equal to expected:\n%s\n", - s, expected) - } +`) } func TestBigOverlay(t *testing.T) { @@ -224,7 +219,118 @@ spec: if err != nil { t.Fatalf("Err: %v", err) } - if m == nil { - t.Fatalf("Empty map.") + s, err := m.EncodeAsYaml() + if err != nil { + t.Fatalf("Unexpected err: %v", err) } + assertExpectedEqualsActual(t, s, `apiVersion: v1 +data: + app-init.ini: |2 + + FOO=bar + BAR=baz +kind: ConfigMap +metadata: + annotations: + note: This is a test annotation + labels: + app: mungebot + org: kubernetes + repo: test-infra + name: test-infra-app-config-fd62mfc87h +--- +apiVersion: v1 +data: + DB_PASSWORD: somepw + DB_USERNAME: admin +kind: ConfigMap +metadata: + annotations: + note: This is a test annotation + labels: + app: mungebot + org: kubernetes + repo: test-infra + name: test-infra-app-env-bh449c299k +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + baseAnno: This is a base annotation + note: This is a test annotation + labels: + app: mungebot + foo: bar + org: kubernetes + repo: test-infra + name: test-infra-baseprefix-mungebot-service +spec: + ports: + - port: 7002 + selector: + app: mungebot + foo: bar + org: kubernetes + repo: test-infra +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + annotations: + baseAnno: This is a base annotation + note: This is a test annotation + labels: + app: mungebot + foo: bar + org: kubernetes + repo: test-infra + name: test-infra-baseprefix-mungebot +spec: + replicas: 2 + selector: + matchLabels: + app: mungebot + foo: bar + org: kubernetes + repo: test-infra + template: + metadata: + annotations: + baseAnno: This is a base annotation + note: This is a test annotation + labels: + app: mungebot + foo: bar + org: kubernetes + repo: test-infra + spec: + containers: + - env: + - name: FOO + valueFrom: + configMapKeyRef: + key: somekey + name: test-infra-app-env-bh449c299k + - name: foo + value: bar + image: nginx:1.8.0 + name: nginx + ports: + - containerPort: 80 + - envFrom: + - configMapRef: + name: someConfigMap + - configMapRef: + name: test-infra-app-env-bh449c299k + image: busybox + name: busybox + volumeMounts: + - mountPath: /tmp/env + name: app-env + volumes: + - configMap: + name: test-infra-app-env-bh449c299k + name: app-env +`) } diff --git a/pkg/target/kusttarget_test.go b/pkg/target/kusttarget_test.go index e121b4094..c80c60815 100644 --- a/pkg/target/kusttarget_test.go +++ b/pkg/target/kusttarget_test.go @@ -18,16 +18,12 @@ package target import ( "encoding/base64" - "path/filepath" "reflect" "sort" "strings" "testing" "sigs.k8s.io/kustomize/k8sdeps/kunstruct" - "sigs.k8s.io/kustomize/k8sdeps/transformer" - "sigs.k8s.io/kustomize/pkg/constants" - "sigs.k8s.io/kustomize/pkg/fs" "sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/internal/loadertest" @@ -98,53 +94,24 @@ metadata: var rf = resmap.NewFactory(resource.NewFactory( kunstruct.NewKunstructuredFactoryImpl())) -func makeKustTarget(t *testing.T, l ifc.Loader) *KustTarget { - // Warning: the following filesystem - a fake - must be rooted at /. - // This fs root is used as the working directory for the shell spawned by - // the secretgenerator, and has nothing to do with the filesystem used - // to load relative paths from the fake filesystem. - // This trick only works for secret generator commands that don't actually - // try to read the file system, because these tests don't write to the - // real "/" directory. See use of exec package in the secretfactory. - fakeFs := fs.MakeFakeFS() - fakeFs.Mkdir("/") - kt, err := NewKustTarget( - l, fakeFs, rf, transformer.NewFactoryImpl()) - if err != nil { - t.Fatalf("Unexpected construction error %v", err) - } - return kt -} - -func makeLoader1(t *testing.T) ifc.Loader { - ldr := loadertest.NewFakeLoader("/testpath") - err := ldr.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1)) - if err != nil { - t.Fatalf("Failed to setup fake ldr.") - } - err = ldr.AddFile("/testpath/deployment.yaml", []byte(deploymentContent)) - if err != nil { - t.Fatalf("Failed to setup fake ldr.") - } - err = ldr.AddFile("/testpath/namespace.yaml", []byte(namespaceContent)) - if err != nil { - t.Fatalf("Failed to setup fake ldr.") - } - err = ldr.AddFile("/testpath/jsonpatch.json", []byte(jsonpatchContent)) - if err != nil { - t.Fatalf("Failed to setup fake ldr.") - } - return ldr -} - var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"} var secret = gvk.Gvk{Version: "v1", Kind: "Secret"} var ns = gvk.Gvk{Version: "v1", Kind: "Namespace"} +func makeALoader(t *testing.T) ifc.Loader { + ldr := loadertest.NewFakeLoader("/testpath") + writeK(t, ldr, "/testpath/", kustomizationContent1) + writeF(t, ldr, "/testpath/deployment.yaml", deploymentContent) + writeF(t, ldr, "/testpath/namespace.yaml", namespaceContent) + writeF(t, ldr, "/testpath/jsonpatch.json", jsonpatchContent) + return ldr +} + func TestResources1(t *testing.T) { expected := resmap.ResMap{ - resid.NewResIdWithPrefixSuffixNamespace(deploy, "dply1", "foo-", "-bar", "ns1"): rf.RF().FromMap( + resid.NewResIdWithPrefixSuffixNamespace( + deploy, "dply1", "foo-", "-bar", "ns1"): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -177,7 +144,8 @@ func TestResources1(t *testing.T) { }, }, }), - resid.NewResIdWithPrefixSuffixNamespace(cmap, "literalConfigMap", "foo-", "-bar", "ns1"): rf.RF().FromMap( + resid.NewResIdWithPrefixSuffixNamespace( + cmap, "literalConfigMap", "foo-", "-bar", "ns1"): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -196,7 +164,8 @@ func TestResources1(t *testing.T) { "DB_PASSWORD": "somepw", }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResIdWithPrefixSuffixNamespace(secret, "secret", "foo-", "-bar", "ns1"): rf.RF().FromMap( + resid.NewResIdWithPrefixSuffixNamespace( + secret, "secret", "foo-", "-bar", "ns1"): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -216,7 +185,8 @@ func TestResources1(t *testing.T) { "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResIdWithPrefixSuffixNamespace(ns, "ns1", "foo-", "-bar", ""): rf.RF().FromMap( + resid.NewResIdWithPrefixSuffixNamespace( + ns, "ns1", "foo-", "-bar", ""): rf.RF().FromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -232,7 +202,7 @@ func TestResources1(t *testing.T) { }), } actual, err := makeKustTarget( - t, makeLoader1(t)).MakeCustomizedResMap() + t, makeALoader(t)).MakeCustomizedResMap() if err != nil { t.Fatalf("unexpected Resources error %v", err) } @@ -245,11 +215,8 @@ func TestResources1(t *testing.T) { func TestResourceNotFound(t *testing.T) { l := loadertest.NewFakeLoader("/testpath") - err := l.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1)) - if err != nil { - t.Fatalf("Failed to setup fake ldr.") - } - _, err = makeKustTarget(t, l).MakeCustomizedResMap() + writeK(t, l, "/testpath", kustomizationContent1) + _, err := makeKustTarget(t, l).MakeCustomizedResMap() if err == nil { t.Fatalf("Didn't get the expected error for an unknown resource") } @@ -260,11 +227,8 @@ func TestResourceNotFound(t *testing.T) { func TestSecretTimeout(t *testing.T) { l := loadertest.NewFakeLoader("/testpath") - err := l.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent2)) - if err != nil { - t.Fatalf("Failed to setup fake ldr.") - } - _, err = makeKustTarget(t, l).MakeCustomizedResMap() + writeK(t, l, "/testpath", kustomizationContent2) + _, err := makeKustTarget(t, l).MakeCustomizedResMap() if err == nil { t.Fatalf("Didn't get the expected error for an unknown resource") } @@ -283,7 +247,7 @@ func findSecret(m resmap.ResMap) *resource.Resource { } func TestDisableNameSuffixHash(t *testing.T) { - kt := makeKustTarget(t, makeLoader1(t)) + kt := makeKustTarget(t, makeALoader(t)) m, err := kt.MakeCustomizedResMap() if err != nil { @@ -312,21 +276,6 @@ func TestDisableNameSuffixHash(t *testing.T) { } } -func writeF(t *testing.T, ldr loadertest.FakeLoader, dir string, content string) { - err := ldr.AddFile(dir, []byte(content)) - if err != nil { - t.Fatalf("failed write to %s; %v", dir, err) - } -} - -func writeK( - t *testing.T, ldr loadertest.FakeLoader, dir string, content string) { - writeF(t, ldr, filepath.Join(dir, constants.KustomizationFileName), ` -apiVersion: v1 -kind: Kustomization -`+content) -} - func TestIssue596AllowDirectoriesThatAreSubstringsOfEachOther(t *testing.T) { ldr := loadertest.NewFakeLoader( "/app/overlays/aws-sandbox2.us-east-1") diff --git a/pkg/target/resourceconflict_test.go b/pkg/target/resourceconflict_test.go new file mode 100644 index 000000000..4770366df --- /dev/null +++ b/pkg/target/resourceconflict_test.go @@ -0,0 +1,153 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package target + +import ( + "strings" + "testing" + + "sigs.k8s.io/kustomize/pkg/internal/loadertest" +) + +func writeCombinedOverlays(t *testing.T, ldr loadertest.FakeLoader) { + // Base + writeK(t, ldr, "/app/base", ` +resources: +- serviceaccount.yaml +- rolebinding.yaml +namePrefix: base- +nameSuffix: -suffix +`) + writeF(t, ldr, "/app/base/rolebinding.yaml", ` +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: role +subjects: +- kind: ServiceAccount + name: serviceaccount +`) + writeF(t, ldr, "/app/base/serviceaccount.yaml", ` +apiVersion: v1 +kind: ServiceAccount +metadata: + name: serviceaccount +`) + + // Mid-level overlays + writeK(t, ldr, "/app/overlays/a", ` +bases: +- ../../base +namePrefix: a- +nameSuffix: -suffixA +`) + writeK(t, ldr, "/app/overlays/b", ` +bases: +- ../../base +namePrefix: b- +nameSuffix: -suffixB +`) + + // Top overlay, combining the mid-level overlays + writeK(t, ldr, "/app/combined", ` +bases: +- ../overlays/a +- ../overlays/b +`) +} + +func TestMultibasesNoConflict(t *testing.T) { + ldr := loadertest.NewFakeLoader("/app/combined") + writeCombinedOverlays(t, ldr) + m, err := makeKustTarget(t, ldr).MakeCustomizedResMap() + if err != nil { + t.Fatalf("Unexpected err: %v", err) + } + s, err := m.EncodeAsYaml() + if err != nil { + t.Fatalf("Unexpected err: %v", err) + } + assertExpectedEqualsActual(t, s, `apiVersion: v1 +kind: ServiceAccount +metadata: + name: a-base-serviceaccount-suffix-suffixA +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: b-base-serviceaccount-suffix-suffixB +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: a-base-rolebinding-suffix-suffixA +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: role +subjects: +- kind: ServiceAccount + name: a-base-serviceaccount-suffix-suffixA +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: b-base-rolebinding-suffix-suffixB +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: role +subjects: +- kind: ServiceAccount + name: b-base-serviceaccount-suffix-suffixB +`) +} + +func TestMultibasesWithConflict(t *testing.T) { + ldr := loadertest.NewFakeLoader("/app/combined") + writeCombinedOverlays(t, ldr) + + writeK(t, ldr, "/app/overlays/a", ` +bases: +- ../../base +namePrefix: a- +nameSuffix: -suffixA +resources: +- serviceaccount.yaml +`) + // Expect an error because this resource in the overlay + // matches a resource in the base. + writeF(t, ldr, "/app/overlays/a/serviceaccount.yaml", ` +apiVersion: v1 +kind: ServiceAccount +metadata: + name: serviceaccount +`) + + _, err := makeKustTarget(t, ldr).MakeCustomizedResMap() + if err == nil { + t.Fatalf("Expected resource conflict.") + } + if !strings.Contains( + err.Error(), "Multiple matches for name ~G_v1_ServiceAccount") { + t.Fatalf("Unexpected err: %v", err) + } +} diff --git a/pkg/target/utils_for_test.go b/pkg/target/utils_for_test.go new file mode 100644 index 000000000..c799f3ad5 --- /dev/null +++ b/pkg/target/utils_for_test.go @@ -0,0 +1,131 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package target + +// A collection of utilities used in target tests. + +import ( + "fmt" + "path/filepath" + "strings" + "testing" + + "sigs.k8s.io/kustomize/k8sdeps/transformer" + "sigs.k8s.io/kustomize/pkg/constants" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/internal/loadertest" +) + +func makeKustTarget(t *testing.T, l ifc.Loader) *KustTarget { + // Warning: the following filesystem - a fake - must be rooted at /. + // This fs root is used as the working directory for the shell spawned by + // the secretgenerator, and has nothing to do with the filesystem used + // to load relative paths from the fake filesystem. + // This trick only works for secret generator commands that don't actually + // try to read the file system, because these tests don't write to the + // real "/" directory. See use of exec package in the secretfactory. + fakeFs := fs.MakeFakeFS() + fakeFs.Mkdir("/") + kt, err := NewKustTarget( + l, fakeFs, rf, transformer.NewFactoryImpl()) + if err != nil { + t.Fatalf("Unexpected construction error %v", err) + } + return kt +} + +func writeF( + t *testing.T, ldr loadertest.FakeLoader, dir string, content string) { + err := ldr.AddFile(dir, []byte(content)) + if err != nil { + t.Fatalf("failed write to %s; %v", dir, err) + } +} + +func writeK( + t *testing.T, ldr loadertest.FakeLoader, dir string, content string) { + writeF(t, ldr, filepath.Join(dir, constants.KustomizationFileName), ` +apiVersion: v1 +kind: Kustomization +`+content) +} + +func tabToSpace(input string) string { + var result []string + for _, i := range input { + if i == 9 { + result = append(result, " ") + } else { + result = append(result, string(i)) + } + } + return strings.Join(result, "") +} + +func convertToArray(x string) ([]string, int) { + a := strings.Split(strings.TrimSuffix(x, "\n"), "\n") + maxLen := 0 + for i, v := range a { + z := tabToSpace(v) + if len(z) > maxLen { + maxLen = len(z) + } + a[i] = z + } + return a, maxLen +} + +func hint(a, b string) string { + if a == b { + return " " + } + return "X" +} + +// Pretty printing of file differences. +func assertExpectedEqualsActual(t *testing.T, actual []byte, expected string) { + if expected == string(actual) { + return + } + sE, maxLen := convertToArray(expected) + sA, _ := convertToArray(string(actual)) + format := fmt.Sprintf("%%s %%-%ds %%s\n", maxLen+4) + + limit := 0 + if len(sE) < len(sA) { + limit = len(sE) + } else { + limit = len(sA) + } + + fmt.Printf(format, " ", "EXPECTED", "ACTUAL") + fmt.Printf(format, " ", "--------", "------") + for i := 0; i < limit; i++ { + fmt.Printf(format, hint(sE[i], sA[i]), sE[i], sA[i]) + } + if len(sE) < len(sA) { + for i := len(sE); i < len(sA); i++ { + fmt.Printf(format, "X", "", sA[i]) + } + } else { + for i := len(sA); i < len(sE); i++ { + fmt.Printf(format, "X", sE[i], "") + } + } + t.Fatalf("Expected not equal to actual") +}