1/* 2Copyright 2015 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package v1 18 19import ( 20 "k8s.io/apimachinery/pkg/runtime" 21 "k8s.io/apimachinery/pkg/util/intstr" 22 "k8s.io/client-go/pkg/util" 23 "k8s.io/client-go/pkg/util/parsers" 24) 25 26func addDefaultingFuncs(scheme *runtime.Scheme) error { 27 RegisterDefaults(scheme) 28 return scheme.AddDefaultingFuncs( 29 SetDefaults_PodExecOptions, 30 SetDefaults_PodAttachOptions, 31 SetDefaults_ReplicationController, 32 SetDefaults_Volume, 33 SetDefaults_ContainerPort, 34 SetDefaults_Container, 35 SetDefaults_ServiceSpec, 36 SetDefaults_Pod, 37 SetDefaults_PodSpec, 38 SetDefaults_Probe, 39 SetDefaults_SecretVolumeSource, 40 SetDefaults_ConfigMapVolumeSource, 41 SetDefaults_DownwardAPIVolumeSource, 42 SetDefaults_ProjectedVolumeSource, 43 SetDefaults_Secret, 44 SetDefaults_PersistentVolume, 45 SetDefaults_PersistentVolumeClaim, 46 SetDefaults_ISCSIVolumeSource, 47 SetDefaults_Endpoints, 48 SetDefaults_HTTPGetAction, 49 SetDefaults_NamespaceStatus, 50 SetDefaults_Node, 51 SetDefaults_NodeStatus, 52 SetDefaults_ObjectFieldSelector, 53 SetDefaults_LimitRangeItem, 54 SetDefaults_ConfigMap, 55 SetDefaults_RBDVolumeSource, 56 SetDefaults_ResourceList, 57 ) 58} 59 60func SetDefaults_ResourceList(obj *ResourceList) { 61 for key, val := range *obj { 62 // TODO(#18538): We round up resource values to milli scale to maintain API compatibility. 63 // In the future, we should instead reject values that need rounding. 64 const milliScale = -3 65 val.RoundUp(milliScale) 66 67 (*obj)[ResourceName(key)] = val 68 } 69} 70 71func SetDefaults_PodExecOptions(obj *PodExecOptions) { 72 obj.Stdout = true 73 obj.Stderr = true 74} 75func SetDefaults_PodAttachOptions(obj *PodAttachOptions) { 76 obj.Stdout = true 77 obj.Stderr = true 78} 79func SetDefaults_ReplicationController(obj *ReplicationController) { 80 var labels map[string]string 81 if obj.Spec.Template != nil { 82 labels = obj.Spec.Template.Labels 83 } 84 // TODO: support templates defined elsewhere when we support them in the API 85 if labels != nil { 86 if len(obj.Spec.Selector) == 0 { 87 obj.Spec.Selector = labels 88 } 89 if len(obj.Labels) == 0 { 90 obj.Labels = labels 91 } 92 } 93 if obj.Spec.Replicas == nil { 94 obj.Spec.Replicas = new(int32) 95 *obj.Spec.Replicas = 1 96 } 97} 98func SetDefaults_Volume(obj *Volume) { 99 if util.AllPtrFieldsNil(&obj.VolumeSource) { 100 obj.VolumeSource = VolumeSource{ 101 EmptyDir: &EmptyDirVolumeSource{}, 102 } 103 } 104} 105func SetDefaults_ContainerPort(obj *ContainerPort) { 106 if obj.Protocol == "" { 107 obj.Protocol = ProtocolTCP 108 } 109} 110func SetDefaults_Container(obj *Container) { 111 if obj.ImagePullPolicy == "" { 112 // Ignore error and assume it has been validated elsewhere 113 _, tag, _, _ := parsers.ParseImageName(obj.Image) 114 115 // Check image tag 116 if tag == "latest" { 117 obj.ImagePullPolicy = PullAlways 118 } else { 119 obj.ImagePullPolicy = PullIfNotPresent 120 } 121 } 122 if obj.TerminationMessagePath == "" { 123 obj.TerminationMessagePath = TerminationMessagePathDefault 124 } 125 if obj.TerminationMessagePolicy == "" { 126 obj.TerminationMessagePolicy = TerminationMessageReadFile 127 } 128} 129func SetDefaults_ServiceSpec(obj *ServiceSpec) { 130 if obj.SessionAffinity == "" { 131 obj.SessionAffinity = ServiceAffinityNone 132 } 133 if obj.Type == "" { 134 obj.Type = ServiceTypeClusterIP 135 } 136 for i := range obj.Ports { 137 sp := &obj.Ports[i] 138 if sp.Protocol == "" { 139 sp.Protocol = ProtocolTCP 140 } 141 if sp.TargetPort == intstr.FromInt(0) || sp.TargetPort == intstr.FromString("") { 142 sp.TargetPort = intstr.FromInt(int(sp.Port)) 143 } 144 } 145} 146func SetDefaults_Pod(obj *Pod) { 147 // If limits are specified, but requests are not, default requests to limits 148 // This is done here rather than a more specific defaulting pass on ResourceRequirements 149 // because we only want this defaulting semantic to take place on a Pod and not a PodTemplate 150 for i := range obj.Spec.Containers { 151 // set requests to limits if requests are not specified, but limits are 152 if obj.Spec.Containers[i].Resources.Limits != nil { 153 if obj.Spec.Containers[i].Resources.Requests == nil { 154 obj.Spec.Containers[i].Resources.Requests = make(ResourceList) 155 } 156 for key, value := range obj.Spec.Containers[i].Resources.Limits { 157 if _, exists := obj.Spec.Containers[i].Resources.Requests[key]; !exists { 158 obj.Spec.Containers[i].Resources.Requests[key] = *(value.Copy()) 159 } 160 } 161 } 162 } 163 for i := range obj.Spec.InitContainers { 164 if obj.Spec.InitContainers[i].Resources.Limits != nil { 165 if obj.Spec.InitContainers[i].Resources.Requests == nil { 166 obj.Spec.InitContainers[i].Resources.Requests = make(ResourceList) 167 } 168 for key, value := range obj.Spec.InitContainers[i].Resources.Limits { 169 if _, exists := obj.Spec.InitContainers[i].Resources.Requests[key]; !exists { 170 obj.Spec.InitContainers[i].Resources.Requests[key] = *(value.Copy()) 171 } 172 } 173 } 174 } 175} 176func SetDefaults_PodSpec(obj *PodSpec) { 177 if obj.DNSPolicy == "" { 178 obj.DNSPolicy = DNSClusterFirst 179 } 180 if obj.RestartPolicy == "" { 181 obj.RestartPolicy = RestartPolicyAlways 182 } 183 if obj.HostNetwork { 184 defaultHostNetworkPorts(&obj.Containers) 185 defaultHostNetworkPorts(&obj.InitContainers) 186 } 187 if obj.SecurityContext == nil { 188 obj.SecurityContext = &PodSecurityContext{} 189 } 190 if obj.TerminationGracePeriodSeconds == nil { 191 period := int64(DefaultTerminationGracePeriodSeconds) 192 obj.TerminationGracePeriodSeconds = &period 193 } 194 if obj.SchedulerName == "" { 195 obj.SchedulerName = DefaultSchedulerName 196 } 197} 198func SetDefaults_Probe(obj *Probe) { 199 if obj.TimeoutSeconds == 0 { 200 obj.TimeoutSeconds = 1 201 } 202 if obj.PeriodSeconds == 0 { 203 obj.PeriodSeconds = 10 204 } 205 if obj.SuccessThreshold == 0 { 206 obj.SuccessThreshold = 1 207 } 208 if obj.FailureThreshold == 0 { 209 obj.FailureThreshold = 3 210 } 211} 212func SetDefaults_SecretVolumeSource(obj *SecretVolumeSource) { 213 if obj.DefaultMode == nil { 214 perm := int32(SecretVolumeSourceDefaultMode) 215 obj.DefaultMode = &perm 216 } 217} 218func SetDefaults_ConfigMapVolumeSource(obj *ConfigMapVolumeSource) { 219 if obj.DefaultMode == nil { 220 perm := int32(ConfigMapVolumeSourceDefaultMode) 221 obj.DefaultMode = &perm 222 } 223} 224func SetDefaults_DownwardAPIVolumeSource(obj *DownwardAPIVolumeSource) { 225 if obj.DefaultMode == nil { 226 perm := int32(DownwardAPIVolumeSourceDefaultMode) 227 obj.DefaultMode = &perm 228 } 229} 230func SetDefaults_Secret(obj *Secret) { 231 if obj.Type == "" { 232 obj.Type = SecretTypeOpaque 233 } 234} 235func SetDefaults_ProjectedVolumeSource(obj *ProjectedVolumeSource) { 236 if obj.DefaultMode == nil { 237 perm := int32(ProjectedVolumeSourceDefaultMode) 238 obj.DefaultMode = &perm 239 } 240} 241func SetDefaults_PersistentVolume(obj *PersistentVolume) { 242 if obj.Status.Phase == "" { 243 obj.Status.Phase = VolumePending 244 } 245 if obj.Spec.PersistentVolumeReclaimPolicy == "" { 246 obj.Spec.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimRetain 247 } 248} 249func SetDefaults_PersistentVolumeClaim(obj *PersistentVolumeClaim) { 250 if obj.Status.Phase == "" { 251 obj.Status.Phase = ClaimPending 252 } 253} 254func SetDefaults_ISCSIVolumeSource(obj *ISCSIVolumeSource) { 255 if obj.ISCSIInterface == "" { 256 obj.ISCSIInterface = "default" 257 } 258} 259func SetDefaults_AzureDiskVolumeSource(obj *AzureDiskVolumeSource) { 260 if obj.CachingMode == nil { 261 obj.CachingMode = new(AzureDataDiskCachingMode) 262 *obj.CachingMode = AzureDataDiskCachingNone 263 } 264 if obj.FSType == nil { 265 obj.FSType = new(string) 266 *obj.FSType = "ext4" 267 } 268 if obj.ReadOnly == nil { 269 obj.ReadOnly = new(bool) 270 *obj.ReadOnly = false 271 } 272} 273func SetDefaults_Endpoints(obj *Endpoints) { 274 for i := range obj.Subsets { 275 ss := &obj.Subsets[i] 276 for i := range ss.Ports { 277 ep := &ss.Ports[i] 278 if ep.Protocol == "" { 279 ep.Protocol = ProtocolTCP 280 } 281 } 282 } 283} 284func SetDefaults_HTTPGetAction(obj *HTTPGetAction) { 285 if obj.Path == "" { 286 obj.Path = "/" 287 } 288 if obj.Scheme == "" { 289 obj.Scheme = URISchemeHTTP 290 } 291} 292func SetDefaults_NamespaceStatus(obj *NamespaceStatus) { 293 if obj.Phase == "" { 294 obj.Phase = NamespaceActive 295 } 296} 297func SetDefaults_Node(obj *Node) { 298 if obj.Spec.ExternalID == "" { 299 obj.Spec.ExternalID = obj.Name 300 } 301} 302func SetDefaults_NodeStatus(obj *NodeStatus) { 303 if obj.Allocatable == nil && obj.Capacity != nil { 304 obj.Allocatable = make(ResourceList, len(obj.Capacity)) 305 for key, value := range obj.Capacity { 306 obj.Allocatable[key] = *(value.Copy()) 307 } 308 obj.Allocatable = obj.Capacity 309 } 310} 311func SetDefaults_ObjectFieldSelector(obj *ObjectFieldSelector) { 312 if obj.APIVersion == "" { 313 obj.APIVersion = "v1" 314 } 315} 316func SetDefaults_LimitRangeItem(obj *LimitRangeItem) { 317 // for container limits, we apply default values 318 if obj.Type == LimitTypeContainer { 319 320 if obj.Default == nil { 321 obj.Default = make(ResourceList) 322 } 323 if obj.DefaultRequest == nil { 324 obj.DefaultRequest = make(ResourceList) 325 } 326 327 // If a default limit is unspecified, but the max is specified, default the limit to the max 328 for key, value := range obj.Max { 329 if _, exists := obj.Default[key]; !exists { 330 obj.Default[key] = *(value.Copy()) 331 } 332 } 333 // If a default limit is specified, but the default request is not, default request to limit 334 for key, value := range obj.Default { 335 if _, exists := obj.DefaultRequest[key]; !exists { 336 obj.DefaultRequest[key] = *(value.Copy()) 337 } 338 } 339 // If a default request is not specified, but the min is provided, default request to the min 340 for key, value := range obj.Min { 341 if _, exists := obj.DefaultRequest[key]; !exists { 342 obj.DefaultRequest[key] = *(value.Copy()) 343 } 344 } 345 } 346} 347func SetDefaults_ConfigMap(obj *ConfigMap) { 348 if obj.Data == nil { 349 obj.Data = make(map[string]string) 350 } 351} 352 353// With host networking default all container ports to host ports. 354func defaultHostNetworkPorts(containers *[]Container) { 355 for i := range *containers { 356 for j := range (*containers)[i].Ports { 357 if (*containers)[i].Ports[j].HostPort == 0 { 358 (*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort 359 } 360 } 361 } 362} 363 364func SetDefaults_RBDVolumeSource(obj *RBDVolumeSource) { 365 if obj.RBDPool == "" { 366 obj.RBDPool = "rbd" 367 } 368 if obj.RadosUser == "" { 369 obj.RadosUser = "admin" 370 } 371 if obj.Keyring == "" { 372 obj.Keyring = "/etc/ceph/keyring" 373 } 374} 375 376func SetDefaults_ScaleIOVolumeSource(obj *ScaleIOVolumeSource) { 377 if obj.ProtectionDomain == "" { 378 obj.ProtectionDomain = "default" 379 } 380 if obj.StoragePool == "" { 381 obj.StoragePool = "default" 382 } 383 if obj.StorageMode == "" { 384 obj.StorageMode = "ThinProvisioned" 385 } 386 if obj.FSType == "" { 387 obj.FSType = "xfs" 388 } 389} 390