mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	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:
		@@ -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")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user