k8s.io/kubernetes@v1.29.3/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 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 }