rebase: update kubernetes to 1.30

updating kubernetes to 1.30 release

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
Madhu Rajanna
2024-05-15 08:54:18 +02:00
committed by mergify[bot]
parent 62ddcf715b
commit e727bd351e
747 changed files with 73809 additions and 10436 deletions

View File

@ -51,6 +51,9 @@ const (
// to the pod, which don't count towards the backoff limit, according to the
// pod failure policy. When the annotation is absent zero is implied.
JobIndexIgnoredFailureCountAnnotation = labelPrefix + "job-index-ignored-failure-count"
// JobControllerName reserved value for the managedBy field for the built-in
// Job controller.
JobControllerName = "kubernetes.io/job-controller"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@ -256,6 +259,51 @@ type PodFailurePolicy struct {
Rules []PodFailurePolicyRule
}
// SuccessPolicy describes when a Job can be declared as succeeded based on the success of some indexes.
type SuccessPolicy struct {
// rules represents the list of alternative rules for the declaring the Jobs
// as successful before `.status.succeeded >= .spec.completions`. Once any of the rules are met,
// the "SucceededCriteriaMet" condition is added, and the lingering pods are removed.
// The terminal state for such a Job has the "Complete" condition.
// Additionally, these rules are evaluated in order; Once the Job meets one of the rules,
// other rules are ignored. At most 20 elements are allowed.
// +listType=atomic
Rules []SuccessPolicyRule
}
// SuccessPolicyRule describes rule for declaring a Job as succeeded.
// Each rule must have at least one of the "succeededIndexes" or "succeededCount" specified.
type SuccessPolicyRule struct {
// succeededIndexes specifies the set of indexes
// which need to be contained in the actual set of the succeeded indexes for the Job.
// The list of indexes must be within 0 to ".spec.completions-1" and
// must not contain duplicates. At least one element is required.
// The indexes are represented as intervals separated by commas.
// The intervals can be a decimal integer or a pair of decimal integers separated by a hyphen.
// The number are listed in represented by the first and last element of the series,
// separated by a hyphen.
// For example, if the completed indexes are 1, 3, 4, 5 and 7, they are
// represented as "1,3-5,7".
// When this field is null, this field doesn't default to any value
// and is never evaluated at any time.
//
// +optional
SucceededIndexes *string
// succeededCount specifies the minimal required size of the actual set of the succeeded indexes
// for the Job. When succeededCount is used along with succeededIndexes, the check is
// constrained only to the set of indexes specified by succeededIndexes.
// For example, given that succeededIndexes is "1-4", succeededCount is "3",
// and completed indexes are "1", "3", and "5", the Job isn't declared as succeeded
// because only "1" and "3" indexes are considered in that rules.
// When this field is null, this doesn't default to any value and
// is never evaluated at any time.
// When specified it needs to be a positive integer.
//
// +optional
SucceededCount *int32
}
// JobSpec describes how the job execution will look like.
type JobSpec struct {
@ -287,6 +335,17 @@ type JobSpec struct {
// +optional
PodFailurePolicy *PodFailurePolicy
// successPolicy specifies the policy when the Job can be declared as succeeded.
// If empty, the default behavior applies - the Job is declared as succeeded
// only when the number of succeeded pods equals to the completions.
// When the field is specified, it must be immutable and works only for the Indexed Jobs.
// Once the Job meets the SuccessPolicy, the lingering pods are terminated.
//
// This field is alpha-level. To use this field, you must enable the
// `JobSuccessPolicy` feature gate (disabled by default).
// +optional
SuccessPolicy *SuccessPolicy
// Specifies the duration in seconds relative to the startTime that the job
// may be continuously active before the system tries to terminate it; value
// must be positive integer. If a Job is suspended (at creation or through an
@ -409,6 +468,20 @@ type JobSpec struct {
// This is on by default.
// +optional
PodReplacementPolicy *PodReplacementPolicy
// ManagedBy field indicates the controller that manages a Job. The k8s Job
// controller reconciles jobs which don't have this field at all or the field
// value is the reserved string `kubernetes.io/job-controller`, but skips
// reconciling Jobs with a custom value for this field.
// The value must be a valid domain-prefixed path (e.g. acme.io/foo) -
// all characters before the first "/" must be a valid subdomain as defined
// by RFC 1123. All characters trailing the first "/" must be valid HTTP Path
// characters as defined by RFC 3986. The value cannot exceed 64 characters.
//
// This field is alpha-level. The job controller accepts setting the field
// when the feature gate JobManagedBy is enabled (disabled by default).
// +optional
ManagedBy *string
}
// JobStatus represents the current state of a Job.
@ -420,6 +493,12 @@ type JobStatus struct {
// status true; when the Job is resumed, the status of this condition will
// become false. When a Job is completed, one of the conditions will have
// type "Complete" and status true.
//
// A job is considered finished when it is in a terminal condition, either
// "Complete" or "Failed". A Job cannot have both the "Complete" and "Failed" conditions.
// Additionally, it cannot be in the "Complete" and "FailureTarget" conditions.
// The "Complete", "Failed" and "FailureTarget" conditions cannot be disabled.
//
// +optional
Conditions []JobCondition
@ -427,17 +506,25 @@ type JobStatus struct {
// Job is created in the suspended state, this field is not set until the
// first time it is resumed. This field is reset every time a Job is resumed
// from suspension. It is represented in RFC3339 form and is in UTC.
//
// Once set, the field can only be removed when the job is suspended.
// The field cannot be modified while the job is unsuspended or finished.
//
// +optional
StartTime *metav1.Time
// Represents time when the job was completed. It is not guaranteed to
// be set in happens-before order across separate operations.
// It is represented in RFC3339 form and is in UTC.
// The completion time is only set when the job finishes successfully.
// The completion time is set when the job finishes successfully, and only then.
// The value cannot be updated or removed. The value indicates the same or
// later point in time as the startTime field.
// +optional
CompletionTime *metav1.Time
// The number of pending and running pods.
// The number of pending and running pods which are not terminating (without
// a deletionTimestamp).
// The value is zero for finished jobs.
// +optional
Active int32
@ -454,10 +541,13 @@ type JobStatus struct {
Ready *int32
// The number of pods which reached phase Succeeded.
// The value increases monotonically for a given spec. However, it may
// decrease in reaction to scale down of elastic indexed jobs.
// +optional
Succeeded int32
// The number of pods which reached phase Failed.
// The value increases monotonically.
// +optional
Failed int32
@ -471,7 +561,7 @@ type JobStatus struct {
// +optional
CompletedIndexes string
// FailedIndexes holds the failed indexes when backoffLimitPerIndex=true.
// FailedIndexes holds the failed indexes when spec.backoffLimitPerIndex is set.
// The indexes are represented in the text format analogous as for the
// `completedIndexes` field, ie. they are kept as decimal integers
// separated by commas. The numbers are listed in increasing order. Three or
@ -479,6 +569,8 @@ type JobStatus struct {
// last element of the series, separated by a hyphen.
// For example, if the failed indexes are 1, 3, 4, 5 and 7, they are
// represented as "1,3-5,7".
// The set of failed indexes cannot overlap with the set of completed indexes.
//
// This field is beta-level. It can be used when the `JobBackoffLimitPerIndex`
// feature gate is enabled (enabled by default).
// +optional
@ -498,6 +590,7 @@ type JobStatus struct {
//
// Old jobs might not be tracked using this field, in which case the field
// remains null.
// The structure is empty for finished jobs.
// +optional
UncountedTerminatedPods *UncountedTerminatedPods
}
@ -529,6 +622,8 @@ const (
JobFailed JobConditionType = "Failed"
// FailureTarget means the job is about to fail its execution.
JobFailureTarget JobConditionType = "FailureTarget"
// JobSuccessCriteriaMet means the Job has reached a success state and will be marked as Completed
JobSuccessCriteriaMet JobConditionType = "SuccessCriteriaMet"
)
// JobCondition describes current state of a job.

View File

@ -257,6 +257,11 @@ func (in *JobSpec) DeepCopyInto(out *JobSpec) {
*out = new(PodFailurePolicy)
(*in).DeepCopyInto(*out)
}
if in.SuccessPolicy != nil {
in, out := &in.SuccessPolicy, &out.SuccessPolicy
*out = new(SuccessPolicy)
(*in).DeepCopyInto(*out)
}
if in.ActiveDeadlineSeconds != nil {
in, out := &in.ActiveDeadlineSeconds, &out.ActiveDeadlineSeconds
*out = new(int64)
@ -308,6 +313,11 @@ func (in *JobSpec) DeepCopyInto(out *JobSpec) {
*out = new(PodReplacementPolicy)
**out = **in
}
if in.ManagedBy != nil {
in, out := &in.ManagedBy, &out.ManagedBy
*out = new(string)
**out = **in
}
return
}
@ -481,6 +491,55 @@ func (in *PodFailurePolicyRule) DeepCopy() *PodFailurePolicyRule {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SuccessPolicy) DeepCopyInto(out *SuccessPolicy) {
*out = *in
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]SuccessPolicyRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SuccessPolicy.
func (in *SuccessPolicy) DeepCopy() *SuccessPolicy {
if in == nil {
return nil
}
out := new(SuccessPolicy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SuccessPolicyRule) DeepCopyInto(out *SuccessPolicyRule) {
*out = *in
if in.SucceededIndexes != nil {
in, out := &in.SucceededIndexes, &out.SucceededIndexes
*out = new(string)
**out = **in
}
if in.SucceededCount != nil {
in, out := &in.SucceededCount, &out.SucceededCount
*out = new(int32)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SuccessPolicyRule.
func (in *SuccessPolicyRule) DeepCopy() *SuccessPolicyRule {
if in == nil {
return nil
}
out := new(SuccessPolicyRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UncountedTerminatedPods) DeepCopyInto(out *UncountedTerminatedPods) {
*out = *in

View File

@ -52,6 +52,19 @@ const (
// Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead.
DeprecatedSeccompProfileDockerDefault string = "docker/default"
// DeprecatedAppArmorAnnotationKeyPrefix is the prefix to an annotation key specifying a container's apparmor profile.
// Deprecated: use a pod or container security context `appArmorProfile` field instead.
DeprecatedAppArmorAnnotationKeyPrefix = "container.apparmor.security.beta.kubernetes.io/"
// DeprecatedAppArmorAnnotationValueRuntimeDefault is the profile specifying the runtime default.
DeprecatedAppArmorAnnotationValueRuntimeDefault = "runtime/default"
// DeprecatedAppArmorAnnotationValueLocalhostPrefix is the prefix for specifying profiles loaded on the node.
DeprecatedAppArmorAnnotationValueLocalhostPrefix = "localhost/"
// DeprecatedAppArmorAnnotationValueUnconfined is the Unconfined AppArmor profile
DeprecatedAppArmorAnnotationValueUnconfined = "unconfined"
// PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized)
// in the Annotations of a Node.
PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods"

View File

@ -508,7 +508,7 @@ type PersistentVolumeClaimSpec struct {
// If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
// set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
// exists.
// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass
// More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
// (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled.
// +featureGate=VolumeAttributesClass
// +optional
@ -2011,6 +2011,26 @@ type VolumeMount struct {
// Optional: Defaults to false (read-write).
// +optional
ReadOnly bool
// RecursiveReadOnly specifies whether read-only mounts should be handled
// recursively.
//
// If ReadOnly is false, this field has no meaning and must be unspecified.
//
// If ReadOnly is true, and this field is set to Disabled, the mount is not made
// recursively read-only. If this field is set to IfPossible, the mount is made
// recursively read-only, if it is supported by the container runtime. If this
// field is set to Enabled, the mount is made recursively read-only if it is
// supported by the container runtime, otherwise the pod will not be started and
// an error will be generated to indicate the reason.
//
// If this field is set to IfPossible or Enabled, MountPropagation must be set to
// None (or be unspecified, which defaults to None).
//
// If this field is not specified, it is treated as an equivalent of Disabled.
//
// +featureGate=RecursiveReadOnlyMounts
// +optional
RecursiveReadOnly *RecursiveReadOnlyMode
// Required. If the path is not an absolute path (e.g. some/path) it
// will be prepended with the appropriate root prefix for the operating
// system. On Linux this is '/', on Windows this is 'C:\'.
@ -2023,6 +2043,8 @@ type VolumeMount struct {
// to container and the other way around.
// When not set, MountPropagationNone is used.
// This field is beta in 1.10.
// When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified
// (which defaults to None).
// +optional
MountPropagation *MountPropagationMode
// Expanded path within the volume from which the container's volume should be mounted.
@ -2058,6 +2080,18 @@ const (
MountPropagationBidirectional MountPropagationMode = "Bidirectional"
)
// RecursiveReadOnlyMode describes recursive-readonly mode.
type RecursiveReadOnlyMode string
const (
// RecursiveReadOnlyDisabled disables recursive-readonly mode.
RecursiveReadOnlyDisabled RecursiveReadOnlyMode = "Disabled"
// RecursiveReadOnlyIfPossible enables recursive-readonly mode if possible.
RecursiveReadOnlyIfPossible RecursiveReadOnlyMode = "IfPossible"
// RecursiveReadOnlyEnabled enables recursive-readonly mode, or raise an error.
RecursiveReadOnlyEnabled RecursiveReadOnlyMode = "Enabled"
)
// VolumeDevice describes a mapping of a raw block device within a container.
type VolumeDevice struct {
// name must match the name of a persistentVolumeClaim in the pod
@ -2068,7 +2102,11 @@ type VolumeDevice struct {
// EnvVar represents an environment variable present in a Container.
type EnvVar struct {
// Required: This must be a C_IDENTIFIER.
// Required: Name of the environment variable.
// When the RelaxedEnvironmentVariableValidation feature gate is disabled, this must consist of alphabetic characters,
// digits, '_', '-', or '.', and must not start with a digit.
// When the RelaxedEnvironmentVariableValidation feature gate is enabled,
// this may contain any printable ASCII characters except '='.
Name string
// Optional: no more than one of the following may be specified.
// Optional: Defaults to ""; variable references $(VAR_NAME) are expanded
@ -2698,6 +2736,11 @@ type ContainerStatus struct {
// +featureGate=InPlacePodVerticalScaling
// +optional
Resources *ResourceRequirements
// Status of volume mounts.
// +listType=atomic
// +optional
// +featureGate=RecursiveReadOnlyMounts
VolumeMounts []VolumeMountStatus
}
// PodPhase is a label for the condition of a pod at the current time.
@ -2771,6 +2814,23 @@ const (
PodResizeStatusInfeasible PodResizeStatus = "Infeasible"
)
// VolumeMountStatus shows status of volume mounts.
type VolumeMountStatus struct {
// Name corresponds to the name of the original VolumeMount.
Name string
// MountPath corresponds to the original VolumeMount.
MountPath string
// ReadOnly corresponds to the original VolumeMount.
// +optional
ReadOnly bool
// RecursiveReadOnly must be set to Disabled, Enabled, or unspecified (for non-readonly mounts).
// An IfPossible value in the original VolumeMount must be translated to Disabled or Enabled,
// depending on the mount result.
// +featureGate=RecursiveReadOnlyMounts
// +optional
RecursiveReadOnly *RecursiveReadOnlyMode
}
// RestartPolicy describes how the container should be restarted.
// Only one of the following restart policies may be specified.
// If none of the following policies is specified, the default one
@ -3255,7 +3315,7 @@ type PodSpec struct {
// +optional
Tolerations []Toleration
// HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts
// file if specified. This is only valid for non-hostNetwork pods.
// file if specified.
// +optional
HostAliases []HostAlias
// If specified, indicates the pod's priority. "system-node-critical" and
@ -3325,6 +3385,7 @@ type PodSpec struct {
// - spec.hostPID
// - spec.hostIPC
// - spec.hostUsers
// - spec.securityContext.appArmorProfile
// - spec.securityContext.seLinuxOptions
// - spec.securityContext.seccompProfile
// - spec.securityContext.fsGroup
@ -3334,6 +3395,7 @@ type PodSpec struct {
// - spec.securityContext.runAsUser
// - spec.securityContext.runAsGroup
// - spec.securityContext.supplementalGroups
// - spec.containers[*].securityContext.appArmorProfile
// - spec.containers[*].securityContext.seLinuxOptions
// - spec.containers[*].securityContext.seccompProfile
// - spec.containers[*].securityContext.capabilities
@ -3352,9 +3414,6 @@ type PodSpec struct {
//
// SchedulingGates can only be set at pod creation time, and be removed only afterwards.
//
// This is a beta feature enabled by the PodSchedulingReadiness feature gate.
//
// +featureGate=PodSchedulingReadiness
// +optional
SchedulingGates []PodSchedulingGate
// ResourceClaims defines which ResourceClaims must be allocated
@ -3601,6 +3660,10 @@ type PodSecurityContext struct {
// Note that this field cannot be set when spec.os.name is windows.
// +optional
SeccompProfile *SeccompProfile
// appArmorProfile is the AppArmor options to use by the containers in this pod.
// Note that this field cannot be set when spec.os.name is windows.
// +optional
AppArmorProfile *AppArmorProfile
}
// SeccompProfile defines a pod/container's seccomp profile settings.
@ -3628,6 +3691,38 @@ const (
SeccompProfileTypeLocalhost SeccompProfileType = "Localhost"
)
// AppArmorProfile defines a pod or container's AppArmor settings.
// +union
type AppArmorProfile struct {
// type indicates which kind of AppArmor profile will be applied.
// Valid options are:
// Localhost - a profile pre-loaded on the node.
// RuntimeDefault - the container runtime's default profile.
// Unconfined - no AppArmor enforcement.
// +unionDescriminator
Type AppArmorProfileType
// localhostProfile indicates a profile loaded on the node that should be used.
// The profile must be preconfigured on the node to work.
// Must match the loaded name of the profile.
// Must be set if and only if type is "Localhost".
// +optional
LocalhostProfile *string
}
// +enum
type AppArmorProfileType string
const (
// AppArmorProfileTypeUnconfined indicates that no AppArmor profile should be enforced.
AppArmorProfileTypeUnconfined AppArmorProfileType = "Unconfined"
// AppArmorProfileTypeRuntimeDefault indicates that the container runtime's default AppArmor
// profile should be used.
AppArmorProfileTypeRuntimeDefault AppArmorProfileType = "RuntimeDefault"
// AppArmorProfileTypeLocalhost indicates that a profile pre-loaded on the node should be used.
AppArmorProfileTypeLocalhost AppArmorProfileType = "Localhost"
)
// PodQOSClass defines the supported qos classes of Pods.
type PodQOSClass string
@ -4166,6 +4261,18 @@ const (
ServiceExternalTrafficPolicyLocal ServiceExternalTrafficPolicy = "Local"
)
// These are valid values for the TrafficDistribution field of a Service.
const (
// Indicates a preference for routing traffic to endpoints that are
// topologically proximate to the client. The interpretation of "topologically
// proximate" may vary across implementations and could encompass endpoints
// within the same node, rack, zone, or even region. Setting this value gives
// implementations permission to make different tradeoffs, e.g. optimizing for
// proximity rather than equal distribution of load. Users should not set this
// value if such tradeoffs are not acceptable.
ServiceTrafficDistributionPreferClose = "PreferClose"
)
// These are the valid conditions of a service.
const (
// LoadBalancerPortsError represents the condition of the requested ports
@ -4429,6 +4536,15 @@ type ServiceSpec struct {
// (possibly modified by topology and other features).
// +optional
InternalTrafficPolicy *ServiceInternalTrafficPolicy
// TrafficDistribution offers a way to express preferences for how traffic is
// distributed to Service endpoints. Implementations can use this field as a
// hint, but are not required to guarantee strict adherence. If the field is
// not set, the implementation will apply its default routing strategy. If set
// to "PreferClose", implementations should prioritize endpoints that are
// topologically close (e.g., same zone).
// +optional
TrafficDistribution *string
}
// ServicePort represents the port on which the service is exposed
@ -4717,6 +4833,26 @@ type NodeDaemonEndpoints struct {
KubeletEndpoint DaemonEndpoint
}
// NodeRuntimeHandlerFeatures is a set of runtime features.
type NodeRuntimeHandlerFeatures struct {
// RecursiveReadOnlyMounts is set to true if the runtime handler supports RecursiveReadOnlyMounts.
// +featureGate=RecursiveReadOnlyMounts
// +optional
RecursiveReadOnlyMounts *bool
// Reserved: UserNamespaces *bool
}
// NodeRuntimeHandler is a set of runtime handler information.
type NodeRuntimeHandler struct {
// Runtime handler name.
// Empty for the default runtime handler.
// +optional
Name string
// Supported features.
// +optional
Features *NodeRuntimeHandlerFeatures
}
// NodeSystemInfo is a set of ids/uuids to uniquely identify the node.
type NodeSystemInfo struct {
// MachineID reported by the node. For unique machine identification
@ -4827,6 +4963,10 @@ type NodeStatus struct {
// Status of the config assigned to the node via the dynamic Kubelet config feature.
// +optional
Config *NodeConfigStatus
// The available runtime handlers.
// +featureGate=RecursiveReadOnlyMounts
// +optional
RuntimeHandlers []NodeRuntimeHandler
}
// UniqueVolumeName defines the name of attached volume
@ -4900,9 +5040,8 @@ const (
// NodeConditionType defines node's condition
type NodeConditionType string
// These are valid conditions of node. Currently, we don't have enough information to decide
// node condition. In the future, we will add more. The proposed set of conditions are:
// NodeReady, NodeReachable
// These are valid but not exhaustive conditions of node. A cloud provider may set a condition not listed here.
// Relevant events contain "NodeReady", "NodeNotReady", "NodeSchedulable", and "NodeNotSchedulable".
const (
// NodeReady means kubelet is healthy and ready to accept pods.
NodeReady NodeConditionType = "Ready"
@ -4979,14 +5118,6 @@ type NodeAddress struct {
Address string
}
// NodeResources is an object for conveying resource information about a node.
// see https://kubernetes.io/docs/concepts/architecture/nodes/#capacity for more details.
type NodeResources struct {
// Capacity represents the available resources of a node
// +optional
Capacity ResourceList
}
// ResourceName is the name identifying various resources in a ResourceList.
type ResourceName string
@ -5003,7 +5134,6 @@ const (
// Volume size, in bytes (e,g. 5Gi = 5GiB = 5 * 1024 * 1024 * 1024)
ResourceStorage ResourceName = "storage"
// Local ephemeral storage, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
// The resource name for ResourceEphemeralStorage is alpha and it can change across releases.
ResourceEphemeralStorage ResourceName = "ephemeral-storage"
)
@ -6020,6 +6150,11 @@ type SecurityContext struct {
// Note that this field cannot be set when spec.os.name is windows.
// +optional
SeccompProfile *SeccompProfile
// appArmorProfile is the AppArmor options to use by this container. If set, this profile
// overrides the pod's appArmorProfile.
// Note that this field cannot be set when spec.os.name is windows.
// +optional
AppArmorProfile *AppArmorProfile
}
// ProcMountType defines the type of proc mount
@ -6221,8 +6356,6 @@ type TopologySpreadConstraint struct {
// In this situation, new pod with the same labelSelector cannot be scheduled,
// because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones,
// it will violate MaxSkew.
//
// This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default).
// +optional
MinDomains *int32
// NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector

View File

@ -62,6 +62,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.AppArmorProfile)(nil), (*core.AppArmorProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AppArmorProfile_To_core_AppArmorProfile(a.(*v1.AppArmorProfile), b.(*core.AppArmorProfile), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.AppArmorProfile)(nil), (*v1.AppArmorProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_AppArmorProfile_To_v1_AppArmorProfile(a.(*core.AppArmorProfile), b.(*v1.AppArmorProfile), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.AttachedVolume)(nil), (*core.AttachedVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AttachedVolume_To_core_AttachedVolume(a.(*v1.AttachedVolume), b.(*core.AttachedVolume), scope)
}); err != nil {
@ -1052,13 +1062,23 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodeResources)(nil), (*core.NodeResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodeResources_To_core_NodeResources(a.(*v1.NodeResources), b.(*core.NodeResources), scope)
if err := s.AddGeneratedConversionFunc((*v1.NodeRuntimeHandler)(nil), (*core.NodeRuntimeHandler)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodeRuntimeHandler_To_core_NodeRuntimeHandler(a.(*v1.NodeRuntimeHandler), b.(*core.NodeRuntimeHandler), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.NodeResources)(nil), (*v1.NodeResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_NodeResources_To_v1_NodeResources(a.(*core.NodeResources), b.(*v1.NodeResources), scope)
if err := s.AddGeneratedConversionFunc((*core.NodeRuntimeHandler)(nil), (*v1.NodeRuntimeHandler)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_NodeRuntimeHandler_To_v1_NodeRuntimeHandler(a.(*core.NodeRuntimeHandler), b.(*v1.NodeRuntimeHandler), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodeRuntimeHandlerFeatures)(nil), (*core.NodeRuntimeHandlerFeatures)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodeRuntimeHandlerFeatures_To_core_NodeRuntimeHandlerFeatures(a.(*v1.NodeRuntimeHandlerFeatures), b.(*core.NodeRuntimeHandlerFeatures), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.NodeRuntimeHandlerFeatures)(nil), (*v1.NodeRuntimeHandlerFeatures)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_NodeRuntimeHandlerFeatures_To_v1_NodeRuntimeHandlerFeatures(a.(*core.NodeRuntimeHandlerFeatures), b.(*v1.NodeRuntimeHandlerFeatures), scope)
}); err != nil {
return err
}
@ -2097,6 +2117,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.VolumeMountStatus)(nil), (*core.VolumeMountStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_VolumeMountStatus_To_core_VolumeMountStatus(a.(*v1.VolumeMountStatus), b.(*core.VolumeMountStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.VolumeMountStatus)(nil), (*v1.VolumeMountStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_VolumeMountStatus_To_v1_VolumeMountStatus(a.(*core.VolumeMountStatus), b.(*v1.VolumeMountStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.VolumeNodeAffinity)(nil), (*core.VolumeNodeAffinity)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_VolumeNodeAffinity_To_core_VolumeNodeAffinity(a.(*v1.VolumeNodeAffinity), b.(*core.VolumeNodeAffinity), scope)
}); err != nil {
@ -2385,6 +2415,28 @@ func Convert_core_Affinity_To_v1_Affinity(in *core.Affinity, out *v1.Affinity, s
return autoConvert_core_Affinity_To_v1_Affinity(in, out, s)
}
func autoConvert_v1_AppArmorProfile_To_core_AppArmorProfile(in *v1.AppArmorProfile, out *core.AppArmorProfile, s conversion.Scope) error {
out.Type = core.AppArmorProfileType(in.Type)
out.LocalhostProfile = (*string)(unsafe.Pointer(in.LocalhostProfile))
return nil
}
// Convert_v1_AppArmorProfile_To_core_AppArmorProfile is an autogenerated conversion function.
func Convert_v1_AppArmorProfile_To_core_AppArmorProfile(in *v1.AppArmorProfile, out *core.AppArmorProfile, s conversion.Scope) error {
return autoConvert_v1_AppArmorProfile_To_core_AppArmorProfile(in, out, s)
}
func autoConvert_core_AppArmorProfile_To_v1_AppArmorProfile(in *core.AppArmorProfile, out *v1.AppArmorProfile, s conversion.Scope) error {
out.Type = v1.AppArmorProfileType(in.Type)
out.LocalhostProfile = (*string)(unsafe.Pointer(in.LocalhostProfile))
return nil
}
// Convert_core_AppArmorProfile_To_v1_AppArmorProfile is an autogenerated conversion function.
func Convert_core_AppArmorProfile_To_v1_AppArmorProfile(in *core.AppArmorProfile, out *v1.AppArmorProfile, s conversion.Scope) error {
return autoConvert_core_AppArmorProfile_To_v1_AppArmorProfile(in, out, s)
}
func autoConvert_v1_AttachedVolume_To_core_AttachedVolume(in *v1.AttachedVolume, out *core.AttachedVolume, s conversion.Scope) error {
out.Name = core.UniqueVolumeName(in.Name)
out.DevicePath = in.DevicePath
@ -3317,6 +3369,7 @@ func autoConvert_v1_ContainerStatus_To_core_ContainerStatus(in *v1.ContainerStat
out.Started = (*bool)(unsafe.Pointer(in.Started))
out.AllocatedResources = *(*core.ResourceList)(unsafe.Pointer(&in.AllocatedResources))
out.Resources = (*core.ResourceRequirements)(unsafe.Pointer(in.Resources))
out.VolumeMounts = *(*[]core.VolumeMountStatus)(unsafe.Pointer(&in.VolumeMounts))
return nil
}
@ -3341,6 +3394,7 @@ func autoConvert_core_ContainerStatus_To_v1_ContainerStatus(in *core.ContainerSt
out.Started = (*bool)(unsafe.Pointer(in.Started))
out.AllocatedResources = *(*v1.ResourceList)(unsafe.Pointer(&in.AllocatedResources))
out.Resources = (*v1.ResourceRequirements)(unsafe.Pointer(in.Resources))
out.VolumeMounts = *(*[]v1.VolumeMountStatus)(unsafe.Pointer(&in.VolumeMounts))
return nil
}
@ -5049,24 +5103,46 @@ func Convert_url_Values_To_v1_NodeProxyOptions(in *url.Values, out *v1.NodeProxy
return autoConvert_url_Values_To_v1_NodeProxyOptions(in, out, s)
}
func autoConvert_v1_NodeResources_To_core_NodeResources(in *v1.NodeResources, out *core.NodeResources, s conversion.Scope) error {
out.Capacity = *(*core.ResourceList)(unsafe.Pointer(&in.Capacity))
func autoConvert_v1_NodeRuntimeHandler_To_core_NodeRuntimeHandler(in *v1.NodeRuntimeHandler, out *core.NodeRuntimeHandler, s conversion.Scope) error {
out.Name = in.Name
out.Features = (*core.NodeRuntimeHandlerFeatures)(unsafe.Pointer(in.Features))
return nil
}
// Convert_v1_NodeResources_To_core_NodeResources is an autogenerated conversion function.
func Convert_v1_NodeResources_To_core_NodeResources(in *v1.NodeResources, out *core.NodeResources, s conversion.Scope) error {
return autoConvert_v1_NodeResources_To_core_NodeResources(in, out, s)
// Convert_v1_NodeRuntimeHandler_To_core_NodeRuntimeHandler is an autogenerated conversion function.
func Convert_v1_NodeRuntimeHandler_To_core_NodeRuntimeHandler(in *v1.NodeRuntimeHandler, out *core.NodeRuntimeHandler, s conversion.Scope) error {
return autoConvert_v1_NodeRuntimeHandler_To_core_NodeRuntimeHandler(in, out, s)
}
func autoConvert_core_NodeResources_To_v1_NodeResources(in *core.NodeResources, out *v1.NodeResources, s conversion.Scope) error {
out.Capacity = *(*v1.ResourceList)(unsafe.Pointer(&in.Capacity))
func autoConvert_core_NodeRuntimeHandler_To_v1_NodeRuntimeHandler(in *core.NodeRuntimeHandler, out *v1.NodeRuntimeHandler, s conversion.Scope) error {
out.Name = in.Name
out.Features = (*v1.NodeRuntimeHandlerFeatures)(unsafe.Pointer(in.Features))
return nil
}
// Convert_core_NodeResources_To_v1_NodeResources is an autogenerated conversion function.
func Convert_core_NodeResources_To_v1_NodeResources(in *core.NodeResources, out *v1.NodeResources, s conversion.Scope) error {
return autoConvert_core_NodeResources_To_v1_NodeResources(in, out, s)
// Convert_core_NodeRuntimeHandler_To_v1_NodeRuntimeHandler is an autogenerated conversion function.
func Convert_core_NodeRuntimeHandler_To_v1_NodeRuntimeHandler(in *core.NodeRuntimeHandler, out *v1.NodeRuntimeHandler, s conversion.Scope) error {
return autoConvert_core_NodeRuntimeHandler_To_v1_NodeRuntimeHandler(in, out, s)
}
func autoConvert_v1_NodeRuntimeHandlerFeatures_To_core_NodeRuntimeHandlerFeatures(in *v1.NodeRuntimeHandlerFeatures, out *core.NodeRuntimeHandlerFeatures, s conversion.Scope) error {
out.RecursiveReadOnlyMounts = (*bool)(unsafe.Pointer(in.RecursiveReadOnlyMounts))
return nil
}
// Convert_v1_NodeRuntimeHandlerFeatures_To_core_NodeRuntimeHandlerFeatures is an autogenerated conversion function.
func Convert_v1_NodeRuntimeHandlerFeatures_To_core_NodeRuntimeHandlerFeatures(in *v1.NodeRuntimeHandlerFeatures, out *core.NodeRuntimeHandlerFeatures, s conversion.Scope) error {
return autoConvert_v1_NodeRuntimeHandlerFeatures_To_core_NodeRuntimeHandlerFeatures(in, out, s)
}
func autoConvert_core_NodeRuntimeHandlerFeatures_To_v1_NodeRuntimeHandlerFeatures(in *core.NodeRuntimeHandlerFeatures, out *v1.NodeRuntimeHandlerFeatures, s conversion.Scope) error {
out.RecursiveReadOnlyMounts = (*bool)(unsafe.Pointer(in.RecursiveReadOnlyMounts))
return nil
}
// Convert_core_NodeRuntimeHandlerFeatures_To_v1_NodeRuntimeHandlerFeatures is an autogenerated conversion function.
func Convert_core_NodeRuntimeHandlerFeatures_To_v1_NodeRuntimeHandlerFeatures(in *core.NodeRuntimeHandlerFeatures, out *v1.NodeRuntimeHandlerFeatures, s conversion.Scope) error {
return autoConvert_core_NodeRuntimeHandlerFeatures_To_v1_NodeRuntimeHandlerFeatures(in, out, s)
}
func autoConvert_v1_NodeSelector_To_core_NodeSelector(in *v1.NodeSelector, out *core.NodeSelector, s conversion.Scope) error {
@ -5172,6 +5248,7 @@ func autoConvert_v1_NodeStatus_To_core_NodeStatus(in *v1.NodeStatus, out *core.N
out.VolumesInUse = *(*[]core.UniqueVolumeName)(unsafe.Pointer(&in.VolumesInUse))
out.VolumesAttached = *(*[]core.AttachedVolume)(unsafe.Pointer(&in.VolumesAttached))
out.Config = (*core.NodeConfigStatus)(unsafe.Pointer(in.Config))
out.RuntimeHandlers = *(*[]core.NodeRuntimeHandler)(unsafe.Pointer(&in.RuntimeHandlers))
return nil
}
@ -5196,6 +5273,7 @@ func autoConvert_core_NodeStatus_To_v1_NodeStatus(in *core.NodeStatus, out *v1.N
out.VolumesInUse = *(*[]v1.UniqueVolumeName)(unsafe.Pointer(&in.VolumesInUse))
out.VolumesAttached = *(*[]v1.AttachedVolume)(unsafe.Pointer(&in.VolumesAttached))
out.Config = (*v1.NodeConfigStatus)(unsafe.Pointer(in.Config))
out.RuntimeHandlers = *(*[]v1.NodeRuntimeHandler)(unsafe.Pointer(&in.RuntimeHandlers))
return nil
}
@ -6412,6 +6490,7 @@ func autoConvert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecu
out.Sysctls = *(*[]core.Sysctl)(unsafe.Pointer(&in.Sysctls))
out.FSGroupChangePolicy = (*core.PodFSGroupChangePolicy)(unsafe.Pointer(in.FSGroupChangePolicy))
out.SeccompProfile = (*core.SeccompProfile)(unsafe.Pointer(in.SeccompProfile))
out.AppArmorProfile = (*core.AppArmorProfile)(unsafe.Pointer(in.AppArmorProfile))
return nil
}
@ -6436,6 +6515,7 @@ func autoConvert_core_PodSecurityContext_To_v1_PodSecurityContext(in *core.PodSe
out.FSGroupChangePolicy = (*v1.PodFSGroupChangePolicy)(unsafe.Pointer(in.FSGroupChangePolicy))
out.Sysctls = *(*[]v1.Sysctl)(unsafe.Pointer(&in.Sysctls))
out.SeccompProfile = (*v1.SeccompProfile)(unsafe.Pointer(in.SeccompProfile))
out.AppArmorProfile = (*v1.AppArmorProfile)(unsafe.Pointer(in.AppArmorProfile))
return nil
}
@ -7789,6 +7869,7 @@ func autoConvert_v1_SecurityContext_To_core_SecurityContext(in *v1.SecurityConte
out.AllowPrivilegeEscalation = (*bool)(unsafe.Pointer(in.AllowPrivilegeEscalation))
out.ProcMount = (*core.ProcMountType)(unsafe.Pointer(in.ProcMount))
out.SeccompProfile = (*core.SeccompProfile)(unsafe.Pointer(in.SeccompProfile))
out.AppArmorProfile = (*core.AppArmorProfile)(unsafe.Pointer(in.AppArmorProfile))
return nil
}
@ -7809,6 +7890,7 @@ func autoConvert_core_SecurityContext_To_v1_SecurityContext(in *core.SecurityCon
out.AllowPrivilegeEscalation = (*bool)(unsafe.Pointer(in.AllowPrivilegeEscalation))
out.ProcMount = (*v1.ProcMountType)(unsafe.Pointer(in.ProcMount))
out.SeccompProfile = (*v1.SeccompProfile)(unsafe.Pointer(in.SeccompProfile))
out.AppArmorProfile = (*v1.AppArmorProfile)(unsafe.Pointer(in.AppArmorProfile))
return nil
}
@ -8079,6 +8161,7 @@ func autoConvert_v1_ServiceSpec_To_core_ServiceSpec(in *v1.ServiceSpec, out *cor
out.AllocateLoadBalancerNodePorts = (*bool)(unsafe.Pointer(in.AllocateLoadBalancerNodePorts))
out.LoadBalancerClass = (*string)(unsafe.Pointer(in.LoadBalancerClass))
out.InternalTrafficPolicy = (*core.ServiceInternalTrafficPolicy)(unsafe.Pointer(in.InternalTrafficPolicy))
out.TrafficDistribution = (*string)(unsafe.Pointer(in.TrafficDistribution))
return nil
}
@ -8107,6 +8190,7 @@ func autoConvert_core_ServiceSpec_To_v1_ServiceSpec(in *core.ServiceSpec, out *v
out.AllocateLoadBalancerNodePorts = (*bool)(unsafe.Pointer(in.AllocateLoadBalancerNodePorts))
out.LoadBalancerClass = (*string)(unsafe.Pointer(in.LoadBalancerClass))
out.InternalTrafficPolicy = (*v1.ServiceInternalTrafficPolicy)(unsafe.Pointer(in.InternalTrafficPolicy))
out.TrafficDistribution = (*string)(unsafe.Pointer(in.TrafficDistribution))
return nil
}
@ -8502,6 +8586,7 @@ func Convert_core_VolumeDevice_To_v1_VolumeDevice(in *core.VolumeDevice, out *v1
func autoConvert_v1_VolumeMount_To_core_VolumeMount(in *v1.VolumeMount, out *core.VolumeMount, s conversion.Scope) error {
out.Name = in.Name
out.ReadOnly = in.ReadOnly
out.RecursiveReadOnly = (*core.RecursiveReadOnlyMode)(unsafe.Pointer(in.RecursiveReadOnly))
out.MountPath = in.MountPath
out.SubPath = in.SubPath
out.MountPropagation = (*core.MountPropagationMode)(unsafe.Pointer(in.MountPropagation))
@ -8517,6 +8602,7 @@ func Convert_v1_VolumeMount_To_core_VolumeMount(in *v1.VolumeMount, out *core.Vo
func autoConvert_core_VolumeMount_To_v1_VolumeMount(in *core.VolumeMount, out *v1.VolumeMount, s conversion.Scope) error {
out.Name = in.Name
out.ReadOnly = in.ReadOnly
out.RecursiveReadOnly = (*v1.RecursiveReadOnlyMode)(unsafe.Pointer(in.RecursiveReadOnly))
out.MountPath = in.MountPath
out.SubPath = in.SubPath
out.MountPropagation = (*v1.MountPropagationMode)(unsafe.Pointer(in.MountPropagation))
@ -8529,6 +8615,32 @@ func Convert_core_VolumeMount_To_v1_VolumeMount(in *core.VolumeMount, out *v1.Vo
return autoConvert_core_VolumeMount_To_v1_VolumeMount(in, out, s)
}
func autoConvert_v1_VolumeMountStatus_To_core_VolumeMountStatus(in *v1.VolumeMountStatus, out *core.VolumeMountStatus, s conversion.Scope) error {
out.Name = in.Name
out.MountPath = in.MountPath
out.ReadOnly = in.ReadOnly
out.RecursiveReadOnly = (*core.RecursiveReadOnlyMode)(unsafe.Pointer(in.RecursiveReadOnly))
return nil
}
// Convert_v1_VolumeMountStatus_To_core_VolumeMountStatus is an autogenerated conversion function.
func Convert_v1_VolumeMountStatus_To_core_VolumeMountStatus(in *v1.VolumeMountStatus, out *core.VolumeMountStatus, s conversion.Scope) error {
return autoConvert_v1_VolumeMountStatus_To_core_VolumeMountStatus(in, out, s)
}
func autoConvert_core_VolumeMountStatus_To_v1_VolumeMountStatus(in *core.VolumeMountStatus, out *v1.VolumeMountStatus, s conversion.Scope) error {
out.Name = in.Name
out.MountPath = in.MountPath
out.ReadOnly = in.ReadOnly
out.RecursiveReadOnly = (*v1.RecursiveReadOnlyMode)(unsafe.Pointer(in.RecursiveReadOnly))
return nil
}
// Convert_core_VolumeMountStatus_To_v1_VolumeMountStatus is an autogenerated conversion function.
func Convert_core_VolumeMountStatus_To_v1_VolumeMountStatus(in *core.VolumeMountStatus, out *v1.VolumeMountStatus, s conversion.Scope) error {
return autoConvert_core_VolumeMountStatus_To_v1_VolumeMountStatus(in, out, s)
}
func autoConvert_v1_VolumeNodeAffinity_To_core_VolumeNodeAffinity(in *v1.VolumeNodeAffinity, out *core.VolumeNodeAffinity, s conversion.Scope) error {
out.Required = (*core.NodeSelector)(unsafe.Pointer(in.Required))
return nil

View File

@ -204,7 +204,7 @@ func ValidatePodSpecificAnnotationUpdates(newPod, oldPod *core.Pod, fldPath *fie
if newVal, exists := newAnnotations[k]; exists && newVal == oldVal {
continue // No change.
}
if strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
if strings.HasPrefix(k, v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix) {
allErrs = append(allErrs, field.Forbidden(fldPath.Key(k), "may not remove or update AppArmor annotations"))
}
if k == core.MirrorPodAnnotationKey {
@ -216,7 +216,7 @@ func ValidatePodSpecificAnnotationUpdates(newPod, oldPod *core.Pod, fldPath *fie
if _, ok := oldAnnotations[k]; ok {
continue // No change.
}
if strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
if strings.HasPrefix(k, v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix) {
allErrs = append(allErrs, field.Forbidden(fldPath.Key(k), "may not add AppArmor annotations"))
}
if k == core.MirrorPodAnnotationKey {
@ -942,7 +942,7 @@ func validateKeyToPath(kp *core.KeyToPath, fldPath *field.Path) field.ErrorList
if len(kp.Path) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
}
allErrs = append(allErrs, validateLocalNonReservedPath(kp.Path, fldPath.Child("path"))...)
allErrs = append(allErrs, ValidateLocalNonReservedPath(kp.Path, fldPath.Child("path"))...)
if kp.Mode != nil && (*kp.Mode > 0777 || *kp.Mode < 0) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("mode"), *kp.Mode, fileModeErrorMsg))
}
@ -1050,7 +1050,7 @@ func validateDownwardAPIVolumeFile(file *core.DownwardAPIVolumeFile, fldPath *fi
if len(file.Path) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
}
allErrs = append(allErrs, validateLocalNonReservedPath(file.Path, fldPath.Child("path"))...)
allErrs = append(allErrs, ValidateLocalNonReservedPath(file.Path, fldPath.Child("path"))...)
if file.FieldRef != nil {
allErrs = append(allErrs, validateObjectFieldSelector(file.FieldRef, &validVolumeDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
if file.ResourceFieldRef != nil {
@ -1153,6 +1153,8 @@ func validateProjectionSources(projection *core.ProjectedVolumeSource, projectio
}
if source.ServiceAccountToken.Path == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
} else if !opts.AllowNonLocalProjectedTokenPath {
allErrs = append(allErrs, ValidateLocalNonReservedPath(source.ServiceAccountToken.Path, fldPath.Child("path"))...)
}
}
if projPath := srcPath.Child("clusterTrustBundlePEM"); source.ClusterTrustBundle != nil {
@ -1209,7 +1211,7 @@ func validateProjectionSources(projection *core.ProjectedVolumeSource, projectio
allErrs = append(allErrs, field.Required(projPath.Child("path"), ""))
}
allErrs = append(allErrs, validateLocalNonReservedPath(source.ClusterTrustBundle.Path, projPath.Child("path"))...)
allErrs = append(allErrs, ValidateLocalNonReservedPath(source.ClusterTrustBundle.Path, projPath.Child("path"))...)
curPath := source.ClusterTrustBundle.Path
if !allPaths.Has(curPath) {
@ -1319,11 +1321,37 @@ func validateMountPropagation(mountPropagation *core.MountPropagationMode, conta
return allErrs
}
// This validate will make sure targetPath:
// validateMountRecursiveReadOnly validates RecursiveReadOnly mounts.
func validateMountRecursiveReadOnly(mount core.VolumeMount, fldPath *field.Path) field.ErrorList {
if mount.RecursiveReadOnly == nil {
return nil
}
allErrs := field.ErrorList{}
switch *mount.RecursiveReadOnly {
case core.RecursiveReadOnlyDisabled:
// NOP
case core.RecursiveReadOnlyEnabled, core.RecursiveReadOnlyIfPossible:
if !mount.ReadOnly {
allErrs = append(allErrs, field.Forbidden(fldPath, "may only be specified when readOnly is true"))
}
if mount.MountPropagation != nil && *mount.MountPropagation != core.MountPropagationNone {
allErrs = append(allErrs, field.Forbidden(fldPath, "may only be specified when mountPropagation is None or not specified"))
}
default:
supportedRRO := sets.New(
core.RecursiveReadOnlyDisabled,
core.RecursiveReadOnlyIfPossible,
core.RecursiveReadOnlyEnabled)
allErrs = append(allErrs, field.NotSupported(fldPath, *mount.RecursiveReadOnly, sets.List(supportedRRO)))
}
return allErrs
}
// ValidateLocalNonReservedPath makes sure targetPath:
// 1. is not abs path
// 2. does not contain any '..' elements
// 3. does not start with '..'
func validateLocalNonReservedPath(targetPath string, fldPath *field.Path) field.ErrorList {
func ValidateLocalNonReservedPath(targetPath string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validateLocalDescendingPath(targetPath, fldPath)...)
// Don't report this error if the check for .. elements already caught it.
@ -2555,8 +2583,14 @@ func ValidateEnv(vars []core.EnvVar, fldPath *field.Path, opts PodValidationOpti
if len(ev.Name) == 0 {
allErrs = append(allErrs, field.Required(idxPath.Child("name"), ""))
} else {
for _, msg := range validation.IsEnvVarName(ev.Name) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, msg))
if opts.AllowRelaxedEnvironmentVariableValidation {
for _, msg := range validation.IsRelaxedEnvVarName(ev.Name) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, msg))
}
} else {
for _, msg := range validation.IsEnvVarName(ev.Name) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, msg))
}
}
}
allErrs = append(allErrs, validateEnvVarValueFrom(ev, idxPath.Child("valueFrom"), opts)...)
@ -2701,13 +2735,19 @@ func validateContainerResourceFieldSelector(fs *core.ResourceFieldSelector, expr
return allErrs
}
func ValidateEnvFrom(vars []core.EnvFromSource, fldPath *field.Path) field.ErrorList {
func ValidateEnvFrom(vars []core.EnvFromSource, fldPath *field.Path, opts PodValidationOptions) field.ErrorList {
allErrs := field.ErrorList{}
for i, ev := range vars {
idxPath := fldPath.Index(i)
if len(ev.Prefix) > 0 {
for _, msg := range validation.IsEnvVarName(ev.Prefix) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("prefix"), ev.Prefix, msg))
if opts.AllowRelaxedEnvironmentVariableValidation {
for _, msg := range validation.IsRelaxedEnvVarName(ev.Prefix) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("prefix"), ev.Prefix, msg))
}
} else {
for _, msg := range validation.IsEnvVarName(ev.Prefix) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("prefix"), ev.Prefix, msg))
}
}
}
@ -2895,6 +2935,7 @@ func ValidateVolumeMounts(mounts []core.VolumeMount, voldevices map[string]strin
if mnt.MountPropagation != nil {
allErrs = append(allErrs, validateMountPropagation(mnt.MountPropagation, container, fldPath.Child("mountPropagation"))...)
}
allErrs = append(allErrs, validateMountRecursiveReadOnly(mnt, fldPath.Child("recursiveReadOnly"))...)
}
return allErrs
}
@ -3348,7 +3389,7 @@ func validateResizePolicy(policyList []core.ContainerResizePolicy, fldPath *fiel
// validateEphemeralContainers is called by pod spec and template validation to validate the list of ephemeral containers.
// Note that this is called for pod template even though ephemeral containers aren't allowed in pod templates.
func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, containers, initContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, containers, initContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy, hostUsers bool) field.ErrorList {
var allErrs field.ErrorList
if len(ephemeralContainers) == 0 {
@ -3369,7 +3410,7 @@ func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer,
idxPath := fldPath.Index(i)
c := (*core.Container)(&ec.EphemeralContainerCommon)
allErrs = append(allErrs, validateContainerCommon(c, volumes, podClaimNames, idxPath, opts, podRestartPolicy)...)
allErrs = append(allErrs, validateContainerCommon(c, volumes, podClaimNames, idxPath, opts, podRestartPolicy, hostUsers)...)
// Ephemeral containers don't need looser constraints for pod templates, so it's convenient to apply both validations
// here where we've already converted EphemeralContainerCommon to Container.
allErrs = append(allErrs, validateContainerOnlyForPod(c, idxPath)...)
@ -3431,7 +3472,7 @@ func validateFieldAllowList(value interface{}, allowedFields map[string]bool, er
}
// validateInitContainers is called by pod spec and template validation to validate the list of init containers
func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], gracePeriod int64, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], gracePeriod int64, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy, hostUsers bool) field.ErrorList {
var allErrs field.ErrorList
allNames := sets.Set[string]{}
@ -3442,7 +3483,7 @@ func validateInitContainers(containers []core.Container, regularContainers []cor
idxPath := fldPath.Index(i)
// Apply the validation common to all container types
allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, idxPath, opts, podRestartPolicy)...)
allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, idxPath, opts, podRestartPolicy, hostUsers)...)
restartAlways := false
// Apply the validation specific to init containers
@ -3497,7 +3538,7 @@ func validateInitContainers(containers []core.Container, regularContainers []cor
// validateContainerCommon applies validation common to all container types. It's called by regular, init, and ephemeral
// container list validation to require a properly formatted name, image, etc.
func validateContainerCommon(ctr *core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], path *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
func validateContainerCommon(ctr *core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], path *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy, hostUsers bool) field.ErrorList {
var allErrs field.ErrorList
namePath := path.Child("name")
@ -3530,13 +3571,13 @@ func validateContainerCommon(ctr *core.Container, volumes map[string]core.Volume
volDevices := GetVolumeDeviceMap(ctr.VolumeDevices)
allErrs = append(allErrs, validateContainerPorts(ctr.Ports, path.Child("ports"))...)
allErrs = append(allErrs, ValidateEnv(ctr.Env, path.Child("env"), opts)...)
allErrs = append(allErrs, ValidateEnvFrom(ctr.EnvFrom, path.Child("envFrom"))...)
allErrs = append(allErrs, ValidateEnvFrom(ctr.EnvFrom, path.Child("envFrom"), opts)...)
allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volDevices, volumes, ctr, path.Child("volumeMounts"))...)
allErrs = append(allErrs, ValidateVolumeDevices(ctr.VolumeDevices, volMounts, volumes, path.Child("volumeDevices"))...)
allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, path.Child("imagePullPolicy"))...)
allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, podClaimNames, path.Child("resources"), opts)...)
allErrs = append(allErrs, validateResizePolicy(ctr.ResizePolicy, path.Child("resizePolicy"), podRestartPolicy)...)
allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, path.Child("securityContext"))...)
allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, path.Child("securityContext"), hostUsers)...)
return allErrs
}
@ -3569,7 +3610,7 @@ func validateHostUsers(spec *core.PodSpec, fldPath *field.Path) field.ErrorList
}
// validateContainers is called by pod spec and template validation to validate the list of regular containers.
func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], gracePeriod int64, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.Set[string], gracePeriod int64, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy, hostUsers bool) field.ErrorList {
allErrs := field.ErrorList{}
if len(containers) == 0 {
@ -3581,7 +3622,7 @@ func validateContainers(containers []core.Container, volumes map[string]core.Vol
path := fldPath.Index(i)
// Apply validation common to all containers
allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, path, opts, podRestartPolicy)...)
allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, path, opts, podRestartPolicy, hostUsers)...)
// Container names must be unique within the list of regular containers.
// Collisions with init or ephemeral container names will be detected by the init or ephemeral
@ -3718,9 +3759,7 @@ func validatePodDNSConfig(dnsConfig *core.PodDNSConfig, dnsPolicy *core.DNSPolic
allErrs = append(allErrs, field.Invalid(fldPath.Child("nameservers"), dnsConfig.Nameservers, fmt.Sprintf("must not have more than %v nameservers", MaxDNSNameservers)))
}
for i, ns := range dnsConfig.Nameservers {
if ip := netutils.ParseIPSloppy(ns); ip == nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("nameservers").Index(i), ns, "must be valid IP address"))
}
allErrs = append(allErrs, validation.IsValidIP(fldPath.Child("nameservers").Index(i), ns)...)
}
// Validate searches.
if len(dnsConfig.Searches) > MaxDNSSearchPaths {
@ -3887,12 +3926,10 @@ func validateOnlyDeletedSchedulingGates(newGates, oldGates []core.PodSchedulingG
func ValidateHostAliases(hostAliases []core.HostAlias, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for _, hostAlias := range hostAliases {
if ip := netutils.ParseIPSloppy(hostAlias.IP); ip == nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("ip"), hostAlias.IP, "must be valid IP address"))
}
for _, hostname := range hostAlias.Hostnames {
allErrs = append(allErrs, ValidateDNS1123Subdomain(hostname, fldPath.Child("hostnames"))...)
for i, hostAlias := range hostAliases {
allErrs = append(allErrs, validation.IsValidIP(fldPath.Index(i).Child("ip"), hostAlias.IP)...)
for j, hostname := range hostAlias.Hostnames {
allErrs = append(allErrs, ValidateDNS1123Subdomain(hostname, fldPath.Index(i).Child("hostnames").Index(j))...)
}
}
return allErrs
@ -3976,13 +4013,15 @@ type PodValidationOptions struct {
AllowHostIPsField bool
// Allow invalid topologySpreadConstraint labelSelector for backward compatibility
AllowInvalidTopologySpreadConstraintLabelSelector bool
// Allow node selector additions for gated pods.
AllowMutableNodeSelectorAndNodeAffinity bool
// Allow projected token volumes with non-local paths
AllowNonLocalProjectedTokenPath bool
// Allow namespaced sysctls in hostNet and hostIPC pods
AllowNamespacedSysctlsForHostNetAndHostIPC bool
// The top-level resource being validated is a Pod, not just a PodSpec
// embedded in some other resource.
ResourceIsPod bool
// Allow relaxed validation of environment variable names
AllowRelaxedEnvironmentVariableValidation bool
}
// validatePodMetadataAndSpec tests if required fields in the pod.metadata and pod.spec are set,
@ -4027,9 +4066,7 @@ func validatePodIPs(pod *core.Pod) field.ErrorList {
// all PodIPs must be valid IPs
for i, podIP := range pod.Status.PodIPs {
for _, msg := range validation.IsValidIP(podIP.IP) {
allErrs = append(allErrs, field.Invalid(podIPsField.Index(i), podIP.IP, msg))
}
allErrs = append(allErrs, validation.IsValidIP(podIPsField.Index(i), podIP.IP)...)
}
// if we have more than one Pod.PodIP then
@ -4081,9 +4118,7 @@ func validateHostIPs(pod *core.Pod) field.ErrorList {
// all HostPs must be valid IPs
for i, hostIP := range pod.Status.HostIPs {
for _, msg := range validation.IsValidIP(hostIP.IP) {
allErrs = append(allErrs, field.Invalid(hostIPsField.Index(i), hostIP.IP, msg))
}
allErrs = append(allErrs, validation.IsValidIP(hostIPsField.Index(i), hostIP.IP)...)
}
// if we have more than one Pod.HostIP then
@ -4131,13 +4166,17 @@ func ValidatePodSpec(spec *core.PodSpec, podMeta *metav1.ObjectMeta, fldPath *fi
gracePeriod = *spec.TerminationGracePeriodSeconds
}
// The default for hostUsers is true, so a spec with no SecurityContext or no HostUsers field will be true.
// If the default ever changes, this condition will need to be changed.
hostUsers := spec.SecurityContext == nil || spec.SecurityContext.HostUsers == nil || *spec.SecurityContext.HostUsers
vols, vErrs := ValidateVolumes(spec.Volumes, podMeta, fldPath.Child("volumes"), opts)
allErrs = append(allErrs, vErrs...)
podClaimNames := gatherPodResourceClaimNames(spec.ResourceClaims)
allErrs = append(allErrs, validatePodResourceClaims(podMeta, spec.ResourceClaims, fldPath.Child("resourceClaims"))...)
allErrs = append(allErrs, validateContainers(spec.Containers, vols, podClaimNames, gracePeriod, fldPath.Child("containers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, podClaimNames, gracePeriod, fldPath.Child("initContainers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateEphemeralContainers(spec.EphemeralContainers, spec.Containers, spec.InitContainers, vols, podClaimNames, fldPath.Child("ephemeralContainers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateContainers(spec.Containers, vols, podClaimNames, gracePeriod, fldPath.Child("containers"), opts, &spec.RestartPolicy, hostUsers)...)
allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, podClaimNames, gracePeriod, fldPath.Child("initContainers"), opts, &spec.RestartPolicy, hostUsers)...)
allErrs = append(allErrs, validateEphemeralContainers(spec.EphemeralContainers, spec.Containers, spec.InitContainers, vols, podClaimNames, fldPath.Child("ephemeralContainers"), opts, &spec.RestartPolicy, hostUsers)...)
allErrs = append(allErrs, validatePodHostNetworkDeps(spec, fldPath, opts)...)
allErrs = append(allErrs, validateRestartPolicy(&spec.RestartPolicy, fldPath.Child("restartPolicy"))...)
allErrs = append(allErrs, validateDNSPolicy(&spec.DNSPolicy, fldPath.Child("dnsPolicy"))...)
@ -4240,6 +4279,9 @@ func validateWindows(spec *core.PodSpec, fldPath *field.Path) field.ErrorList {
securityContext := spec.SecurityContext
// validate Pod SecurityContext
if securityContext != nil {
if securityContext.AppArmorProfile != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("securityContext").Child("appArmorProfile"), "cannot be set for a windows pod"))
}
if securityContext.SELinuxOptions != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("securityContext").Child("seLinuxOptions"), "cannot be set for a windows pod"))
}
@ -4286,6 +4328,9 @@ func validateWindows(spec *core.PodSpec, fldPath *field.Path) field.ErrorList {
// TODO: Think if we need to relax this restriction or some of the restrictions
if sc != nil {
fldPath := cFldPath.Child("securityContext")
if sc.AppArmorProfile != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("appArmorProfile"), "cannot be set for a windows pod"))
}
if sc.SELinuxOptions != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("seLinuxOptions"), "cannot be set for a windows pod"))
}
@ -4663,13 +4708,55 @@ func validateSeccompProfileType(fldPath *field.Path, seccompProfileType core.Sec
}
}
func ValidateAppArmorProfileField(profile *core.AppArmorProfile, fldPath *field.Path) field.ErrorList {
if profile == nil {
return nil
}
allErrs := field.ErrorList{}
switch profile.Type {
case core.AppArmorProfileTypeLocalhost:
if profile.LocalhostProfile == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("localhostProfile"), "must be set when AppArmor type is Localhost"))
} else {
localhostProfile := strings.TrimSpace(*profile.LocalhostProfile)
if localhostProfile != *profile.LocalhostProfile {
allErrs = append(allErrs, field.Invalid(fldPath.Child("localhostProfile"), *profile.LocalhostProfile, "must not be padded with whitespace"))
} else if localhostProfile == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("localhostProfile"), "must be set when AppArmor type is Localhost"))
}
const maxLocalhostProfileLength = 4095 // PATH_MAX - 1
if len(*profile.LocalhostProfile) > maxLocalhostProfileLength {
allErrs = append(allErrs, field.TooLongMaxLength(fldPath.Child("localhostProfile"), *profile.LocalhostProfile, maxLocalhostProfileLength))
}
}
case core.AppArmorProfileTypeRuntimeDefault, core.AppArmorProfileTypeUnconfined:
if profile.LocalhostProfile != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("localhostProfile"), profile.LocalhostProfile, "can only be set when AppArmor type is Localhost"))
}
case "":
allErrs = append(allErrs, field.Required(fldPath.Child("type"), "type is required when appArmorProfile is set"))
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), profile.Type,
[]core.AppArmorProfileType{core.AppArmorProfileTypeLocalhost, core.AppArmorProfileTypeRuntimeDefault, core.AppArmorProfileTypeUnconfined}))
}
return allErrs
}
func ValidateAppArmorPodAnnotations(annotations map[string]string, spec *core.PodSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for k, p := range annotations {
if !strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
if !strings.HasPrefix(k, v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix) {
continue
}
containerName := strings.TrimPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix)
containerName := strings.TrimPrefix(k, v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix)
if !podSpecHasContainer(spec, containerName) {
allErrs = append(allErrs, field.Invalid(fldPath.Key(k), containerName, "container not found"))
}
@ -4683,15 +4770,70 @@ func ValidateAppArmorPodAnnotations(annotations map[string]string, spec *core.Po
}
func ValidateAppArmorProfileFormat(profile string) error {
if profile == "" || profile == v1.AppArmorBetaProfileRuntimeDefault || profile == v1.AppArmorBetaProfileNameUnconfined {
if profile == "" || profile == v1.DeprecatedAppArmorBetaProfileRuntimeDefault || profile == v1.DeprecatedAppArmorBetaProfileNameUnconfined {
return nil
}
if !strings.HasPrefix(profile, v1.AppArmorBetaProfileNamePrefix) {
if !strings.HasPrefix(profile, v1.DeprecatedAppArmorBetaProfileNamePrefix) {
return fmt.Errorf("invalid AppArmor profile name: %q", profile)
}
return nil
}
// validateAppArmorAnnotationsAndFieldsMatchOnCreate validates that AppArmor fields and annotations are consistent.
func validateAppArmorAnnotationsAndFieldsMatchOnCreate(objectMeta metav1.ObjectMeta, podSpec *core.PodSpec, specPath *field.Path) field.ErrorList {
if !utilfeature.DefaultFeatureGate.Enabled(features.AppArmorFields) {
return nil
}
if podSpec.OS != nil && podSpec.OS.Name == core.Windows {
// Skip consistency check for windows pods.
return nil
}
allErrs := field.ErrorList{}
var podProfile *core.AppArmorProfile
if podSpec.SecurityContext != nil {
podProfile = podSpec.SecurityContext.AppArmorProfile
}
podshelper.VisitContainersWithPath(podSpec, specPath, func(c *core.Container, cFldPath *field.Path) bool {
containerProfile := podProfile
if c.SecurityContext != nil && c.SecurityContext.AppArmorProfile != nil {
containerProfile = c.SecurityContext.AppArmorProfile
}
if containerProfile == nil {
return true
}
key := core.DeprecatedAppArmorAnnotationKeyPrefix + c.Name
if annotation, found := objectMeta.Annotations[key]; found {
apparmorPath := cFldPath.Child("securityContext").Child("appArmorProfile")
switch containerProfile.Type {
case core.AppArmorProfileTypeUnconfined:
if annotation != core.DeprecatedAppArmorAnnotationValueUnconfined {
allErrs = append(allErrs, field.Forbidden(apparmorPath.Child("type"), "apparmor type in annotation and field must match"))
}
case core.AppArmorProfileTypeRuntimeDefault:
if annotation != core.DeprecatedAppArmorAnnotationValueRuntimeDefault {
allErrs = append(allErrs, field.Forbidden(apparmorPath.Child("type"), "apparmor type in annotation and field must match"))
}
case core.AppArmorProfileTypeLocalhost:
if !strings.HasPrefix(annotation, core.DeprecatedAppArmorAnnotationValueLocalhostPrefix) {
allErrs = append(allErrs, field.Forbidden(apparmorPath.Child("type"), "apparmor type in annotation and field must match"))
} else if containerProfile.LocalhostProfile == nil || strings.TrimPrefix(annotation, core.DeprecatedAppArmorAnnotationValueLocalhostPrefix) != *containerProfile.LocalhostProfile {
allErrs = append(allErrs, field.Forbidden(apparmorPath.Child("localhostProfile"), "apparmor profile in annotation and field must match"))
}
}
}
return true
})
return allErrs
}
func podSpecHasContainer(spec *core.PodSpec, containerName string) bool {
var hasContainer bool
podshelper.VisitContainersWithPath(spec, field.NewPath("spec"), func(c *core.Container, _ *field.Path) bool {
@ -4805,6 +4947,7 @@ func validatePodSpecSecurityContext(securityContext *core.PodSecurityContext, sp
allErrs = append(allErrs, validateSeccompProfileField(securityContext.SeccompProfile, fldPath.Child("seccompProfile"))...)
allErrs = append(allErrs, validateWindowsSecurityContextOptions(securityContext.WindowsOptions, fldPath.Child("windowsOptions"))...)
allErrs = append(allErrs, ValidateAppArmorProfileField(securityContext.AppArmorProfile, fldPath.Child("appArmorProfile"))...)
}
return allErrs
@ -4845,6 +4988,7 @@ func ValidatePodCreate(pod *core.Pod, opts PodValidationOptions) field.ErrorList
allErrs = append(allErrs, field.Forbidden(fldPath.Child("nodeName"), "cannot be set until all schedulingGates have been cleared"))
}
allErrs = append(allErrs, validateSeccompAnnotationsAndFields(pod.ObjectMeta, &pod.Spec, fldPath)...)
allErrs = append(allErrs, validateAppArmorAnnotationsAndFieldsMatchOnCreate(pod.ObjectMeta, &pod.Spec, fldPath)...)
return allErrs
}
@ -5060,7 +5204,7 @@ func ValidatePodUpdate(newPod, oldPod *core.Pod, opts PodValidationOptions) fiel
// Handle validations specific to gated pods.
podIsGated := len(oldPod.Spec.SchedulingGates) > 0
if opts.AllowMutableNodeSelectorAndNodeAffinity && podIsGated {
if podIsGated {
// Additions to spec.nodeSelector are allowed (no deletions or mutations) for gated pods.
if !apiequality.Semantic.DeepEqual(mungedPodSpec.NodeSelector, oldPod.Spec.NodeSelector) {
allErrs = append(allErrs, validateNodeSelectorMutation(specPath.Child("nodeSelector"), mungedPodSpec.NodeSelector, oldPod.Spec.NodeSelector)...)
@ -5439,10 +5583,8 @@ func ValidateService(service *core.Service) field.ErrorList {
ipPath := specPath.Child("externalIPs")
for i, ip := range service.Spec.ExternalIPs {
idxPath := ipPath.Index(i)
if msgs := validation.IsValidIP(ip); len(msgs) != 0 {
for i := range msgs {
allErrs = append(allErrs, field.Invalid(idxPath, ip, msgs[i]))
}
if errs := validation.IsValidIP(idxPath, ip); len(errs) != 0 {
allErrs = append(allErrs, errs...)
} else {
allErrs = append(allErrs, ValidateNonSpecialIP(ip, idxPath)...)
}
@ -5496,24 +5638,32 @@ func ValidateService(service *core.Service) field.ErrorList {
ports[key] = true
}
// Validate SourceRange field and annotation
_, ok := service.Annotations[core.AnnotationLoadBalancerSourceRangesKey]
if len(service.Spec.LoadBalancerSourceRanges) > 0 || ok {
var fieldPath *field.Path
var val string
if len(service.Spec.LoadBalancerSourceRanges) > 0 {
fieldPath = specPath.Child("LoadBalancerSourceRanges")
val = fmt.Sprintf("%v", service.Spec.LoadBalancerSourceRanges)
} else {
fieldPath = field.NewPath("metadata", "annotations").Key(core.AnnotationLoadBalancerSourceRangesKey)
val = service.Annotations[core.AnnotationLoadBalancerSourceRangesKey]
}
// Validate SourceRanges field or annotation.
if len(service.Spec.LoadBalancerSourceRanges) > 0 {
fieldPath := specPath.Child("LoadBalancerSourceRanges")
if service.Spec.Type != core.ServiceTypeLoadBalancer {
allErrs = append(allErrs, field.Forbidden(fieldPath, "may only be used when `type` is 'LoadBalancer'"))
}
_, err := apiservice.GetLoadBalancerSourceRanges(service)
if err != nil {
allErrs = append(allErrs, field.Invalid(fieldPath, val, "must be a list of IP ranges. For example, 10.240.0.0/24,10.250.0.0/24 "))
for idx, value := range service.Spec.LoadBalancerSourceRanges {
// Note: due to a historical accident around transition from the
// annotation value, these values are allowed to be space-padded.
value = strings.TrimSpace(value)
allErrs = append(allErrs, validation.IsValidCIDR(fieldPath.Index(idx), value)...)
}
} else if val, annotationSet := service.Annotations[core.AnnotationLoadBalancerSourceRangesKey]; annotationSet {
fieldPath := field.NewPath("metadata", "annotations").Key(core.AnnotationLoadBalancerSourceRangesKey)
if service.Spec.Type != core.ServiceTypeLoadBalancer {
allErrs = append(allErrs, field.Forbidden(fieldPath, "may only be used when `type` is 'LoadBalancer'"))
}
val = strings.TrimSpace(val)
if val != "" {
cidrs := strings.Split(val, ",")
for _, value := range cidrs {
value = strings.TrimSpace(value)
allErrs = append(allErrs, validation.IsValidCIDR(fieldPath, value)...)
}
}
}
@ -5534,6 +5684,9 @@ func ValidateService(service *core.Service) field.ErrorList {
// internal traffic policy field
allErrs = append(allErrs, validateServiceInternalTrafficFieldsValue(service)...)
// traffic distribution field
allErrs = append(allErrs, validateServiceTrafficDistribution(service)...)
return allErrs
}
@ -5651,6 +5804,22 @@ func validateServiceInternalTrafficFieldsValue(service *core.Service) field.Erro
return allErrs
}
// validateServiceTrafficDistribution validates the values for the
// trafficDistribution field.
func validateServiceTrafficDistribution(service *core.Service) field.ErrorList {
allErrs := field.ErrorList{}
if service.Spec.TrafficDistribution == nil {
return allErrs
}
if *service.Spec.TrafficDistribution != v1.ServiceTrafficDistributionPreferClose {
allErrs = append(allErrs, field.NotSupported(field.NewPath("spec").Child("trafficDistribution"), *service.Spec.TrafficDistribution, []string{v1.ServiceTrafficDistributionPreferClose}))
}
return allErrs
}
// ValidateServiceCreate validates Services as they are created.
func ValidateServiceCreate(service *core.Service) field.ErrorList {
return ValidateService(service)
@ -5797,6 +5966,7 @@ func ValidatePodTemplateSpec(spec *core.PodTemplateSpec, fldPath *field.Path, op
allErrs = append(allErrs, ValidatePodSpecificAnnotations(spec.Annotations, &spec.Spec, fldPath.Child("annotations"), opts)...)
allErrs = append(allErrs, ValidatePodSpec(&spec.Spec, nil, fldPath.Child("spec"), opts)...)
allErrs = append(allErrs, validateSeccompAnnotationsAndFields(spec.ObjectMeta, &spec.Spec, fldPath.Child("spec"))...)
allErrs = append(allErrs, validateAppArmorAnnotationsAndFieldsMatchOnCreate(spec.ObjectMeta, &spec.Spec, fldPath.Child("spec"))...)
if len(spec.Spec.EphemeralContainers) > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("spec", "ephemeralContainers"), "ephemeral containers not allowed in pod template"))
@ -5916,9 +6086,7 @@ func ValidateNode(node *core.Node) field.ErrorList {
// all PodCIDRs should be valid ones
for idx, value := range node.Spec.PodCIDRs {
if _, err := ValidateCIDR(value); err != nil {
allErrs = append(allErrs, field.Invalid(podCIDRsField.Index(idx), node.Spec.PodCIDRs, "must be valid CIDR"))
}
allErrs = append(allErrs, validation.IsValidCIDR(podCIDRsField.Index(idx), value)...)
}
// if more than PodCIDR then
@ -6954,9 +7122,7 @@ func validateEndpointSubsets(subsets []core.EndpointSubset, fldPath *field.Path)
func validateEndpointAddress(address *core.EndpointAddress, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for _, msg := range validation.IsValidIP(address.IP) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("ip"), address.IP, msg))
}
allErrs = append(allErrs, validation.IsValidIP(fldPath.Child("ip"), address.IP)...)
if len(address.Hostname) > 0 {
allErrs = append(allErrs, ValidateDNS1123Label(address.Hostname, fldPath.Child("hostname"))...)
}
@ -7022,7 +7188,7 @@ func validateEndpointPort(port *core.EndpointPort, requireName bool, fldPath *fi
}
// ValidateSecurityContext ensures the security context contains valid settings
func ValidateSecurityContext(sc *core.SecurityContext, fldPath *field.Path) field.ErrorList {
func ValidateSecurityContext(sc *core.SecurityContext, fldPath *field.Path, hostUsers bool) field.ErrorList {
allErrs := field.ErrorList{}
// this should only be true for testing since SecurityContext is defaulted by the core
if sc == nil {
@ -7051,6 +7217,9 @@ func ValidateSecurityContext(sc *core.SecurityContext, fldPath *field.Path) fiel
if err := ValidateProcMountType(fldPath.Child("procMount"), *sc.ProcMount); err != nil {
allErrs = append(allErrs, err)
}
if hostUsers && *sc.ProcMount == core.UnmaskedProcMount {
allErrs = append(allErrs, field.Invalid(fldPath.Child("procMount"), sc.ProcMount, "`hostUsers` must be false to use `Unmasked`"))
}
}
allErrs = append(allErrs, validateSeccompProfileField(sc.SeccompProfile, fldPath.Child("seccompProfile"))...)
@ -7069,6 +7238,7 @@ func ValidateSecurityContext(sc *core.SecurityContext, fldPath *field.Path) fiel
}
allErrs = append(allErrs, validateWindowsSecurityContextOptions(sc.WindowsOptions, fldPath.Child("windowsOptions"))...)
allErrs = append(allErrs, ValidateAppArmorProfileField(sc.AppArmorProfile, fldPath.Child("appArmorProfile"))...)
return allErrs
}
@ -7302,9 +7472,7 @@ func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field.
for i, ingress := range status.Ingress {
idxPath := ingrPath.Index(i)
if len(ingress.IP) > 0 {
if isIP := (netutils.ParseIPSloppy(ingress.IP) != nil); !isIP {
allErrs = append(allErrs, field.Invalid(idxPath.Child("ip"), ingress.IP, "must be a valid IP address"))
}
allErrs = append(allErrs, validation.IsValidIP(idxPath.Child("ip"), ingress.IP)...)
}
if utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) && ingress.IPMode == nil {
@ -7350,15 +7518,6 @@ func validateVolumeNodeAffinity(nodeAffinity *core.VolumeNodeAffinity, fldPath *
return true, allErrs
}
// ValidateCIDR validates whether a CIDR matches the conventions expected by net.ParseCIDR
func ValidateCIDR(cidr string) (*net.IPNet, error) {
_, net, err := netutils.ParseCIDRSloppy(cidr)
if err != nil {
return nil, err
}
return net, nil
}
func IsDecremented(update, old *int32) bool {
if update == nil && old != nil {
return true
@ -7658,11 +7817,9 @@ func ValidateServiceClusterIPsRelatedFields(service *core.Service) field.ErrorLi
}
// is it valid ip?
errorMessages := validation.IsValidIP(clusterIP)
errorMessages := validation.IsValidIP(clusterIPsField.Index(i), clusterIP)
hasInvalidIPs = (len(errorMessages) != 0) || hasInvalidIPs
for _, msg := range errorMessages {
allErrs = append(allErrs, field.Invalid(clusterIPsField.Index(i), clusterIP, msg))
}
allErrs = append(allErrs, errorMessages...)
}
// max two

View File

@ -74,6 +74,27 @@ func (in *Affinity) DeepCopy() *Affinity {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppArmorProfile) DeepCopyInto(out *AppArmorProfile) {
*out = *in
if in.LocalhostProfile != nil {
in, out := &in.LocalhostProfile, &out.LocalhostProfile
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppArmorProfile.
func (in *AppArmorProfile) DeepCopy() *AppArmorProfile {
if in == nil {
return nil
}
out := new(AppArmorProfile)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AttachedVolume) DeepCopyInto(out *AttachedVolume) {
*out = *in
@ -1041,6 +1062,13 @@ func (in *ContainerStatus) DeepCopyInto(out *ContainerStatus) {
*out = new(ResourceRequirements)
(*in).DeepCopyInto(*out)
}
if in.VolumeMounts != nil {
in, out := &in.VolumeMounts, &out.VolumeMounts
*out = make([]VolumeMountStatus, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
@ -2728,24 +2756,43 @@ func (in *NodeProxyOptions) DeepCopyObject() runtime.Object {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeResources) DeepCopyInto(out *NodeResources) {
func (in *NodeRuntimeHandler) DeepCopyInto(out *NodeRuntimeHandler) {
*out = *in
if in.Capacity != nil {
in, out := &in.Capacity, &out.Capacity
*out = make(ResourceList, len(*in))
for key, val := range *in {
(*out)[key] = val.DeepCopy()
}
if in.Features != nil {
in, out := &in.Features, &out.Features
*out = new(NodeRuntimeHandlerFeatures)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResources.
func (in *NodeResources) DeepCopy() *NodeResources {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRuntimeHandler.
func (in *NodeRuntimeHandler) DeepCopy() *NodeRuntimeHandler {
if in == nil {
return nil
}
out := new(NodeResources)
out := new(NodeRuntimeHandler)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeRuntimeHandlerFeatures) DeepCopyInto(out *NodeRuntimeHandlerFeatures) {
*out = *in
if in.RecursiveReadOnlyMounts != nil {
in, out := &in.RecursiveReadOnlyMounts, &out.RecursiveReadOnlyMounts
*out = new(bool)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRuntimeHandlerFeatures.
func (in *NodeRuntimeHandlerFeatures) DeepCopy() *NodeRuntimeHandlerFeatures {
if in == nil {
return nil
}
out := new(NodeRuntimeHandlerFeatures)
in.DeepCopyInto(out)
return out
}
@ -2910,6 +2957,13 @@ func (in *NodeStatus) DeepCopyInto(out *NodeStatus) {
*out = new(NodeConfigStatus)
(*in).DeepCopyInto(*out)
}
if in.RuntimeHandlers != nil {
in, out := &in.RuntimeHandlers, &out.RuntimeHandlers
*out = make([]NodeRuntimeHandler, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
@ -4033,6 +4087,11 @@ func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) {
*out = new(SeccompProfile)
(*in).DeepCopyInto(*out)
}
if in.AppArmorProfile != nil {
in, out := &in.AppArmorProfile, &out.AppArmorProfile
*out = new(AppArmorProfile)
(*in).DeepCopyInto(*out)
}
return
}
@ -5401,6 +5460,11 @@ func (in *SecurityContext) DeepCopyInto(out *SecurityContext) {
*out = new(SeccompProfile)
(*in).DeepCopyInto(*out)
}
if in.AppArmorProfile != nil {
in, out := &in.AppArmorProfile, &out.AppArmorProfile
*out = new(AppArmorProfile)
(*in).DeepCopyInto(*out)
}
return
}
@ -5700,6 +5764,11 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) {
*out = new(ServiceInternalTrafficPolicy)
**out = **in
}
if in.TrafficDistribution != nil {
in, out := &in.TrafficDistribution, &out.TrafficDistribution
*out = new(string)
**out = **in
}
return
}
@ -6058,6 +6127,11 @@ func (in *VolumeDevice) DeepCopy() *VolumeDevice {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeMount) DeepCopyInto(out *VolumeMount) {
*out = *in
if in.RecursiveReadOnly != nil {
in, out := &in.RecursiveReadOnly, &out.RecursiveReadOnly
*out = new(RecursiveReadOnlyMode)
**out = **in
}
if in.MountPropagation != nil {
in, out := &in.MountPropagation, &out.MountPropagation
*out = new(MountPropagationMode)
@ -6076,6 +6150,27 @@ func (in *VolumeMount) DeepCopy() *VolumeMount {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeMountStatus) DeepCopyInto(out *VolumeMountStatus) {
*out = *in
if in.RecursiveReadOnly != nil {
in, out := &in.RecursiveReadOnly, &out.RecursiveReadOnly
*out = new(RecursiveReadOnlyMode)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeMountStatus.
func (in *VolumeMountStatus) DeepCopy() *VolumeMountStatus {
if in == nil {
return nil
}
out := new(VolumeMountStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeNodeAffinity) DeepCopyInto(out *VolumeNodeAffinity) {
*out = *in