Merge pull request #55465 from yanxuean/configmap-unittest

Automatic merge from submit-queue (batch tested with PRs 53337, 55465, 55512, 55522, 54554). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

add unit test for VisitPodConfigmapNames

Signed-off-by: yanxuean <yan.xuean@zte.com.cn>

**What this PR does / why we need it**:

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #

**Special notes for your reviewer**:

**Release note**:
```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue 2017-11-11 12:44:22 -08:00 committed by GitHub
commit 47ecba9949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -125,7 +125,7 @@ func TestPodSecrets(t *testing.T) {
"Spec.Volumes[*].VolumeSource.ISCSI.SecretRef", "Spec.Volumes[*].VolumeSource.ISCSI.SecretRef",
"Spec.Volumes[*].VolumeSource.StorageOS.SecretRef", "Spec.Volumes[*].VolumeSource.StorageOS.SecretRef",
) )
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.Pod{})) secretPaths := collectResourcePaths(t, "secret", nil, "", reflect.TypeOf(&api.Pod{}))
secretPaths = secretPaths.Difference(excludedSecretPaths) secretPaths = secretPaths.Difference(excludedSecretPaths)
if missingPaths := expectedSecretPaths.Difference(secretPaths); len(missingPaths) > 0 { if missingPaths := expectedSecretPaths.Difference(secretPaths); len(missingPaths) > 0 {
t.Logf("Missing expected secret paths:\n%s", strings.Join(missingPaths.List(), "\n")) t.Logf("Missing expected secret paths:\n%s", strings.Join(missingPaths.List(), "\n"))
@ -146,36 +146,111 @@ func TestPodSecrets(t *testing.T) {
} }
} }
// collectSecretPaths traverses the object, computing all the struct paths that lead to fields with "secret" in the name. // collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name.
func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.Type) sets.String { func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, name string, tp reflect.Type) sets.String {
secretPaths := sets.NewString() resourcename = strings.ToLower(resourcename)
resourcePaths := sets.NewString()
if tp.Kind() == reflect.Ptr { if tp.Kind() == reflect.Ptr {
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...) resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...)
return secretPaths return resourcePaths
} }
if strings.Contains(strings.ToLower(name), "secret") { if strings.Contains(strings.ToLower(name), resourcename) {
secretPaths.Insert(path.String()) resourcePaths.Insert(path.String())
} }
switch tp.Kind() { switch tp.Kind() {
case reflect.Ptr: case reflect.Ptr:
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...) resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...)
case reflect.Struct: case reflect.Struct:
for i := 0; i < tp.NumField(); i++ { for i := 0; i < tp.NumField(); i++ {
field := tp.Field(i) field := tp.Field(i)
secretPaths.Insert(collectSecretPaths(t, path.Child(field.Name), field.Name, field.Type).List()...) resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type).List()...)
} }
case reflect.Interface: case reflect.Interface:
t.Errorf("cannot find secret fields in interface{} field %s", path.String()) t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String())
case reflect.Map: case reflect.Map:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...) resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...)
case reflect.Slice: case reflect.Slice:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...) resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...)
default: default:
// all primitive types // all primitive types
} }
return secretPaths return resourcePaths
}
func TestPodConfigmaps(t *testing.T) {
// Stub containing all possible ConfigMap references in a pod.
// The names of the referenced ConfigMaps match struct paths detected by reflection.
pod := &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{{
EnvFrom: []api.EnvFromSource{{
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{
Name: "Spec.Containers[*].EnvFrom[*].ConfigMapRef"}}}},
Env: []api.EnvVar{{
ValueFrom: &api.EnvVarSource{
ConfigMapKeyRef: &api.ConfigMapKeySelector{
LocalObjectReference: api.LocalObjectReference{
Name: "Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}},
InitContainers: []api.Container{{
EnvFrom: []api.EnvFromSource{{
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{
Name: "Spec.InitContainers[*].EnvFrom[*].ConfigMapRef"}}}},
Env: []api.EnvVar{{
ValueFrom: &api.EnvVarSource{
ConfigMapKeyRef: &api.ConfigMapKeySelector{
LocalObjectReference: api.LocalObjectReference{
Name: "Spec.InitContainers[*].Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}},
Volumes: []api.Volume{{
VolumeSource: api.VolumeSource{
Projected: &api.ProjectedVolumeSource{
Sources: []api.VolumeProjection{{
ConfigMap: &api.ConfigMapProjection{
LocalObjectReference: api.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.Projected.Sources[*].ConfigMap"}}}}}}}, {
VolumeSource: api.VolumeSource{
ConfigMap: &api.ConfigMapVolumeSource{
LocalObjectReference: api.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}},
},
}
extractedNames := sets.NewString()
VisitPodConfigmapNames(pod, func(name string) bool {
extractedNames.Insert(name)
return true
})
// expectedPaths holds struct paths to fields with "ConfigMap" in the name that are references to ConfigMap API objects.
// every path here should be represented as an example in the Pod stub above, with the ConfigMap name set to the path.
expectedPaths := sets.NewString(
"Spec.Containers[*].EnvFrom[*].ConfigMapRef",
"Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef",
"Spec.InitContainers[*].EnvFrom[*].ConfigMapRef",
"Spec.InitContainers[*].Env[*].ValueFrom.ConfigMapKeyRef",
"Spec.Volumes[*].VolumeSource.Projected.Sources[*].ConfigMap",
"Spec.Volumes[*].VolumeSource.ConfigMap",
)
collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&api.Pod{}))
if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 {
t.Logf("Missing expected paths:\n%s", strings.Join(missingPaths.List(), "\n"))
t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths")
}
if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 {
t.Logf("Extra paths:\n%s", strings.Join(extraPaths.List(), "\n"))
t.Error("Extra fields with resource in the name found. Verify VisitPodConfigmapNames() is including these fields if appropriate, then correct expectedPaths")
}
if missingNames := expectedPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected names:\n%s", strings.Join(missingNames.List(), "\n"))
t.Error("Missing expected names. Verify the pod stub above includes these references, then verify VisitPodConfigmapNames() is correctly finding the missing names")
}
if extraNames := extractedNames.Difference(expectedPaths); len(extraNames) > 0 {
t.Logf("Extra names:\n%s", strings.Join(extraNames.List(), "\n"))
t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names")
}
} }