// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) field.ErrorList { allErrs := field.ErrorList{} // Make sure event.Namespace and the involvedObject.Namespace agree if len(event.InvolvedObject.Namespace) == 0 { // event.Namespace must also be empty (or "default", for compatibility with old clients) if event.Namespace != api.NamespaceNone && event.Namespace != api.NamespaceDefault { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace")) } } else { // event namespace must match if event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace")) } } // For kinds we recognize, make sure involvedObject.Namespace is set for namespaced kinds if namespaced, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion); err == nil { if namespaced && len(event.InvolvedObject.Namespace) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("involvedObject", "namespace"), fmt.Sprintf("required for kind %s", event.InvolvedObject.Kind))) } if !namespaced && len(event.InvolvedObject.Namespace) > 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, fmt.Sprintf("not allowed for kind %s", event.InvolvedObject.Kind))) } } for _, msg := range validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg)) } return allErrs }
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 validateIngressRules(ingressRules []extensions.IngressRule, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(ingressRules) == 0 { return append(allErrs, field.Required(fldPath, "")) } for i, ih := range ingressRules { if len(ih.Host) > 0 { if isIP := (net.ParseIP(ih.Host) != nil); isIP { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, "must be a DNS name, not an IP address")) } // TODO: Ports and ips are allowed in the host part of a url // according to RFC 3986, consider allowing them. if strings.Contains(ih.Host, "*") { for _, msg := range validation.IsWildcardDNS1123Subdomain(ih.Host) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg)) } continue } for _, msg := range validation.IsDNS1123Subdomain(ih.Host) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg)) } } allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue, fldPath.Index(0))...) } return allErrs }
// ValidateStatefulSetSpec tests if required fields in the StatefulSet spec are set. func ValidateStatefulSetSpec(spec *apps.StatefulSetSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...) if spec.Selector == nil { allErrs = append(allErrs, field.Required(fldPath.Child("selector"), "")) } else { allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is not valid for statefulset.")) } } selector, err := metav1.LabelSelectorAsSelector(spec.Selector) if err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "")) } else { allErrs = append(allErrs, ValidatePodTemplateSpecForStatefulSet(&spec.Template, selector, fldPath.Child("template"))...) } if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) } return allErrs }
func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} limPath := fldPath.Child("limits") reqPath := fldPath.Child("requests") for resourceName, quantity := range requirements.Limits { fldPath := limPath.Key(string(resourceName)) // Validate resource name. allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...) // Validate resource quantity. allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...) // Check that request <= limit. requestQuantity, exists := requirements.Requests[resourceName] if exists { // For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal. if resourceName == v1.ResourceNvidiaGPU && quantity.Cmp(requestQuantity) != 0 { allErrs = append(allErrs, field.Invalid(reqPath, requestQuantity.String(), fmt.Sprintf("must be equal to %s limit", v1.ResourceNvidiaGPU))) } else if quantity.Cmp(requestQuantity) < 0 { allErrs = append(allErrs, field.Invalid(limPath, quantity.String(), fmt.Sprintf("must be greater than or equal to %s request", resourceName))) } } } for resourceName, quantity := range requirements.Requests { fldPath := reqPath.Key(string(resourceName)) // Validate resource name. allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...) // Validate resource quantity. allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...) } return allErrs }
func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRuleValue, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(httpIngressRuleValue.Paths) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("paths"), "")) } for i, rule := range httpIngressRuleValue.Paths { if len(rule.Path) > 0 { if !strings.HasPrefix(rule.Path, "/") { allErrs = append(allErrs, field.Invalid(fldPath.Child("paths").Index(i).Child("path"), rule.Path, "must be an absolute path")) } // TODO: More draconian path regex validation. // Path must be a valid regex. This is the basic requirement. // In addition to this any characters not allowed in a path per // RFC 3986 section-3.3 cannot appear as a literal in the regex. // Consider the example: http://host/valid?#bar, everything after // the last '/' is a valid regex that matches valid#bar, which // isn't a valid path, because the path terminates at the first ? // or #. A more sophisticated form of validation would detect that // the user is confusing url regexes with path regexes. _, err := regexp.CompilePOSIX(rule.Path) if err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("paths").Index(i).Child("path"), rule.Path, "must be a valid regex")) } } allErrs = append(allErrs, validateIngressBackend(&rule.Backend, fldPath.Child("backend"))...) } return allErrs }
func ValidateSelfSubjectAccessReviewSpec(spec authorizationapi.SelfSubjectAccessReviewSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if spec.ResourceAttributes != nil && spec.NonResourceAttributes != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceAttributes"), spec.NonResourceAttributes, `cannot be specified in combination with resourceAttributes`)) } if spec.ResourceAttributes == nil && spec.NonResourceAttributes == nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceAttributes"), spec.NonResourceAttributes, `exactly one of nonResourceAttributes or resourceAttributes must be specified`)) } return allErrs }
func ValidatePositiveIntOrPercent(intOrPercent intstr.IntOrString, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} switch intOrPercent.Type { case intstr.String: for _, msg := range validation.IsValidPercent(intOrPercent.StrVal) { allErrs = append(allErrs, field.Invalid(fldPath, intOrPercent, msg)) } case intstr.Int: allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(intOrPercent.IntValue()), fldPath)...) default: allErrs = append(allErrs, field.Invalid(fldPath, intOrPercent, "must be an integer or percentage (e.g '5%%')")) } return allErrs }
func ValidateAPIService(apiServer *discoveryapi.APIService) field.ErrorList { requiredName := apiServer.Spec.Version + "." + apiServer.Spec.Group allErrs := validation.ValidateObjectMeta(&apiServer.ObjectMeta, false, func(name string, prefix bool) []string { if minimalFailures := path.IsValidPathSegmentName(name); len(minimalFailures) > 0 { return minimalFailures } // the name *must* be version.group if name != requiredName { return []string{fmt.Sprintf("must be `spec.version+\".\"+spec.group`: %q", requiredName)} } return []string{} }, field.NewPath("metadata")) // in this case we allow empty group if len(apiServer.Spec.Group) == 0 && apiServer.Spec.Version != "v1" { allErrs = append(allErrs, field.Required(field.NewPath("spec", "group"), "only v1 may have an empty group and it better be legacy kube")) } if len(apiServer.Spec.Group) > 0 { for _, errString := range utilvalidation.IsDNS1123Subdomain(apiServer.Spec.Group) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "group"), apiServer.Spec.Group, errString)) } } for _, errString := range utilvalidation.IsDNS1035Label(apiServer.Spec.Version) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "version"), apiServer.Spec.Version, errString)) } if apiServer.Spec.Priority <= 0 || apiServer.Spec.Priority > 1000 { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "priority"), apiServer.Spec.Priority, "priority must be positive and less than 1000")) } if len(apiServer.Spec.Service.Namespace) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("spec", "service", "namespace"), "")) } if len(apiServer.Spec.Service.Name) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("spec", "service", "name"), "")) } if apiServer.Spec.InsecureSkipTLSVerify && len(apiServer.Spec.CABundle) > 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "insecureSkipTLSVerify"), apiServer.Spec.InsecureSkipTLSVerify, "may not be true if caBundle is present")) } return allErrs }
// Validate ensures that the specified values fall within the range of the strategy. func (s *defaultCapabilities) Validate(pod *api.Pod, container *api.Container) field.ErrorList { allErrs := field.ErrorList{} // if the security context isn't set then we haven't generated correctly. Shouldn't get here // if using the provider correctly if container.SecurityContext == nil { allErrs = append(allErrs, field.Invalid(field.NewPath("securityContext"), container.SecurityContext, "no security context is set")) return allErrs } if container.SecurityContext.Capabilities == nil { // if container.SC.Caps is nil then nothing was defaulted by the strat or requested by the pod author // if there are no required caps on the strategy and nothing is requested on the pod // then we can safely return here without further validation. if len(s.defaultAddCapabilities) == 0 && len(s.requiredDropCapabilities) == 0 { return allErrs } // container has no requested caps but we have required caps. We should have something in // at least the drops on the container. allErrs = append(allErrs, field.Invalid(field.NewPath("capabilities"), container.SecurityContext.Capabilities, "required capabilities are not set on the securityContext")) return allErrs } // validate that anything being added is in the default or allowed sets defaultAdd := makeCapSet(s.defaultAddCapabilities) allowedAdd := makeCapSet(s.allowedCaps) for _, cap := range container.SecurityContext.Capabilities.Add { sCap := string(cap) if !defaultAdd.Has(sCap) && !allowedAdd.Has(sCap) { allErrs = append(allErrs, field.Invalid(field.NewPath("capabilities", "add"), sCap, "capability may not be added")) } } // validate that anything that is required to be dropped is in the drop set containerDrops := makeCapSet(container.SecurityContext.Capabilities.Drop) for _, requiredDrop := range s.requiredDropCapabilities { sDrop := string(requiredDrop) if !containerDrops.Has(sDrop) { allErrs = append(allErrs, field.Invalid(field.NewPath("capabilities", "drop"), container.SecurityContext.Capabilities.Drop, fmt.Sprintf("%s is required to be dropped but was not found", sDrop))) } } return allErrs }
// Validate ensures that the specified values fall within the range of the strategy. Validation // of this will pass if either the UID is not set, assuming that the image will provided the UID // or if the UID is set it is not root. In order to work properly this assumes that the kubelet // performs a final check on runAsUser or the image UID when runAsUser is nil. func (s *nonRoot) Validate(pod *api.Pod, container *api.Container) field.ErrorList { allErrs := field.ErrorList{} securityContextPath := field.NewPath("securityContext") if container.SecurityContext == nil { detail := fmt.Sprintf("unable to validate nil security context for container %s", container.Name) allErrs = append(allErrs, field.Invalid(securityContextPath, container.SecurityContext, detail)) return allErrs } if container.SecurityContext.RunAsUser != nil && *container.SecurityContext.RunAsUser == 0 { detail := fmt.Sprintf("running with the root UID is forbidden by the pod security policy %s", container.Name) allErrs = append(allErrs, field.Invalid(securityContextPath.Child("runAsUser"), *container.SecurityContext.RunAsUser, detail)) return allErrs } return allErrs }
func ValidateSelfSubjectAccessReview(sar *authorizationapi.SelfSubjectAccessReview) field.ErrorList { allErrs := ValidateSelfSubjectAccessReviewSpec(sar.Spec, field.NewPath("spec")) if !api.Semantic.DeepEqual(metav1.ObjectMeta{}, sar.ObjectMeta) { allErrs = append(allErrs, field.Invalid(field.NewPath("metadata"), sar.ObjectMeta, `must be empty`)) } return allErrs }
func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...) // TODO allow multiple API groups. For now, restrict to one, but I can envision other experimental roles in other groups taking // advantage of the binding infrastructure if roleBinding.RoleRef.APIGroup != rbac.GroupName { allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName})) } switch roleBinding.RoleRef.Kind { case "ClusterRole": default: allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"ClusterRole"})) } if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), "")) } else { for _, msg := range minimalNameRequirements(roleBinding.RoleRef.Name, false) { allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg)) } } subjectsPath := field.NewPath("subjects") for i, subject := range roleBinding.Subjects { allErrs = append(allErrs, validateRoleBindingSubject(subject, false, subjectsPath.Index(i))...) } return allErrs }
// Validates that a Quantity is not negative func ValidateNonnegativeQuantity(value resource.Quantity, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if value.Cmp(resource.Quantity{}) < 0 { allErrs = append(allErrs, field.Invalid(fldPath, value.String(), isNegativeErrorMsg)) } return allErrs }
// Validates that given value is not negative. func ValidateNonnegativeField(value int64, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if value < 0 { allErrs = append(allErrs, field.Invalid(fldPath, value, IsNegativeErrorMsg)) } return allErrs }
// ValidateLabelName validates that the label name is correctly defined. func ValidateLabelName(labelName string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsQualifiedName(labelName) { allErrs = append(allErrs, field.Invalid(fldPath, labelName, msg)) } return allErrs }
func ValidateImmutableField(newVal, oldVal interface{}, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if !api.Semantic.DeepEqual(oldVal, newVal) { allErrs = append(allErrs, field.Invalid(fldPath, newVal, FieldImmutableErrorMsg)) } return allErrs }
func ValidateClusterUpdate(cluster, oldCluster *federation.Cluster) field.ErrorList { allErrs := validation.ValidateObjectMetaUpdate(&cluster.ObjectMeta, &oldCluster.ObjectMeta, field.NewPath("metadata")) if cluster.Name != oldCluster.Name { allErrs = append(allErrs, field.Invalid(field.NewPath("meta", "name"), cluster.Name+" != "+oldCluster.Name, "cannot change cluster name")) } return allErrs }
func Convert_unversioned_LabelSelector_to_map(in *metav1.LabelSelector, out *map[string]string, s conversion.Scope) error { var err error *out, err = metav1.LabelSelectorAsMap(in) if err != nil { err = field.Invalid(field.NewPath("labelSelector"), *in, fmt.Sprintf("cannot convert to old selector: %v", err)) } return err }
// Validate compute resource typename. // Refer to docs/design/resources.md for more details. func validateResourceName(value string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsQualifiedName(value) { allErrs = append(allErrs, field.Invalid(fldPath, value, msg)) } if len(allErrs) != 0 { return allErrs } if len(strings.Split(value, "/")) == 1 { if !api.IsStandardResourceName(value) { return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified")) } } return field.ErrorList{} }
func validateScheduleFormat(schedule string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if _, err := cron.ParseStandard(schedule); err != nil { allErrs = append(allErrs, field.Invalid(fldPath, schedule, err.Error())) } return allErrs }
// validateIDRanges ensures the range is valid. func validateIDRanges(fldPath *field.Path, rng extensions.IDRange) field.ErrorList { allErrs := field.ErrorList{} // if 0 <= Min <= Max then we do not need to validate max. It is always greater than or // equal to 0 and Min. if rng.Min < 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), rng.Min, "min cannot be negative")) } if rng.Max < 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("max"), rng.Max, "max cannot be negative")) } if rng.Min > rng.Max { allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), rng.Min, "min cannot be greater than max")) } return allErrs }
// Validate finalizer names func ValidateFinalizerName(stringValue string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsQualifiedName(stringValue) { allErrs = append(allErrs, field.Invalid(fldPath, stringValue, msg)) } if len(allErrs) != 0 { return allErrs } if len(strings.Split(stringValue, "/")) == 1 { if !api.IsStandardFinalizerName(stringValue) { return append(allErrs, field.Invalid(fldPath, stringValue, "name is neither a standard finalizer name nor is it fully qualified")) } } return field.ErrorList{} }
// ValidateObjectMeta validates an object's metadata on creation. It expects that name generation has already // been performed. // It doesn't return an error for rootscoped resources with namespace, because namespace should already be cleared before. func ValidateObjectMeta(meta *metav1.ObjectMeta, requiresNamespace bool, nameFn apimachineyvalidation.ValidateNameFunc, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(meta.GenerateName) != 0 { for _, msg := range nameFn(meta.GenerateName, true) { allErrs = append(allErrs, field.Invalid(fldPath.Child("generateName"), meta.GenerateName, msg)) } } // If the generated name validates, but the calculated value does not, it's a problem with generation, and we // report it here. This may confuse users, but indicates a programming bug and still must be validated. // If there are multiple fields out of which one is required then add an or as a separator if len(meta.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "name or generateName is required")) } else { for _, msg := range nameFn(meta.Name, false) { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), meta.Name, msg)) } } if requiresNamespace { if len(meta.Namespace) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), "")) } else { for _, msg := range apimachineyvalidation.ValidateNamespaceName(meta.Namespace, false) { allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), meta.Namespace, msg)) } } } else { if len(meta.Namespace) != 0 { allErrs = append(allErrs, field.Forbidden(fldPath.Child("namespace"), "not allowed on this type")) } } if len(meta.ClusterName) != 0 { for _, msg := range ValidateClusterName(meta.ClusterName, false) { allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterName"), meta.ClusterName, msg)) } } allErrs = append(allErrs, apimachineyvalidation.ValidateNonnegativeField(meta.Generation, fldPath.Child("generation"))...) allErrs = append(allErrs, v1validation.ValidateLabels(meta.Labels, fldPath.Child("labels"))...) allErrs = append(allErrs, ValidateAnnotations(meta.Annotations, fldPath.Child("annotations"))...) allErrs = append(allErrs, ValidateOwnerReferences(meta.OwnerReferences, fldPath.Child("ownerReferences"))...) for _, finalizer := range meta.Finalizers { allErrs = append(allErrs, ValidateFinalizerName(finalizer, fldPath.Child("finalizers"))...) } return allErrs }
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList { allErrs := validateResourceName(value, fldPath) if len(strings.Split(value, "/")) == 1 { if !api.IsStandardContainerResourceName(value) { return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers")) } } return field.ErrorList{} }
func ValidateLocalSubjectAccessReview(sar *authorizationapi.LocalSubjectAccessReview) field.ErrorList { allErrs := ValidateSubjectAccessReviewSpec(sar.Spec, field.NewPath("spec")) objectMetaShallowCopy := sar.ObjectMeta objectMetaShallowCopy.Namespace = "" if !api.Semantic.DeepEqual(metav1.ObjectMeta{}, objectMetaShallowCopy) { allErrs = append(allErrs, field.Invalid(field.NewPath("metadata"), sar.ObjectMeta, `must be empty except for namespace`)) } if sar.Spec.ResourceAttributes != nil && sar.Spec.ResourceAttributes.Namespace != sar.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("spec.resourceAttributes.namespace"), sar.Spec.ResourceAttributes.Namespace, `must match metadata.namespace`)) } if sar.Spec.NonResourceAttributes != nil { allErrs = append(allErrs, field.Invalid(field.NewPath("spec.nonResourceAttributes"), sar.Spec.NonResourceAttributes, `disallowed on this kind of request`)) } return allErrs }
func ValidatePodLogOptions(opts *v1.PodLogOptions) field.ErrorList { allErrs := field.ErrorList{} if opts.TailLines != nil && *opts.TailLines < 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("tailLines"), *opts.TailLines, isNegativeErrorMsg)) } if opts.LimitBytes != nil && *opts.LimitBytes < 1 { allErrs = append(allErrs, field.Invalid(field.NewPath("limitBytes"), *opts.LimitBytes, "must be greater than 0")) } switch { case opts.SinceSeconds != nil && opts.SinceTime != nil: allErrs = append(allErrs, field.Forbidden(field.NewPath(""), "at most one of `sinceTime` or `sinceSeconds` may be specified")) case opts.SinceSeconds != nil: if *opts.SinceSeconds < 1 { allErrs = append(allErrs, field.Invalid(field.NewPath("sinceSeconds"), *opts.SinceSeconds, "must be greater than 0")) } } return allErrs }
func IsNotMoreThan100Percent(intOrStringValue intstr.IntOrString, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} value, isPercent := getPercentValue(intOrStringValue) if !isPercent || value <= 100 { return nil } allErrs = append(allErrs, field.Invalid(fldPath, intOrStringValue, "must not be greater than 100%")) return allErrs }
// ValidateLabels validates that a set of labels are correctly defined. func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for k, v := range labels { allErrs = append(allErrs, ValidateLabelName(k, fldPath)...) for _, msg := range validation.IsValidLabelValue(v) { allErrs = append(allErrs, field.Invalid(fldPath, v, msg)) } } return allErrs }
// hasHostPort checks the port definitions on the container for HostPort > 0. func (s *simpleProvider) hasInvalidHostPort(container *api.Container, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, cp := range container.Ports { if cp.HostPort > 0 && !s.isValidHostPort(int(cp.HostPort)) { detail := fmt.Sprintf("Host port %d is not allowed to be used. Allowed ports: %v", cp.HostPort, s.psp.Spec.HostPorts) allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPort"), cp.HostPort, detail)) } } return allErrs }