Simplify code base.

- In ResMap, drop concept of internal Id to Resource
   map.  The ResMap is now (just) a list, allowing only
   very particular edits.

 - Resources should now be maintained in the order
   loaded.  A later PR can adjust tests to remove the
   internal legacy sorting, and confirm order-out is
   predictable from order-in.  The PR would suppress
   the sort in tests, and reorder the output to make
   all tests pass again, and confirm that the new order
   matched depth-first input traversal.  The FromMap
   fixture function was removed from all test inputs to
   establish a predictable input order.

 - Resources now have two 'Ids', OriginalId and
   CurrentId.  The former is fixed as
   GVK-name-namespace at load time, the latter changes
   during transformations.  The latter can be used to
   narrow name references when the former maps to
   multiple resources.  We allow bases to be loaded
   more than once in a build (a diamond pattern), so
   the OriginalId is not unique across the resources
   set.  The CurrentId is (and must be) unique, but is
   constantly mutating.  Failing to make this
   distinction clear, and attempting to maintain a
   mapping from a single mutating Id to a resource was
   making the code too complex.

 - Drop prefix/suffix from ResId - the ResId is now
   immutable.  A later PR can remove the distinction
   with ItemId.

 - This PR increases coverage of ResMap is since this
   is a large refactor.  Higher level tests didn't need
   much change outside reordering of results at the
   resource level.
This commit is contained in:
Jeffrey Regan
2019-06-12 11:29:57 -07:00
parent 624aa5290e
commit 3a01a63a01
75 changed files with 2481 additions and 2962 deletions

View File

@@ -25,9 +25,7 @@ import (
"sigs.k8s.io/kustomize/pkg/plugins"
)
// TODO(monopole): Make prefixsuffixtransformer changes
// needed to enable this test.
func disabledTestOrderPreserved(t *testing.T) {
func TestOrderPreserved(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th.WriteK("/app/base", `
namePrefix: b-
@@ -86,8 +84,36 @@ metadata:
t.Fatalf("Err: %v", err)
}
th.AssertActualEqualsExpectedNoSort(m, `
TBD
./tr `)
apiVersion: v1
kind: Namespace
metadata:
name: p-b-myNs
---
apiVersion: v1
kind: Role
metadata:
name: p-b-myRole
---
apiVersion: v1
kind: Service
metadata:
name: p-b-myService
---
apiVersion: v1
kind: Deployment
metadata:
name: p-b-myDep
---
apiVersion: v1
kind: Service
metadata:
name: p-myService2
---
apiVersion: v1
kind: Namespace
metadata:
name: p-myNs2
`)
}
func TestBaseInResourceList(t *testing.T) {

View File

@@ -61,7 +61,7 @@ kind: Secret
metadata:
labels:
app: release-name-minecraft
chart: minecraft-1.0.1
chart: minecraft-1.0.3
heritage: Tiller
release: release-name
name: LOOOOOOOONG-release-name-minecraft
@@ -72,7 +72,7 @@ kind: Service
metadata:
labels:
app: release-name-minecraft
chart: minecraft-1.0.1
chart: minecraft-1.0.3
heritage: Tiller
release: release-name
name: LOOOOOOOONG-release-name-minecraft
@@ -93,7 +93,7 @@ metadata:
volume.alpha.kubernetes.io/storage-class: default
labels:
app: release-name-minecraft
chart: minecraft-1.0.1
chart: minecraft-1.0.3
heritage: Tiller
release: release-name
name: LOOOOOOOONG-release-name-minecraft-datadir

View File

@@ -312,6 +312,15 @@ spec:
location: SE
---
kind: Gorilla
metadata:
labels:
movie: planetOfTheApes
name: o-ursus
spec:
diet: heston
location: Arizona
---
kind: Gorilla
metadata:
labels:
app: myApp
@@ -320,14 +329,5 @@ metadata:
spec:
diet: bambooshoots
location: SW
---
kind: Gorilla
metadata:
labels:
movie: planetOfTheApes
name: o-ursus
spec:
diet: heston
location: Arizona
`)
}

View File

@@ -374,6 +374,16 @@ secretGenerator:
}
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
team: override-foo
name: staging-configmap-in-overlay-k7cbc75tg8
---
apiVersion: v1
data:
foo: override-bar
kind: ConfigMap
@@ -388,16 +398,6 @@ metadata:
name: staging-team-foo-configmap-in-base-gh9d7t85gb
---
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
team: override-foo
name: staging-configmap-in-overlay-k7cbc75tg8
---
apiVersion: v1
data:
password: c29tZXB3
proxy: aGFwcm94eQ==

View File

@@ -14,7 +14,6 @@ import (
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/kusttest"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
. "sigs.k8s.io/kustomize/pkg/target"
@@ -80,64 +79,53 @@ func TestResources(t *testing.T) {
th.WriteF("/whatever/namespace.yaml", namespaceContent)
th.WriteF("/whatever/jsonpatch.json", jsonpatchContent)
expected := resmap.New()
expected.AppendWithId(
resid.NewResIdWithPrefixSuffixNamespace(
gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"},
"dply1", "foo-", "-bar", "ns1"), th.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-dply1-bar",
"namespace": "ns1",
"labels": map[string]interface{}{
resources := []*resource.Resource{
th.RF().FromMapWithName("dply1", map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-dply1-bar",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"spec": map[string]interface{}{
"replica": "3",
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"spec": map[string]interface{}{
"replica": "3",
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"labels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"labels": map[string]interface{}{
"app": "nginx",
},
},
},
},
}))
expected.AppendWithId(
resid.NewResIdWithPrefixSuffixNamespace(
gvk.Gvk{Version: "v1", Kind: "Namespace"},
"ns1", "foo-", "-bar", ""), th.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "foo-ns1-bar",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
}),
th.RF().FromMapWithName("ns1", map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "foo-ns1-bar",
"labels": map[string]interface{}{
"app": "nginx",
},
}))
expected.AppendWithId(
resid.NewResIdWithPrefixSuffixNamespace(
gvk.Gvk{Version: "v1", Kind: "ConfigMap"},
"literalConfigMap", "foo-", "-bar", "ns1"), th.FromMap(
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
}),
th.RF().FromMapWithName("literalConfigMap",
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -155,11 +143,8 @@ func TestResources(t *testing.T) {
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}))
expected.AppendWithId(
resid.NewResIdWithPrefixSuffixNamespace(
gvk.Gvk{Version: "v1", Kind: "Secret"},
"secret", "foo-", "-bar", "ns1"), th.FromMap(
}),
th.RF().FromMapWithName("secret",
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
@@ -178,13 +163,22 @@ func TestResources(t *testing.T) {
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}))
}),
}
expected := resmap.New()
for _, r := range resources {
if err := expected.Append(r); err != nil {
t.Fatalf("unexpected error %v", err)
}
}
actual, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}
if err = expected.ErrorIfNotEqualSets(actual); err != nil {
if err = expected.ErrorIfNotEqualLists(actual); err != nil {
t.Fatalf("unexpected inequality: %v", err)
}
}
@@ -215,7 +209,7 @@ func TestResourceNotFound(t *testing.T) {
func findSecret(m resmap.ResMap) *resource.Resource {
for _, r := range m.Resources() {
if r.Id().Gvk().Kind == "Secret" {
if r.OrgId().Kind == "Secret" {
return r
}
}

View File

@@ -149,6 +149,15 @@ spec:
}
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
name: staging-configmap-in-overlay-k7cbc75tg8
---
apiVersion: v1
data:
foo: bar
kind: ConfigMap
@@ -163,15 +172,6 @@ metadata:
name: staging-team-foo-configmap-in-base-g7k6gt2889
---
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
name: staging-configmap-in-overlay-k7cbc75tg8
---
apiVersion: v1
kind: Service
metadata:
annotations:

View File

@@ -10,14 +10,19 @@ import (
"sigs.k8s.io/kustomize/pkg/kusttest"
)
func writeCombinedOverlays(th *kusttest_test.KustTestHarness) {
// Base
func writeBase(th *kusttest_test.KustTestHarness) {
th.WriteK("/app/base", `
resources:
- serviceaccount.yaml
- rolebinding.yaml
namePrefix: base-
nameSuffix: -suffix
namePrefix: pfx-
nameSuffix: -sfx
`)
th.WriteF("/app/base/serviceaccount.yaml", `
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount
`)
th.WriteF("/app/base/rolebinding.yaml", `
apiVersion: rbac.authorization.k8s.io/v1beta1
@@ -32,13 +37,9 @@ subjects:
- kind: ServiceAccount
name: serviceaccount
`)
th.WriteF("/app/base/serviceaccount.yaml", `
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount
`)
}
func writeMidOverlays(th *kusttest_test.KustTestHarness) {
// Mid-level overlays
th.WriteK("/app/overlays/a", `
bases:
@@ -52,7 +53,9 @@ bases:
namePrefix: b-
nameSuffix: -suffixB
`)
}
func writeTopOverlay(th *kusttest_test.KustTestHarness) {
// Top overlay, combining the mid-level overlays
th.WriteK("/app/combined", `
bases:
@@ -61,9 +64,9 @@ bases:
`)
}
func TestMultibasesNoConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/combined")
writeCombinedOverlays(th)
func TestBase(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
writeBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
@@ -72,42 +75,129 @@ func TestMultibasesNoConflict(t *testing.T) {
apiVersion: v1
kind: ServiceAccount
metadata:
name: a-base-serviceaccount-suffix-suffixA
name: pfx-serviceaccount-sfx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: pfx-rolebinding-sfx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: pfx-serviceaccount-sfx
`)
}
func TestMidLevelA(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/a")
writeBase(th)
writeMidOverlays(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
metadata:
name: a-pfx-serviceaccount-sfx-suffixA
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: a-pfx-rolebinding-sfx-suffixA
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: a-pfx-serviceaccount-sfx-suffixA
`)
}
func TestMidLevelB(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/b")
writeBase(th)
writeMidOverlays(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
metadata:
name: b-pfx-serviceaccount-sfx-suffixB
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: b-pfx-rolebinding-sfx-suffixB
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: b-pfx-serviceaccount-sfx-suffixB
`)
}
func TestMultibasesNoConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/combined")
writeBase(th)
writeMidOverlays(th)
writeTopOverlay(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
metadata:
name: a-pfx-serviceaccount-sfx-suffixA
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: b-base-serviceaccount-suffix-suffixB
name: b-pfx-serviceaccount-sfx-suffixB
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: a-base-rolebinding-suffix-suffixA
name: a-pfx-rolebinding-sfx-suffixA
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: a-base-serviceaccount-suffix-suffixA
name: a-pfx-serviceaccount-sfx-suffixA
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: b-base-rolebinding-suffix-suffixB
name: b-pfx-rolebinding-sfx-suffixB
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: b-base-serviceaccount-suffix-suffixB
name: b-pfx-serviceaccount-sfx-suffixB
`)
}
func TestMultibasesWithConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/combined")
writeCombinedOverlays(th)
writeBase(th)
writeMidOverlays(th)
writeTopOverlay(th)
th.WriteK("/app/overlays/a", `
bases:
@@ -131,7 +221,7 @@ metadata:
t.Fatalf("Expected resource conflict.")
}
if !strings.Contains(
err.Error(), "Multiple matches for name ~G_v1_ServiceAccount") {
err.Error(), "multiple matches for ~G_v1_ServiceAccount") {
t.Fatalf("Unexpected err: %v", err)
}
}

View File

@@ -411,10 +411,16 @@ metadata:
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app: cockroachdb
name: dev-base-cockroachdb-public
name: dev-base-cockroachdb
spec:
clusterIP: None
ports:
- name: grpc
port: 26257
@@ -428,16 +434,10 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app: cockroachdb
name: dev-base-cockroachdb
name: dev-base-cockroachdb-public
spec:
clusterIP: None
ports:
- name: grpc
port: 26257