Improve NameReference Test cases

- Add more NameReference Namespace tests
- Address issue when mixing empty/no namespace and default namespace.
- Address ClusterRoleBinding subjects field pointing at multiple namespaces.
This commit is contained in:
Jerome Brette
2019-07-08 01:56:59 -05:00
parent 7998ee7036
commit c4d899f7f3
6 changed files with 418 additions and 48 deletions

View File

@@ -8,6 +8,8 @@ import (
"testing"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/resid"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
"sigs.k8s.io/kustomize/v3/pkg/resource"
@@ -466,6 +468,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
@@ -497,7 +500,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
},
},
}).ResMap(),
expectedErr: "is expected to be string"},
expectedErr: "is expected to be"},
{
resMap: resmaptest_test.NewRmBuilder(t, rf).Add(
map[string]interface{}{
@@ -517,7 +520,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
},
},
}).ResMap(),
expectedErr: "is expected to be either a string or a []interface{}"},
expectedErr: "is expected to be"},
}
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
@@ -590,3 +593,303 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
// utility map to create a deployment object
// with (metadatanamespace, metadataname) as key
// and pointing to "refname" secret and configmap
func deploymentMap(metadatanamespace string, metadataname string,
configmapref string, secretref string) map[string]interface{} {
deployment := map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": metadataname,
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
"env": []interface{}{
map[string]interface{}{
"name": "CM_FOO",
"valueFrom": map[string]interface{}{
"configMapKeyRef": map[string]interface{}{
"name": configmapref,
"key": "somekey",
},
},
},
map[string]interface{}{
"name": "SECRET_FOO",
"valueFrom": map[string]interface{}{
"secretKeyRef": map[string]interface{}{
"name": secretref,
"key": "somekey",
},
},
},
},
},
},
},
},
},
}
if metadatanamespace != "" {
metadata := deployment["metadata"].(map[string]interface{})
metadata["namespace"] = metadatanamespace
}
return deployment
}
// TestNameReferenceNamespace creates configmap, secret, deployment
// serviceAccount and clusterRoleBinding object with the same original
// names (uniquename) in different namespaces and with different current Id.
func TestNameReferenceyNamespace(t *testing.T) {
defaultNs := "default"
ns1 := "ns1"
ns2 := "ns2"
orgname := "uniquename"
prefixedname := "prefix-uniquename"
suffixedname := "uniquename-suffix"
modifiedname := "modifiedname"
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).
// Add ConfigMap with the same org name in noNs, "ns1" and "ns2" namespaces
AddWithName(orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": modifiedname,
}}).
AddWithNsAndName(ns1, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": prefixedname,
"namespace": ns1,
}}).
AddWithNsAndName(ns2, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": suffixedname,
"namespace": ns2,
}}).
// Add Secret with the same org name in noNs, "ns1" and "ns2" namespaces
AddWithNsAndName(defaultNs, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": modifiedname,
"namespace": defaultNs,
}}).
AddWithNsAndName(ns1, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": prefixedname,
"namespace": ns1,
}}).
AddWithNsAndName(ns2, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": suffixedname,
"namespace": ns2,
}}).
// Add Deployment with the same org name in noNs, "ns1" and "ns2" namespaces
AddWithNsAndName(defaultNs, orgname, deploymentMap(defaultNs, modifiedname, modifiedname, modifiedname)).
AddWithNsAndName(ns1, orgname, deploymentMap(ns1, prefixedname, orgname, orgname)).
AddWithNsAndName(ns2, orgname, deploymentMap(ns2, suffixedname, orgname, orgname)).
// Add ServiceAccount with the same org name in noNs, "ns1" and "ns2" namespaces
AddWithName(orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": modifiedname,
}}).
AddWithNsAndName(ns1, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": prefixedname,
"namespace": ns1,
}}).
AddWithNsAndName(ns2, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": suffixedname,
"namespace": ns2,
}}).
// Add a PersisitentVolume to have a clusterwide resources
AddWithName(orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": map[string]interface{}{
"name": modifiedname,
}}).
AddWithName(orgname, map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": modifiedname,
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"persistentvolumes",
},
"resourceNames": []interface{}{
orgname,
},
},
}}).
AddWithName(orgname, map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleBinding",
"metadata": map[string]interface{}{
"name": modifiedname,
},
"roleRef": map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"name": orgname,
},
"subjects": []interface{}{
map[string]interface{}{
"kind": "ServiceAccount",
"name": orgname,
"namespace": defaultNs,
},
map[string]interface{}{
"kind": "ServiceAccount",
"name": orgname,
"namespace": ns1,
},
map[string]interface{}{
"kind": "ServiceAccount",
"name": orgname,
"namespace": ns2,
},
}}).ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
ReplaceResource(deploymentMap(defaultNs, modifiedname, modifiedname, modifiedname)).
ReplaceResource(deploymentMap(ns1, prefixedname, prefixedname, prefixedname)).
ReplaceResource(deploymentMap(ns2, suffixedname, suffixedname, suffixedname)).
ReplaceResource(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": modifiedname,
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"persistentvolumes",
},
"resourceNames": []interface{}{
modifiedname,
},
},
}}).
ReplaceResource(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleBinding",
"metadata": map[string]interface{}{
"name": modifiedname,
},
"roleRef": map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"name": modifiedname,
},
// The following tests required a change in
// getNameFunc implementation in order to leverage
// the namespace field.
"subjects": []interface{}{
map[string]interface{}{
"kind": "ServiceAccount",
"name": modifiedname,
"namespace": defaultNs,
},
map[string]interface{}{
"kind": "ServiceAccount",
"name": prefixedname,
"namespace": ns1,
},
map[string]interface{}{
"kind": "ServiceAccount",
"name": suffixedname,
"namespace": ns2,
},
},
}).ResMap()
clusterRoleId := resid.NewResId(
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
clusterRoleBindingId := resid.NewResId(
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
clusterRole.AppendRefBy(clusterRoleBindingId)
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
err := nrt.Transform(m)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
// TestNameReferenceNamespace creates configmap, secret, deployment
// It validates the change done is IsSameFuzzyNamespace which
// uses the IsNsEquals method instead of the simple == operator.
func TestNameReferenceCandidateSelection(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).
AddWithName("cm1", map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "p1-cm1-hash",
}}).
AddWithNsAndName("default", "secret1", map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "p1-secret1-hash",
"namespace": "default",
}}).
AddWithName("deploy1", deploymentMap("", "p1-deploy1", "cm1", "secret1")).
ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
ReplaceResource(deploymentMap("", "p1-deploy1", "p1-cm1-hash", "p1-secret1-hash")).
ResMap()
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
err := nrt.Transform(m)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}