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 }