func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" { if err := apparmor.ValidateProfileFormat(p); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error())) } } if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" { for _, p := range strings.Split(allowed, ",") { if err := apparmor.ValidateProfileFormat(p); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error())) } } } sysctlAnnotation := annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] sysctlFldPath := fldPath.Key(extensions.SysctlsPodSecurityPolicyAnnotationKey) sysctls, err := extensions.SysctlsFromPodSecurityPolicyAnnotation(sysctlAnnotation) if err != nil { allErrs = append(allErrs, field.Invalid(sysctlFldPath, sysctlAnnotation, err.Error())) } else { allErrs = append(allErrs, validatePodSecurityPolicySysctls(sysctlFldPath, sysctls)...) } if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) } if allowed := annotations[seccomp.AllowedProfilesAnnotationKey]; allowed != "" { for _, p := range strings.Split(allowed, ",") { allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.AllowedProfilesAnnotationKey))...) } } return allErrs }
func objectReflectDiff(path *field.Path, a, b reflect.Value) []diff { switch a.Type().Kind() { case reflect.Struct: var changes []diff for i := 0; i < a.Type().NumField(); i++ { if !public(a.Type().Field(i).Name) { if reflect.DeepEqual(a.Interface(), b.Interface()) { continue } return []diff{{path: path, a: fmt.Sprintf("%#v", a), b: fmt.Sprintf("%#v", b)}} } if sub := objectReflectDiff(path.Child(a.Type().Field(i).Name), a.Field(i), b.Field(i)); len(sub) > 0 { changes = append(changes, sub...) } else { if !reflect.DeepEqual(a.Field(i).Interface(), b.Field(i).Interface()) { changes = append(changes, diff{path: path, a: a.Field(i).Interface(), b: b.Field(i).Interface()}) } } } return changes case reflect.Ptr, reflect.Interface: if a.IsNil() || b.IsNil() { switch { case a.IsNil() && b.IsNil(): return nil case a.IsNil(): return []diff{{path: path, a: nil, b: b.Interface()}} default: return []diff{{path: path, a: a.Interface(), b: nil}} } } return objectReflectDiff(path, a.Elem(), b.Elem()) case reflect.Chan: if !reflect.DeepEqual(a.Interface(), b.Interface()) { return []diff{{path: path, a: a.Interface(), b: b.Interface()}} } return nil case reflect.Slice: lA, lB := a.Len(), b.Len() l := lA if lB < lA { l = lB } if lA == lB && lA == 0 { if a.IsNil() != b.IsNil() { return []diff{{path: path, a: a.Interface(), b: b.Interface()}} } return nil } for i := 0; i < l; i++ { if !reflect.DeepEqual(a.Index(i), b.Index(i)) { return objectReflectDiff(path.Index(i), a.Index(i), b.Index(i)) } } var diffs []diff for i := l; i < lA; i++ { diffs = append(diffs, diff{path: path.Index(i), a: a.Index(i), b: nil}) } for i := l; i < lB; i++ { diffs = append(diffs, diff{path: path.Index(i), a: nil, b: b.Index(i)}) } if len(diffs) == 0 { diffs = append(diffs, diff{path: path, a: a, b: b}) } return diffs case reflect.Map: if reflect.DeepEqual(a.Interface(), b.Interface()) { return nil } aKeys := make(map[interface{}]interface{}) for _, key := range a.MapKeys() { aKeys[key.Interface()] = a.MapIndex(key).Interface() } var missing []diff for _, key := range b.MapKeys() { if _, ok := aKeys[key.Interface()]; ok { delete(aKeys, key.Interface()) if reflect.DeepEqual(a.MapIndex(key).Interface(), b.MapIndex(key).Interface()) { continue } missing = append(missing, objectReflectDiff(path.Key(fmt.Sprintf("%s", key.Interface())), a.MapIndex(key), b.MapIndex(key))...) continue } missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key.Interface())), a: nil, b: b.MapIndex(key).Interface()}) } for key, value := range aKeys { missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key)), a: value, b: nil}) } if len(missing) == 0 { missing = append(missing, diff{path: path, a: a.Interface(), b: b.Interface()}) } sort.Sort(orderedDiffs(missing)) return missing default: if reflect.DeepEqual(a.Interface(), b.Interface()) { return nil } if !a.CanInterface() { return []diff{{path: path, a: fmt.Sprintf("%#v", a), b: fmt.Sprintf("%#v", b)}} } return []diff{{path: path, a: a.Interface(), b: b.Interface()}} } }