...

Source file src/k8s.io/kubernetes/pkg/apis/core/v1/defaults.go

Documentation: k8s.io/kubernetes/pkg/apis/core/v1

     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 utilfeature.DefaultFeatureGate.Enabled(features.DefaultHostNetworkHostPortsInPodTemplates) {
   232  		if obj.HostNetwork {
   233  			defaultHostNetworkPorts(&obj.Containers)
   234  			defaultHostNetworkPorts(&obj.InitContainers)
   235  		}
   236  	}
   237  	if obj.SecurityContext == nil {
   238  		obj.SecurityContext = &v1.PodSecurityContext{}
   239  	}
   240  	if obj.TerminationGracePeriodSeconds == nil {
   241  		period := int64(v1.DefaultTerminationGracePeriodSeconds)
   242  		obj.TerminationGracePeriodSeconds = &period
   243  	}
   244  	if obj.SchedulerName == "" {
   245  		obj.SchedulerName = v1.DefaultSchedulerName
   246  	}
   247  }
   248  func SetDefaults_Probe(obj *v1.Probe) {
   249  	if obj.TimeoutSeconds == 0 {
   250  		obj.TimeoutSeconds = 1
   251  	}
   252  	if obj.PeriodSeconds == 0 {
   253  		obj.PeriodSeconds = 10
   254  	}
   255  	if obj.SuccessThreshold == 0 {
   256  		obj.SuccessThreshold = 1
   257  	}
   258  	if obj.FailureThreshold == 0 {
   259  		obj.FailureThreshold = 3
   260  	}
   261  }
   262  func SetDefaults_SecretVolumeSource(obj *v1.SecretVolumeSource) {
   263  	if obj.DefaultMode == nil {
   264  		perm := int32(v1.SecretVolumeSourceDefaultMode)
   265  		obj.DefaultMode = &perm
   266  	}
   267  }
   268  func SetDefaults_ConfigMapVolumeSource(obj *v1.ConfigMapVolumeSource) {
   269  	if obj.DefaultMode == nil {
   270  		perm := int32(v1.ConfigMapVolumeSourceDefaultMode)
   271  		obj.DefaultMode = &perm
   272  	}
   273  }
   274  func SetDefaults_DownwardAPIVolumeSource(obj *v1.DownwardAPIVolumeSource) {
   275  	if obj.DefaultMode == nil {
   276  		perm := int32(v1.DownwardAPIVolumeSourceDefaultMode)
   277  		obj.DefaultMode = &perm
   278  	}
   279  }
   280  func SetDefaults_Secret(obj *v1.Secret) {
   281  	if obj.Type == "" {
   282  		obj.Type = v1.SecretTypeOpaque
   283  	}
   284  }
   285  func SetDefaults_ProjectedVolumeSource(obj *v1.ProjectedVolumeSource) {
   286  	if obj.DefaultMode == nil {
   287  		perm := int32(v1.ProjectedVolumeSourceDefaultMode)
   288  		obj.DefaultMode = &perm
   289  	}
   290  }
   291  func SetDefaults_ServiceAccountTokenProjection(obj *v1.ServiceAccountTokenProjection) {
   292  	hour := int64(time.Hour.Seconds())
   293  	if obj.ExpirationSeconds == nil {
   294  		obj.ExpirationSeconds = &hour
   295  	}
   296  }
   297  func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) {
   298  	if obj.Status.Phase == "" {
   299  		obj.Status.Phase = v1.VolumePending
   300  	}
   301  	if obj.Spec.PersistentVolumeReclaimPolicy == "" {
   302  		obj.Spec.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimRetain
   303  	}
   304  	if obj.Spec.VolumeMode == nil {
   305  		obj.Spec.VolumeMode = new(v1.PersistentVolumeMode)
   306  		*obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem
   307  	}
   308  }
   309  func SetDefaults_PersistentVolumeClaim(obj *v1.PersistentVolumeClaim) {
   310  	if obj.Status.Phase == "" {
   311  		obj.Status.Phase = v1.ClaimPending
   312  	}
   313  }
   314  func SetDefaults_PersistentVolumeClaimSpec(obj *v1.PersistentVolumeClaimSpec) {
   315  	if obj.VolumeMode == nil {
   316  		obj.VolumeMode = new(v1.PersistentVolumeMode)
   317  		*obj.VolumeMode = v1.PersistentVolumeFilesystem
   318  	}
   319  }
   320  func SetDefaults_ISCSIVolumeSource(obj *v1.ISCSIVolumeSource) {
   321  	if obj.ISCSIInterface == "" {
   322  		obj.ISCSIInterface = "default"
   323  	}
   324  }
   325  func SetDefaults_ISCSIPersistentVolumeSource(obj *v1.ISCSIPersistentVolumeSource) {
   326  	if obj.ISCSIInterface == "" {
   327  		obj.ISCSIInterface = "default"
   328  	}
   329  }
   330  func SetDefaults_AzureDiskVolumeSource(obj *v1.AzureDiskVolumeSource) {
   331  	if obj.CachingMode == nil {
   332  		obj.CachingMode = new(v1.AzureDataDiskCachingMode)
   333  		*obj.CachingMode = v1.AzureDataDiskCachingReadWrite
   334  	}
   335  	if obj.Kind == nil {
   336  		obj.Kind = new(v1.AzureDataDiskKind)
   337  		*obj.Kind = v1.AzureSharedBlobDisk
   338  	}
   339  	if obj.FSType == nil {
   340  		obj.FSType = new(string)
   341  		*obj.FSType = "ext4"
   342  	}
   343  	if obj.ReadOnly == nil {
   344  		obj.ReadOnly = new(bool)
   345  		*obj.ReadOnly = false
   346  	}
   347  }
   348  func SetDefaults_Endpoints(obj *v1.Endpoints) {
   349  	for i := range obj.Subsets {
   350  		ss := &obj.Subsets[i]
   351  		for i := range ss.Ports {
   352  			ep := &ss.Ports[i]
   353  			if ep.Protocol == "" {
   354  				ep.Protocol = v1.ProtocolTCP
   355  			}
   356  		}
   357  	}
   358  }
   359  func SetDefaults_HTTPGetAction(obj *v1.HTTPGetAction) {
   360  	if obj.Path == "" {
   361  		obj.Path = "/"
   362  	}
   363  	if obj.Scheme == "" {
   364  		obj.Scheme = v1.URISchemeHTTP
   365  	}
   366  }
   367  
   368  // SetDefaults_Namespace adds a default label for all namespaces
   369  func SetDefaults_Namespace(obj *v1.Namespace) {
   370  	// we can't SetDefaults for nameless namespaces (generateName).
   371  	// This code needs to be kept in sync with the implementation that exists
   372  	// in Namespace Canonicalize strategy (pkg/registry/core/namespace)
   373  
   374  	// note that this can result in many calls to feature enablement in some cases, but
   375  	// we assume that there's no real cost there.
   376  	if len(obj.Name) > 0 {
   377  		if obj.Labels == nil {
   378  			obj.Labels = map[string]string{}
   379  		}
   380  		obj.Labels[v1.LabelMetadataName] = obj.Name
   381  	}
   382  }
   383  
   384  func SetDefaults_NamespaceStatus(obj *v1.NamespaceStatus) {
   385  	if obj.Phase == "" {
   386  		obj.Phase = v1.NamespaceActive
   387  	}
   388  }
   389  func SetDefaults_NodeStatus(obj *v1.NodeStatus) {
   390  	if obj.Allocatable == nil && obj.Capacity != nil {
   391  		obj.Allocatable = make(v1.ResourceList, len(obj.Capacity))
   392  		for key, value := range obj.Capacity {
   393  			obj.Allocatable[key] = value.DeepCopy()
   394  		}
   395  		obj.Allocatable = obj.Capacity
   396  	}
   397  }
   398  func SetDefaults_ObjectFieldSelector(obj *v1.ObjectFieldSelector) {
   399  	if obj.APIVersion == "" {
   400  		obj.APIVersion = "v1"
   401  	}
   402  }
   403  func SetDefaults_LimitRangeItem(obj *v1.LimitRangeItem) {
   404  	// for container limits, we apply default values
   405  	if obj.Type == v1.LimitTypeContainer {
   406  
   407  		if obj.Default == nil {
   408  			obj.Default = make(v1.ResourceList)
   409  		}
   410  		if obj.DefaultRequest == nil {
   411  			obj.DefaultRequest = make(v1.ResourceList)
   412  		}
   413  
   414  		// If a default limit is unspecified, but the max is specified, default the limit to the max
   415  		for key, value := range obj.Max {
   416  			if _, exists := obj.Default[key]; !exists {
   417  				obj.Default[key] = value.DeepCopy()
   418  			}
   419  		}
   420  		// If a default limit is specified, but the default request is not, default request to limit
   421  		for key, value := range obj.Default {
   422  			if _, exists := obj.DefaultRequest[key]; !exists {
   423  				obj.DefaultRequest[key] = value.DeepCopy()
   424  			}
   425  		}
   426  		// If a default request is not specified, but the min is provided, default request to the min
   427  		for key, value := range obj.Min {
   428  			if _, exists := obj.DefaultRequest[key]; !exists {
   429  				obj.DefaultRequest[key] = value.DeepCopy()
   430  			}
   431  		}
   432  	}
   433  }
   434  func SetDefaults_ConfigMap(obj *v1.ConfigMap) {
   435  	if obj.Data == nil {
   436  		obj.Data = make(map[string]string)
   437  	}
   438  }
   439  
   440  // With host networking default all container ports to host ports.
   441  func defaultHostNetworkPorts(containers *[]v1.Container) {
   442  	for i := range *containers {
   443  		for j := range (*containers)[i].Ports {
   444  			if (*containers)[i].Ports[j].HostPort == 0 {
   445  				(*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
   446  			}
   447  		}
   448  	}
   449  }
   450  
   451  func SetDefaults_RBDVolumeSource(obj *v1.RBDVolumeSource) {
   452  	if obj.RBDPool == "" {
   453  		obj.RBDPool = "rbd"
   454  	}
   455  	if obj.RadosUser == "" {
   456  		obj.RadosUser = "admin"
   457  	}
   458  	if obj.Keyring == "" {
   459  		obj.Keyring = "/etc/ceph/keyring"
   460  	}
   461  }
   462  
   463  func SetDefaults_RBDPersistentVolumeSource(obj *v1.RBDPersistentVolumeSource) {
   464  	if obj.RBDPool == "" {
   465  		obj.RBDPool = "rbd"
   466  	}
   467  	if obj.RadosUser == "" {
   468  		obj.RadosUser = "admin"
   469  	}
   470  	if obj.Keyring == "" {
   471  		obj.Keyring = "/etc/ceph/keyring"
   472  	}
   473  }
   474  
   475  func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
   476  	if obj.StorageMode == "" {
   477  		obj.StorageMode = "ThinProvisioned"
   478  	}
   479  	if obj.FSType == "" {
   480  		obj.FSType = "xfs"
   481  	}
   482  }
   483  
   484  func SetDefaults_ScaleIOPersistentVolumeSource(obj *v1.ScaleIOPersistentVolumeSource) {
   485  	if obj.StorageMode == "" {
   486  		obj.StorageMode = "ThinProvisioned"
   487  	}
   488  	if obj.FSType == "" {
   489  		obj.FSType = "xfs"
   490  	}
   491  }
   492  
   493  func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) {
   494  	typeVol := v1.HostPathUnset
   495  	if obj.Type == nil {
   496  		obj.Type = &typeVol
   497  	}
   498  }
   499  

View as plain text