use generic Set in api

Signed-off-by: bzsuni <bingzhe.sun@daocloud.io>
This commit is contained in:
bzsuni 2023-09-25 19:04:08 +08:00
parent c6bb90aeea
commit aa9b2b1696
10 changed files with 90 additions and 90 deletions

View File

@ -67,12 +67,12 @@ func TestWarnings(t *testing.T) {
for _, tc := range testcases { for _, tc := range testcases {
t.Run("podspec_"+tc.name, func(t *testing.T) { t.Run("podspec_"+tc.name, func(t *testing.T) {
actual := sets.NewString(GetWarningsForRuntimeClass(tc.template)...) actual := sets.New[string](GetWarningsForRuntimeClass(tc.template)...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })

View File

@ -298,12 +298,12 @@ func TestWarnings(t *testing.T) {
for _, tc := range testcases { for _, tc := range testcases {
t.Run("podspec_"+tc.name, func(t *testing.T) { t.Run("podspec_"+tc.name, func(t *testing.T) {
actual := sets.NewString(GetWarningsForPersistentVolume(tc.template)...) actual := sets.New[string](GetWarningsForPersistentVolume(tc.template)...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })

View File

@ -571,12 +571,12 @@ func TestWarnings(t *testing.T) {
for _, tc := range testcases { for _, tc := range testcases {
t.Run("pvcspec_"+tc.name, func(t *testing.T) { t.Run("pvcspec_"+tc.name, func(t *testing.T) {
actual := sets.NewString(GetWarningsForPersistentVolumeClaim(tc.template)...) actual := sets.New[string](GetWarningsForPersistentVolumeClaim(tc.template)...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })

View File

@ -290,19 +290,19 @@ func TestPodSecrets(t *testing.T) {
Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.SecretKeyRef"}}}}}}}}, Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.SecretKeyRef"}}}}}}}},
}, },
} }
extractedNames := sets.NewString() extractedNames := sets.New[string]()
VisitPodSecretNames(pod, func(name string) bool { VisitPodSecretNames(pod, func(name string) bool {
extractedNames.Insert(name) extractedNames.Insert(name)
return true return true
}, AllContainers) }, AllContainers)
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects // excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
excludedSecretPaths := sets.NewString( excludedSecretPaths := sets.New[string](
"Spec.Volumes[*].VolumeSource.CephFS.SecretFile", "Spec.Volumes[*].VolumeSource.CephFS.SecretFile",
) )
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects. // expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
// every path here should be represented as an example in the Pod stub above, with the secret name set to the path. // every path here should be represented as an example in the Pod stub above, with the secret name set to the path.
expectedSecretPaths := sets.NewString( expectedSecretPaths := sets.New[string](
"Spec.Containers[*].EnvFrom[*].SecretRef", "Spec.Containers[*].EnvFrom[*].SecretRef",
"Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef", "Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef",
"Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].SecretRef", "Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].SecretRef",
@ -326,20 +326,20 @@ func TestPodSecrets(t *testing.T) {
secretPaths := collectResourcePaths(t, "secret", 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(sets.List[string](missingPaths), "\n"))
t.Error("Missing expected secret paths. Verify VisitPodSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths") t.Error("Missing expected secret paths. Verify VisitPodSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
} }
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 { if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n")) t.Logf("Extra secret paths:\n%s", strings.Join(sets.List[string](extraPaths), "\n"))
t.Error("Extra fields with 'secret' in the name found. Verify VisitPodSecretNames() is including these fields if appropriate, then correct expectedSecretPaths") t.Error("Extra fields with 'secret' in the name found. Verify VisitPodSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
} }
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 { if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n")) t.Logf("Missing expected secret names:\n%s", strings.Join(sets.List[string](missingNames), "\n"))
t.Error("Missing expected secret names. Verify the pod stub above includes these references, then verify VisitPodSecretNames() is correctly finding the missing names") t.Error("Missing expected secret names. Verify the pod stub above includes these references, then verify VisitPodSecretNames() is correctly finding the missing names")
} }
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 { if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n")) t.Logf("Extra secret names:\n%s", strings.Join(sets.List[string](extraNames), "\n"))
t.Error("Extra secret names extracted. Verify VisitPodSecretNames() is correctly extracting secret names") t.Error("Extra secret names extracted. Verify VisitPodSecretNames() is correctly extracting secret names")
} }
@ -360,12 +360,12 @@ func TestPodSecrets(t *testing.T) {
} }
// collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name. // collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name.
func collectResourcePaths(t *testing.T, resourcename string, 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.Set[string] {
resourcename = strings.ToLower(resourcename) resourcename = strings.ToLower(resourcename)
resourcePaths := sets.NewString() resourcePaths := sets.New[string]()
if tp.Kind() == reflect.Pointer { if tp.Kind() == reflect.Pointer {
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path, name, tp.Elem()))...)
return resourcePaths return resourcePaths
} }
@ -375,7 +375,7 @@ func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, n
switch tp.Kind() { switch tp.Kind() {
case reflect.Pointer: case reflect.Pointer:
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path, name, tp.Elem()))...)
case reflect.Struct: case reflect.Struct:
// ObjectMeta is generic and therefore should never have a field with a specific resource's name; // ObjectMeta is generic and therefore should never have a field with a specific resource's name;
// it contains cycles so it's easiest to just skip it. // it contains cycles so it's easiest to just skip it.
@ -384,14 +384,14 @@ func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, n
} }
for i := 0; i < tp.NumField(); i++ { for i := 0; i < tp.NumField(); i++ {
field := tp.Field(i) field := tp.Field(i)
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type))...)
} }
case reflect.Interface: case reflect.Interface:
t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String()) t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String())
case reflect.Map: case reflect.Map:
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()))...)
case reflect.Slice: case reflect.Slice:
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()))...)
default: default:
// all primitive types // all primitive types
} }
@ -448,7 +448,7 @@ func TestPodConfigmaps(t *testing.T) {
Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}}, Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}},
}, },
} }
extractedNames := sets.NewString() extractedNames := sets.New[string]()
VisitPodConfigmapNames(pod, func(name string) bool { VisitPodConfigmapNames(pod, func(name string) bool {
extractedNames.Insert(name) extractedNames.Insert(name)
return true return true
@ -456,7 +456,7 @@ func TestPodConfigmaps(t *testing.T) {
// expectedPaths holds struct paths to fields with "ConfigMap" in the name that are references to ConfigMap API objects. // 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. // 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( expectedPaths := sets.New[string](
"Spec.Containers[*].EnvFrom[*].ConfigMapRef", "Spec.Containers[*].EnvFrom[*].ConfigMapRef",
"Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef", "Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef",
"Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].ConfigMapRef", "Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].ConfigMapRef",
@ -468,20 +468,20 @@ func TestPodConfigmaps(t *testing.T) {
) )
collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&api.Pod{})) collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&api.Pod{}))
if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 { if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 {
t.Logf("Missing expected paths:\n%s", strings.Join(missingPaths.List(), "\n")) t.Logf("Missing expected paths:\n%s", strings.Join(sets.List[string](missingPaths), "\n"))
t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths") t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths")
} }
if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 { if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 {
t.Logf("Extra paths:\n%s", strings.Join(extraPaths.List(), "\n")) t.Logf("Extra paths:\n%s", strings.Join(sets.List[string](extraPaths), "\n"))
t.Error("Extra fields with resource in the name found. Verify VisitPodConfigmapNames() is including these fields if appropriate, then correct expectedPaths") 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 { if missingNames := expectedPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected names:\n%s", strings.Join(missingNames.List(), "\n")) t.Logf("Missing expected names:\n%s", strings.Join(sets.List[string](missingNames), "\n"))
t.Error("Missing expected names. Verify the pod stub above includes these references, then verify VisitPodConfigmapNames() is correctly finding the missing names") 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 { if extraNames := extractedNames.Difference(expectedPaths); len(extraNames) > 0 {
t.Logf("Extra names:\n%s", strings.Join(extraNames.List(), "\n")) t.Logf("Extra names:\n%s", strings.Join(sets.List[string](extraNames), "\n"))
t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names") t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names")
} }

View File

@ -170,7 +170,7 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta
// duplicate hostAliases (#91670, #58477) // duplicate hostAliases (#91670, #58477)
if len(podSpec.HostAliases) > 1 { if len(podSpec.HostAliases) > 1 {
items := sets.NewString() items := sets.New[string]()
for i, item := range podSpec.HostAliases { for i, item := range podSpec.HostAliases {
if items.Has(item.IP) { if items.Has(item.IP) {
warnings = append(warnings, fmt.Sprintf("%s: duplicate ip %q", fieldPath.Child("spec", "hostAliases").Index(i).Child("ip"), item.IP)) warnings = append(warnings, fmt.Sprintf("%s: duplicate ip %q", fieldPath.Child("spec", "hostAliases").Index(i).Child("ip"), item.IP))
@ -182,7 +182,7 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta
// duplicate imagePullSecrets (#91629, #58477) // duplicate imagePullSecrets (#91629, #58477)
if len(podSpec.ImagePullSecrets) > 1 { if len(podSpec.ImagePullSecrets) > 1 {
items := sets.NewString() items := sets.New[string]()
for i, item := range podSpec.ImagePullSecrets { for i, item := range podSpec.ImagePullSecrets {
if items.Has(item.Name) { if items.Has(item.Name) {
warnings = append(warnings, fmt.Sprintf("%s: duplicate name %q", fieldPath.Child("spec", "imagePullSecrets").Index(i).Child("name"), item.Name)) warnings = append(warnings, fmt.Sprintf("%s: duplicate name %q", fieldPath.Child("spec", "imagePullSecrets").Index(i).Child("name"), item.Name))
@ -237,7 +237,7 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta
// duplicate containers[*].env (#86163, #93266, #58477) // duplicate containers[*].env (#86163, #93266, #58477)
if len(c.Env) > 1 { if len(c.Env) > 1 {
items := sets.NewString() items := sets.New[string]()
for i, item := range c.Env { for i, item := range c.Env {
if items.Has(item.Name) { if items.Has(item.Name) {
// a previous value exists, but it might be OK // a previous value exists, but it might be OK

View File

@ -1066,12 +1066,12 @@ func TestWarnings(t *testing.T) {
if tc.oldTemplate != nil { if tc.oldTemplate != nil {
oldTemplate = tc.oldTemplate oldTemplate = tc.oldTemplate
} }
actual := sets.NewString(GetWarningsForPodTemplate(context.TODO(), nil, tc.template, oldTemplate)...) actual := sets.New[string](GetWarningsForPodTemplate(context.TODO(), nil, tc.template, oldTemplate)...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })
@ -1084,12 +1084,12 @@ func TestWarnings(t *testing.T) {
Spec: tc.template.Spec, Spec: tc.template.Spec,
} }
} }
actual := sets.NewString(GetWarningsForPod(context.TODO(), pod, &api.Pod{})...) actual := sets.New[string](GetWarningsForPod(context.TODO(), pod, &api.Pod{})...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })

View File

@ -76,12 +76,12 @@ func TestStorageClassWarnings(t *testing.T) {
for _, tc := range testcases { for _, tc := range testcases {
t.Run("podspec_"+tc.name, func(t *testing.T) { t.Run("podspec_"+tc.name, func(t *testing.T) {
actual := sets.NewString(GetWarningsForStorageClass(tc.template)...) actual := sets.New[string](GetWarningsForStorageClass(tc.template)...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })
@ -157,12 +157,12 @@ func TestCSIStorageCapacityWarnings(t *testing.T) {
for _, tc := range testcases { for _, tc := range testcases {
t.Run("podspec_"+tc.name, func(t *testing.T) { t.Run("podspec_"+tc.name, func(t *testing.T) {
actual := sets.NewString(GetWarningsForCSIStorageCapacity(tc.template)...) actual := sets.New[string](GetWarningsForCSIStorageCapacity(tc.template)...)
expected := sets.NewString(tc.expected...) expected := sets.New[string](tc.expected...)
for _, missing := range expected.Difference(actual).List() { for _, missing := range sets.List[string](expected.Difference(actual)) {
t.Errorf("missing: %s", missing) t.Errorf("missing: %s", missing)
} }
for _, extra := range actual.Difference(expected).List() { for _, extra := range sets.List[string](actual.Difference(expected)) {
t.Errorf("extra: %s", extra) t.Errorf("extra: %s", extra)
} }
}) })

View File

@ -149,7 +149,7 @@ func TestSpecificKind(t *testing.T) {
roundtrip.RoundTripSpecificKind(t, internalGVK, legacyscheme.Scheme, legacyscheme.Codecs, fuzzer, nil) roundtrip.RoundTripSpecificKind(t, internalGVK, legacyscheme.Scheme, legacyscheme.Codecs, fuzzer, nil)
} }
var nonRoundTrippableTypes = sets.NewString( var nonRoundTrippableTypes = sets.New[string](
"ExportOptions", "ExportOptions",
"GetOptions", "GetOptions",
// WatchEvent does not include kind and version and can only be deserialized // WatchEvent does not include kind and version and can only be deserialized

View File

@ -157,8 +157,8 @@ func TestPVSecrets(t *testing.T) {
Name: "Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef", Name: "Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef",
Namespace: "csi"}}}}}, Namespace: "csi"}}}}},
} }
extractedNames := sets.NewString() extractedNames := sets.New[string]()
extractedNamesWithNamespace := sets.NewString() extractedNamesWithNamespace := sets.New[string]()
for _, pv := range pvs { for _, pv := range pvs {
VisitPVSecretNames(pv, func(namespace, name string, kubeletVisible bool) bool { VisitPVSecretNames(pv, func(namespace, name string, kubeletVisible bool) bool {
@ -169,13 +169,13 @@ func TestPVSecrets(t *testing.T) {
} }
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects // excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
excludedSecretPaths := sets.NewString( excludedSecretPaths := sets.New[string](
"Spec.PersistentVolumeSource.CephFS.SecretFile", "Spec.PersistentVolumeSource.CephFS.SecretFile",
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace", "Spec.PersistentVolumeSource.AzureFile.SecretNamespace",
) )
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects. // expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
// every path here should be represented as an example in the PV stub above, with the secret name set to the path. // every path here should be represented as an example in the PV stub above, with the secret name set to the path.
expectedSecretPaths := sets.NewString( expectedSecretPaths := sets.New[string](
"Spec.PersistentVolumeSource.AzureFile.SecretName", "Spec.PersistentVolumeSource.AzureFile.SecretName",
"Spec.PersistentVolumeSource.CephFS.SecretRef", "Spec.PersistentVolumeSource.CephFS.SecretRef",
"Spec.PersistentVolumeSource.Cinder.SecretRef", "Spec.PersistentVolumeSource.Cinder.SecretRef",
@ -193,24 +193,24 @@ func TestPVSecrets(t *testing.T) {
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.PersistentVolume{})) secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.PersistentVolume{}))
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(sets.List[string](missingPaths), "\n"))
t.Error("Missing expected secret paths. Verify VisitPVSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths") t.Error("Missing expected secret paths. Verify VisitPVSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
} }
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 { if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n")) t.Logf("Extra secret paths:\n%s", strings.Join(sets.List[string](extraPaths), "\n"))
t.Error("Extra fields with 'secret' in the name found. Verify VisitPVSecretNames() is including these fields if appropriate, then correct expectedSecretPaths") t.Error("Extra fields with 'secret' in the name found. Verify VisitPVSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
} }
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 { if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n")) t.Logf("Missing expected secret names:\n%s", strings.Join(sets.List[string](missingNames), "\n"))
t.Error("Missing expected secret names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names") t.Error("Missing expected secret names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names")
} }
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 { if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n")) t.Logf("Extra secret names:\n%s", strings.Join(sets.List(extraNames), "\n"))
t.Error("Extra secret names extracted. Verify VisitPVSecretNames() is correctly extracting secret names") t.Error("Extra secret names extracted. Verify VisitPVSecretNames() is correctly extracting secret names")
} }
expectedNamespacedNames := sets.NewString( expectedNamespacedNames := sets.New[string](
"claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName", "claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName",
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName", "Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName",
@ -240,11 +240,11 @@ func TestPVSecrets(t *testing.T) {
"csi/Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef", "csi/Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef",
) )
if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 { if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 {
t.Logf("Missing expected namespaced names:\n%s", strings.Join(missingNames.List(), "\n")) t.Logf("Missing expected namespaced names:\n%s", strings.Join(sets.List[string](missingNames), "\n"))
t.Error("Missing expected namespaced names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names") t.Error("Missing expected namespaced names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names")
} }
if extraNames := extractedNamesWithNamespace.Difference(expectedNamespacedNames); len(extraNames) > 0 { if extraNames := extractedNamesWithNamespace.Difference(expectedNamespacedNames); len(extraNames) > 0 {
t.Logf("Extra namespaced names:\n%s", strings.Join(extraNames.List(), "\n")) t.Logf("Extra namespaced names:\n%s", strings.Join(sets.List[string](extraNames), "\n"))
t.Error("Extra namespaced names extracted. Verify VisitPVSecretNames() is correctly extracting secret names") t.Error("Extra namespaced names extracted. Verify VisitPVSecretNames() is correctly extracting secret names")
} }
@ -263,11 +263,11 @@ func TestPVSecrets(t *testing.T) {
} }
// collectSecretPaths traverses the object, computing all the struct paths that lead to fields with "secret" in the name. // collectSecretPaths traverses the object, computing all the struct paths that lead to fields with "secret" in the name.
func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.Type) sets.String { func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.Type) sets.Set[string] {
secretPaths := sets.NewString() secretPaths := sets.New[string]()
if tp.Kind() == reflect.Pointer { if tp.Kind() == reflect.Pointer {
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...) secretPaths.Insert(sets.List[string](collectSecretPaths(t, path, name, tp.Elem()))...)
return secretPaths return secretPaths
} }
@ -277,7 +277,7 @@ func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.
switch tp.Kind() { switch tp.Kind() {
case reflect.Pointer: case reflect.Pointer:
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...) secretPaths.Insert(sets.List[string](collectSecretPaths(t, path, name, tp.Elem()))...)
case reflect.Struct: case reflect.Struct:
// ObjectMeta should not have any field with the word "secret" in it; // ObjectMeta should not have any field with the word "secret" in it;
// it contains cycles so it's easiest to just skip it. // it contains cycles so it's easiest to just skip it.
@ -286,14 +286,14 @@ func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.
} }
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()...) secretPaths.Insert(sets.List[string](collectSecretPaths(t, path.Child(field.Name), field.Name, field.Type))...)
} }
case reflect.Interface: case reflect.Interface:
t.Errorf("cannot find secret fields in interface{} field %s", path.String()) t.Errorf("cannot find secret fields in interface{} field %s", path.String())
case reflect.Map: case reflect.Map:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...) secretPaths.Insert(sets.List[string](collectSecretPaths(t, path.Key("*"), "", tp.Elem()))...)
case reflect.Slice: case reflect.Slice:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...) secretPaths.Insert(sets.List[string](collectSecretPaths(t, path.Key("*"), "", tp.Elem()))...)
default: default:
// all primitive types // all primitive types
} }

View File

@ -453,19 +453,19 @@ func TestPodSecrets(t *testing.T) {
Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.SecretKeyRef"}}}}}}}}, Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.SecretKeyRef"}}}}}}}},
}, },
} }
extractedNames := sets.NewString() extractedNames := sets.New[string]()
VisitPodSecretNames(pod, func(name string) bool { VisitPodSecretNames(pod, func(name string) bool {
extractedNames.Insert(name) extractedNames.Insert(name)
return true return true
}) })
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects // excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
excludedSecretPaths := sets.NewString( excludedSecretPaths := sets.New[string](
"Spec.Volumes[*].VolumeSource.CephFS.SecretFile", "Spec.Volumes[*].VolumeSource.CephFS.SecretFile",
) )
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects. // expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
// every path here should be represented as an example in the Pod stub above, with the secret name set to the path. // every path here should be represented as an example in the Pod stub above, with the secret name set to the path.
expectedSecretPaths := sets.NewString( expectedSecretPaths := sets.New[string](
"Spec.Containers[*].EnvFrom[*].SecretRef", "Spec.Containers[*].EnvFrom[*].SecretRef",
"Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef", "Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef",
"Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].SecretRef", "Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].SecretRef",
@ -489,20 +489,20 @@ func TestPodSecrets(t *testing.T) {
secretPaths := collectResourcePaths(t, "secret", nil, "", reflect.TypeOf(&v1.Pod{})) secretPaths := collectResourcePaths(t, "secret", nil, "", reflect.TypeOf(&v1.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(sets.List[string](missingPaths), "\n"))
t.Error("Missing expected secret paths. Verify VisitPodSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths") t.Error("Missing expected secret paths. Verify VisitPodSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
} }
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 { if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n")) t.Logf("Extra secret paths:\n%s", strings.Join(sets.List(extraPaths), "\n"))
t.Error("Extra fields with 'secret' in the name found. Verify VisitPodSecretNames() is including these fields if appropriate, then correct expectedSecretPaths") t.Error("Extra fields with 'secret' in the name found. Verify VisitPodSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
} }
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 { if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n")) t.Logf("Missing expected secret names:\n%s", strings.Join(sets.List[string](missingNames), "\n"))
t.Error("Missing expected secret names. Verify the pod stub above includes these references, then verify VisitPodSecretNames() is correctly finding the missing names") t.Error("Missing expected secret names. Verify the pod stub above includes these references, then verify VisitPodSecretNames() is correctly finding the missing names")
} }
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 { if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n")) t.Logf("Extra secret names:\n%s", strings.Join(sets.List[string](extraNames), "\n"))
t.Error("Extra secret names extracted. Verify VisitPodSecretNames() is correctly extracting secret names") t.Error("Extra secret names extracted. Verify VisitPodSecretNames() is correctly extracting secret names")
} }
@ -523,12 +523,12 @@ func TestPodSecrets(t *testing.T) {
} }
// collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name. // collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name.
func collectResourcePaths(t *testing.T, resourcename string, 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.Set[string] {
resourcename = strings.ToLower(resourcename) resourcename = strings.ToLower(resourcename)
resourcePaths := sets.NewString() resourcePaths := sets.New[string]()
if tp.Kind() == reflect.Pointer { if tp.Kind() == reflect.Pointer {
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path, name, tp.Elem()))...)
return resourcePaths return resourcePaths
} }
@ -538,7 +538,7 @@ func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, n
switch tp.Kind() { switch tp.Kind() {
case reflect.Pointer: case reflect.Pointer:
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path, name, tp.Elem()))...)
case reflect.Struct: case reflect.Struct:
// ObjectMeta is generic and therefore should never have a field with a specific resource's name; // ObjectMeta is generic and therefore should never have a field with a specific resource's name;
// it contains cycles so it's easiest to just skip it. // it contains cycles so it's easiest to just skip it.
@ -547,14 +547,14 @@ func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, n
} }
for i := 0; i < tp.NumField(); i++ { for i := 0; i < tp.NumField(); i++ {
field := tp.Field(i) field := tp.Field(i)
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type))...)
} }
case reflect.Interface: case reflect.Interface:
t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String()) t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String())
case reflect.Map: case reflect.Map:
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()))...)
case reflect.Slice: case reflect.Slice:
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...) resourcePaths.Insert(sets.List[string](collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()))...)
default: default:
// all primitive types // all primitive types
} }
@ -611,7 +611,7 @@ func TestPodConfigmaps(t *testing.T) {
Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}}, Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}},
}, },
} }
extractedNames := sets.NewString() extractedNames := sets.New[string]()
VisitPodConfigmapNames(pod, func(name string) bool { VisitPodConfigmapNames(pod, func(name string) bool {
extractedNames.Insert(name) extractedNames.Insert(name)
return true return true
@ -619,7 +619,7 @@ func TestPodConfigmaps(t *testing.T) {
// expectedPaths holds struct paths to fields with "ConfigMap" in the name that are references to ConfigMap API objects. // 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. // 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( expectedPaths := sets.New[string](
"Spec.Containers[*].EnvFrom[*].ConfigMapRef", "Spec.Containers[*].EnvFrom[*].ConfigMapRef",
"Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef", "Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef",
"Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].ConfigMapRef", "Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].ConfigMapRef",
@ -631,20 +631,20 @@ func TestPodConfigmaps(t *testing.T) {
) )
collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&v1.Pod{})) collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&v1.Pod{}))
if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 { if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 {
t.Logf("Missing expected paths:\n%s", strings.Join(missingPaths.List(), "\n")) t.Logf("Missing expected paths:\n%s", strings.Join(sets.List[string](missingPaths), "\n"))
t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths") t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths")
} }
if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 { if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 {
t.Logf("Extra paths:\n%s", strings.Join(extraPaths.List(), "\n")) t.Logf("Extra paths:\n%s", strings.Join(sets.List[string](extraPaths), "\n"))
t.Error("Extra fields with resource in the name found. Verify VisitPodConfigmapNames() is including these fields if appropriate, then correct expectedPaths") 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 { if missingNames := expectedPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected names:\n%s", strings.Join(missingNames.List(), "\n")) t.Logf("Missing expected names:\n%s", strings.Join(sets.List[string](missingNames), "\n"))
t.Error("Missing expected names. Verify the pod stub above includes these references, then verify VisitPodConfigmapNames() is correctly finding the missing names") 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 { if extraNames := extractedNames.Difference(expectedPaths); len(extraNames) > 0 {
t.Logf("Extra names:\n%s", strings.Join(extraNames.List(), "\n")) t.Logf("Extra names:\n%s", strings.Join(sets.List[string](extraNames), "\n"))
t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names") t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names")
} }