k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/apis/core/v1/defaults.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1
    18  
    19  import (
    20  	"time"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/runtime"
    24  	"k8s.io/apimachinery/pkg/util/intstr"
    25  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    26  	"k8s.io/kubernetes/pkg/api/v1/service"
    27  	"k8s.io/kubernetes/pkg/features"
    28  	"k8s.io/kubernetes/pkg/util/parsers"
    29  	"k8s.io/utils/pointer"
    30  )
    31  
    32  func addDefaultingFuncs(scheme *runtime.Scheme) error {
    33  	return RegisterDefaults(scheme)
    34  }
    35  
    36  func SetDefaults_ResourceList(obj *v1.ResourceList) {
    37  	for key, val := range *obj {
    38  		// TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
    39  		// In the future, we should instead reject values that need rounding.
    40  		const milliScale = -3
    41  		val.RoundUp(milliScale)
    42  
    43  		(*obj)[v1.ResourceName(key)] = val
    44  	}
    45  }
    46  
    47  func SetDefaults_ReplicationController(obj *v1.ReplicationController) {
    48  	var labels map[string]string
    49  	if obj.Spec.Template != nil {
    50  		labels = obj.Spec.Template.Labels
    51  	}
    52  	// TODO: support templates defined elsewhere when we support them in the API
    53  	if labels != nil {
    54  		if len(obj.Spec.Selector) == 0 {
    55  			obj.Spec.Selector = labels
    56  		}
    57  		if len(obj.Labels) == 0 {
    58  			obj.Labels = labels
    59  		}
    60  	}
    61  	if obj.Spec.Replicas == nil {
    62  		obj.Spec.Replicas = new(int32)
    63  		*obj.Spec.Replicas = 1
    64  	}
    65  }
    66  func SetDefaults_Volume(obj *v1.Volume) {
    67  	if pointer.AllPtrFieldsNil(&obj.VolumeSource) {
    68  		obj.VolumeSource = v1.VolumeSource{
    69  			EmptyDir: &v1.EmptyDirVolumeSource{},
    70  		}
    71  	}
    72  }
    73  func SetDefaults_Container(obj *v1.Container) {
    74  	if obj.ImagePullPolicy == "" {
    75  		// Ignore error and assume it has been validated elsewhere
    76  		_, tag, _, _ := parsers.ParseImageName(obj.Image)
    77  
    78  		// Check image tag
    79  		if tag == "latest" {
    80  			obj.ImagePullPolicy = v1.PullAlways
    81  		} else {
    82  			obj.ImagePullPolicy = v1.PullIfNotPresent
    83  		}
    84  	}
    85  	if obj.TerminationMessagePath == "" {
    86  		obj.TerminationMessagePath = v1.TerminationMessagePathDefault
    87  	}
    88  	if obj.TerminationMessagePolicy == "" {
    89  		obj.TerminationMessagePolicy = v1.TerminationMessageReadFile
    90  	}
    91  }
    92  
    93  func SetDefaults_EphemeralContainer(obj *v1.EphemeralContainer) {
    94  	SetDefaults_Container((*v1.Container)(&obj.EphemeralContainerCommon))
    95  }
    96  
    97  func SetDefaults_Service(obj *v1.Service) {
    98  	if obj.Spec.SessionAffinity == "" {
    99  		obj.Spec.SessionAffinity = v1.ServiceAffinityNone
   100  	}
   101  	if obj.Spec.SessionAffinity == v1.ServiceAffinityNone {
   102  		obj.Spec.SessionAffinityConfig = nil
   103  	}
   104  	if obj.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
   105  		if obj.Spec.SessionAffinityConfig == nil || obj.Spec.SessionAffinityConfig.ClientIP == nil || obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil {
   106  			timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
   107  			obj.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
   108  				ClientIP: &v1.ClientIPConfig{
   109  					TimeoutSeconds: &timeoutSeconds,
   110  				},
   111  			}
   112  		}
   113  	}
   114  	if obj.Spec.Type == "" {
   115  		obj.Spec.Type = v1.ServiceTypeClusterIP
   116  	}
   117  	for i := range obj.Spec.Ports {
   118  		sp := &obj.Spec.Ports[i]
   119  		if sp.Protocol == "" {
   120  			sp.Protocol = v1.ProtocolTCP
   121  		}
   122  		if sp.TargetPort == intstr.FromInt32(0) || sp.TargetPort == intstr.FromString("") {
   123  			sp.TargetPort = intstr.FromInt32(sp.Port)
   124  		}
   125  	}
   126  	// Defaults ExternalTrafficPolicy field for externally-accessible service
   127  	// to Global for consistency.
   128  	if service.ExternallyAccessible(obj) && obj.Spec.ExternalTrafficPolicy == "" {
   129  		obj.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyCluster
   130  	}
   131  
   132  	if obj.Spec.InternalTrafficPolicy == nil {
   133  		if obj.Spec.Type == v1.ServiceTypeNodePort || obj.Spec.Type == v1.ServiceTypeLoadBalancer || obj.Spec.Type == v1.ServiceTypeClusterIP {
   134  			serviceInternalTrafficPolicyCluster := v1.ServiceInternalTrafficPolicyCluster
   135  			obj.Spec.InternalTrafficPolicy = &serviceInternalTrafficPolicyCluster
   136  		}
   137  	}
   138  
   139  	if obj.Spec.Type == v1.ServiceTypeLoadBalancer {
   140  		if obj.Spec.AllocateLoadBalancerNodePorts == nil {
   141  			obj.Spec.AllocateLoadBalancerNodePorts = pointer.Bool(true)
   142  		}
   143  	}
   144  
   145  	if obj.Spec.Type == v1.ServiceTypeLoadBalancer {
   146  		if utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) {
   147  			ipMode := v1.LoadBalancerIPModeVIP
   148  
   149  			for i, ing := range obj.Status.LoadBalancer.Ingress {
   150  				if ing.IP != "" && ing.IPMode == nil {
   151  					obj.Status.LoadBalancer.Ingress[i].IPMode = &ipMode
   152  				}
   153  			}
   154  		}
   155  	}
   156  
   157  }
   158  func SetDefaults_Pod(obj *v1.Pod) {
   159  	// If limits are specified, but requests are not, default requests to limits
   160  	// This is done here rather than a more specific defaulting pass on v1.ResourceRequirements
   161  	// because we only want this defaulting semantic to take place on a v1.Pod and not a v1.PodTemplate
   162  	for i := range obj.Spec.Containers {
   163  		// set requests to limits if requests are not specified, but limits are
   164  		if obj.Spec.Containers[i].Resources.Limits != nil {
   165  			if obj.Spec.Containers[i].Resources.Requests == nil {
   166  				obj.Spec.Containers[i].Resources.Requests = make(v1.ResourceList)
   167  			}
   168  			for key, value := range obj.Spec.Containers[i].Resources.Limits {
   169  				if _, exists := obj.Spec.Containers[i].Resources.Requests[key]; !exists {
   170  					obj.Spec.Containers[i].Resources.Requests[key] = value.DeepCopy()
   171  				}
   172  			}
   173  		}
   174  		if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) &&
   175  			obj.Spec.Containers[i].Resources.Requests != nil {
   176  			// For normal containers, set resize restart policy to default value (NotRequired), if not specified.
   177  			resizePolicySpecified := make(map[v1.ResourceName]bool)
   178  			for _, p := range obj.Spec.Containers[i].ResizePolicy {
   179  				resizePolicySpecified[p.ResourceName] = true
   180  			}
   181  			setDefaultResizePolicy := func(resourceName v1.ResourceName) {
   182  				if _, found := resizePolicySpecified[resourceName]; !found {
   183  					obj.Spec.Containers[i].ResizePolicy = append(obj.Spec.Containers[i].ResizePolicy,
   184  						v1.ContainerResizePolicy{
   185  							ResourceName:  resourceName,
   186  							RestartPolicy: v1.NotRequired,
   187  						})
   188  				}
   189  			}
   190  			if _, exists := obj.Spec.Containers[i].Resources.Requests[v1.ResourceCPU]; exists {
   191  				setDefaultResizePolicy(v1.ResourceCPU)
   192  			}
   193  			if _, exists := obj.Spec.Containers[i].Resources.Requests[v1.ResourceMemory]; exists {
   194  				setDefaultResizePolicy(v1.ResourceMemory)
   195  			}
   196  		}
   197  	}
   198  	for i := range obj.Spec.InitContainers {
   199  		if obj.Spec.InitContainers[i].Resources.Limits != nil {
   200  			if obj.Spec.InitContainers[i].Resources.Requests == nil {
   201  				obj.Spec.InitContainers[i].Resources.Requests = make(v1.ResourceList)
   202  			}
   203  			for key, value := range obj.Spec.InitContainers[i].Resources.Limits {
   204  				if _, exists := obj.Spec.InitContainers[i].Resources.Requests[key]; !exists {
   205  					obj.Spec.InitContainers[i].Resources.Requests[key] = value.DeepCopy()
   206  				}
   207  			}
   208  		}
   209  	}
   210  	if obj.Spec.EnableServiceLinks == nil {
   211  		enableServiceLinks := v1.DefaultEnableServiceLinks
   212  		obj.Spec.EnableServiceLinks = &enableServiceLinks
   213  	}
   214  
   215  	if obj.Spec.HostNetwork {
   216  		defaultHostNetworkPorts(&obj.Spec.Containers)
   217  		defaultHostNetworkPorts(&obj.Spec.InitContainers)
   218  	}
   219  }
   220  func SetDefaults_PodSpec(obj *v1.PodSpec) {
   221  	// New fields added here will break upgrade tests:
   222  	// https://github.com/kubernetes/kubernetes/issues/69445
   223  	// In most cases the new defaulted field can added to SetDefaults_Pod instead of here, so
   224  	// that it only materializes in the Pod object and not all objects with a PodSpec field.
   225  	if obj.DNSPolicy == "" {
   226  		obj.DNSPolicy = v1.DNSClusterFirst
   227  	}
   228  	if obj.RestartPolicy == "" {
   229  		obj.RestartPolicy = v1.RestartPolicyAlways
   230  	}
   231  	if obj.SecurityContext == nil {
   232  		obj.SecurityContext = &v1.PodSecurityContext{}
   233  	}
   234  	if obj.TerminationGracePeriodSeconds == nil {
   235  		period := int64(v1.DefaultTerminationGracePeriodSeconds)
   236  		obj.TerminationGracePeriodSeconds = &period
   237  	}
   238  	if obj.SchedulerName == "" {
   239  		obj.SchedulerName = v1.DefaultSchedulerName
   240  	}
   241  }
   242  func SetDefaults_Probe(obj *v1.Probe) {
   243  	if obj.TimeoutSeconds == 0 {
   244  		obj.TimeoutSeconds = 1
   245  	}
   246  	if obj.PeriodSeconds == 0 {
   247  		obj.PeriodSeconds = 10
   248  	}
   249  	if obj.SuccessThreshold == 0 {
   250  		obj.SuccessThreshold = 1
   251  	}
   252  	if obj.FailureThreshold == 0 {
   253  		obj.FailureThreshold = 3
   254  	}
   255  }
   256  func SetDefaults_SecretVolumeSource(obj *v1.SecretVolumeSource) {
   257  	if obj.DefaultMode == nil {
   258  		perm := int32(v1.SecretVolumeSourceDefaultMode)
   259  		obj.DefaultMode = &perm
   260  	}
   261  }
   262  func SetDefaults_ConfigMapVolumeSource(obj *v1.ConfigMapVolumeSource) {
   263  	if obj.DefaultMode == nil {
   264  		perm := int32(v1.ConfigMapVolumeSourceDefaultMode)
   265  		obj.DefaultMode = &perm
   266  	}
   267  }
   268  func SetDefaults_DownwardAPIVolumeSource(obj *v1.DownwardAPIVolumeSource) {
   269  	if obj.DefaultMode == nil {
   270  		perm := int32(v1.DownwardAPIVolumeSourceDefaultMode)
   271  		obj.DefaultMode = &perm
   272  	}
   273  }
   274  func SetDefaults_Secret(obj *v1.Secret) {
   275  	if obj.Type == "" {
   276  		obj.Type = v1.SecretTypeOpaque
   277  	}
   278  }
   279  func SetDefaults_ProjectedVolumeSource(obj *v1.ProjectedVolumeSource) {
   280  	if obj.DefaultMode == nil {
   281  		perm := int32(v1.ProjectedVolumeSourceDefaultMode)
   282  		obj.DefaultMode = &perm
   283  	}
   284  }
   285  func SetDefaults_ServiceAccountTokenProjection(obj *v1.ServiceAccountTokenProjection) {
   286  	hour := int64(time.Hour.Seconds())
   287  	if obj.ExpirationSeconds == nil {
   288  		obj.ExpirationSeconds = &hour
   289  	}
   290  }
   291  func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) {
   292  	if obj.Status.Phase == "" {
   293  		obj.Status.Phase = v1.VolumePending
   294  	}
   295  	if obj.Spec.PersistentVolumeReclaimPolicy == "" {
   296  		obj.Spec.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimRetain
   297  	}
   298  	if obj.Spec.VolumeMode == nil {
   299  		obj.Spec.VolumeMode = new(v1.PersistentVolumeMode)
   300  		*obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem
   301  	}
   302  }
   303  func SetDefaults_PersistentVolumeClaim(obj *v1.PersistentVolumeClaim) {
   304  	if obj.Status.Phase == "" {
   305  		obj.Status.Phase = v1.ClaimPending
   306  	}
   307  }
   308  func SetDefaults_PersistentVolumeClaimSpec(obj *v1.PersistentVolumeClaimSpec) {
   309  	if obj.VolumeMode == nil {
   310  		obj.VolumeMode = new(v1.PersistentVolumeMode)
   311  		*obj.VolumeMode = v1.PersistentVolumeFilesystem
   312  	}
   313  }
   314  func SetDefaults_ISCSIVolumeSource(obj *v1.ISCSIVolumeSource) {
   315  	if obj.ISCSIInterface == "" {
   316  		obj.ISCSIInterface = "default"
   317  	}
   318  }
   319  func SetDefaults_ISCSIPersistentVolumeSource(obj *v1.ISCSIPersistentVolumeSource) {
   320  	if obj.ISCSIInterface == "" {
   321  		obj.ISCSIInterface = "default"
   322  	}
   323  }
   324  func SetDefaults_AzureDiskVolumeSource(obj *v1.AzureDiskVolumeSource) {
   325  	if obj.CachingMode == nil {
   326  		obj.CachingMode = new(v1.AzureDataDiskCachingMode)
   327  		*obj.CachingMode = v1.AzureDataDiskCachingReadWrite
   328  	}
   329  	if obj.Kind == nil {
   330  		obj.Kind = new(v1.AzureDataDiskKind)
   331  		*obj.Kind = v1.AzureSharedBlobDisk
   332  	}
   333  	if obj.FSType == nil {
   334  		obj.FSType = new(string)
   335  		*obj.FSType = "ext4"
   336  	}
   337  	if obj.ReadOnly == nil {
   338  		obj.ReadOnly = new(bool)
   339  		*obj.ReadOnly = false
   340  	}
   341  }
   342  func SetDefaults_Endpoints(obj *v1.Endpoints) {
   343  	for i := range obj.Subsets {
   344  		ss := &obj.Subsets[i]
   345  		for i := range ss.Ports {
   346  			ep := &ss.Ports[i]
   347  			if ep.Protocol == "" {
   348  				ep.Protocol = v1.ProtocolTCP
   349  			}
   350  		}
   351  	}
   352  }
   353  func SetDefaults_HTTPGetAction(obj *v1.HTTPGetAction) {
   354  	if obj.Path == "" {
   355  		obj.Path = "/"
   356  	}
   357  	if obj.Scheme == "" {
   358  		obj.Scheme = v1.URISchemeHTTP
   359  	}
   360  }
   361  
   362  // SetDefaults_Namespace adds a default label for all namespaces
   363  func SetDefaults_Namespace(obj *v1.Namespace) {
   364  	// we can't SetDefaults for nameless namespaces (generateName).
   365  	// This code needs to be kept in sync with the implementation that exists
   366  	// in Namespace Canonicalize strategy (pkg/registry/core/namespace)
   367  
   368  	// note that this can result in many calls to feature enablement in some cases, but
   369  	// we assume that there's no real cost there.
   370  	if len(obj.Name) > 0 {
   371  		if obj.Labels == nil {
   372  			obj.Labels = map[string]string{}
   373  		}
   374  		obj.Labels[v1.LabelMetadataName] = obj.Name
   375  	}
   376  }
   377  
   378  func SetDefaults_NamespaceStatus(obj *v1.NamespaceStatus) {
   379  	if obj.Phase == "" {
   380  		obj.Phase = v1.NamespaceActive
   381  	}
   382  }
   383  func SetDefaults_NodeStatus(obj *v1.NodeStatus) {
   384  	if obj.Allocatable == nil && obj.Capacity != nil {
   385  		obj.Allocatable = make(v1.ResourceList, len(obj.Capacity))
   386  		for key, value := range obj.Capacity {
   387  			obj.Allocatable[key] = value.DeepCopy()
   388  		}
   389  		obj.Allocatable = obj.Capacity
   390  	}
   391  }
   392  func SetDefaults_ObjectFieldSelector(obj *v1.ObjectFieldSelector) {
   393  	if obj.APIVersion == "" {
   394  		obj.APIVersion = "v1"
   395  	}
   396  }
   397  func SetDefaults_LimitRangeItem(obj *v1.LimitRangeItem) {
   398  	// for container limits, we apply default values
   399  	if obj.Type == v1.LimitTypeContainer {
   400  
   401  		if obj.Default == nil {
   402  			obj.Default = make(v1.ResourceList)
   403  		}
   404  		if obj.DefaultRequest == nil {
   405  			obj.DefaultRequest = make(v1.ResourceList)
   406  		}
   407  
   408  		// If a default limit is unspecified, but the max is specified, default the limit to the max
   409  		for key, value := range obj.Max {
   410  			if _, exists := obj.Default[key]; !exists {
   411  				obj.Default[key] = value.DeepCopy()
   412  			}
   413  		}
   414  		// If a default limit is specified, but the default request is not, default request to limit
   415  		for key, value := range obj.Default {
   416  			if _, exists := obj.DefaultRequest[key]; !exists {
   417  				obj.DefaultRequest[key] = value.DeepCopy()
   418  			}
   419  		}
   420  		// If a default request is not specified, but the min is provided, default request to the min
   421  		for key, value := range obj.Min {
   422  			if _, exists := obj.DefaultRequest[key]; !exists {
   423  				obj.DefaultRequest[key] = value.DeepCopy()
   424  			}
   425  		}
   426  	}
   427  }
   428  func SetDefaults_ConfigMap(obj *v1.ConfigMap) {
   429  	if obj.Data == nil {
   430  		obj.Data = make(map[string]string)
   431  	}
   432  }
   433  
   434  // With host networking default all container ports to host ports.
   435  func defaultHostNetworkPorts(containers *[]v1.Container) {
   436  	for i := range *containers {
   437  		for j := range (*containers)[i].Ports {
   438  			if (*containers)[i].Ports[j].HostPort == 0 {
   439  				(*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
   440  			}
   441  		}
   442  	}
   443  }
   444  
   445  func SetDefaults_RBDVolumeSource(obj *v1.RBDVolumeSource) {
   446  	if obj.RBDPool == "" {
   447  		obj.RBDPool = "rbd"
   448  	}
   449  	if obj.RadosUser == "" {
   450  		obj.RadosUser = "admin"
   451  	}
   452  	if obj.Keyring == "" {
   453  		obj.Keyring = "/etc/ceph/keyring"
   454  	}
   455  }
   456  
   457  func SetDefaults_RBDPersistentVolumeSource(obj *v1.RBDPersistentVolumeSource) {
   458  	if obj.RBDPool == "" {
   459  		obj.RBDPool = "rbd"
   460  	}
   461  	if obj.RadosUser == "" {
   462  		obj.RadosUser = "admin"
   463  	}
   464  	if obj.Keyring == "" {
   465  		obj.Keyring = "/etc/ceph/keyring"
   466  	}
   467  }
   468  
   469  func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
   470  	if obj.StorageMode == "" {
   471  		obj.StorageMode = "ThinProvisioned"
   472  	}
   473  	if obj.FSType == "" {
   474  		obj.FSType = "xfs"
   475  	}
   476  }
   477  
   478  func SetDefaults_ScaleIOPersistentVolumeSource(obj *v1.ScaleIOPersistentVolumeSource) {
   479  	if obj.StorageMode == "" {
   480  		obj.StorageMode = "ThinProvisioned"
   481  	}
   482  	if obj.FSType == "" {
   483  		obj.FSType = "xfs"
   484  	}
   485  }
   486  
   487  func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) {
   488  	typeVol := v1.HostPathUnset
   489  	if obj.Type == nil {
   490  		obj.Type = &typeVol
   491  	}
   492  }