123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- /*
- Copyright 2015 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package v1
- import (
- "time"
- "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/runtime"
- "k8s.io/apimachinery/pkg/util/intstr"
- "k8s.io/kubernetes/pkg/util/parsers"
- utilpointer "k8s.io/utils/pointer"
- utilfeature "k8s.io/apiserver/pkg/util/feature"
- "k8s.io/kubernetes/pkg/features"
- utilnet "k8s.io/utils/net"
- )
- func addDefaultingFuncs(scheme *runtime.Scheme) error {
- return RegisterDefaults(scheme)
- }
- func SetDefaults_ResourceList(obj *v1.ResourceList) {
- for key, val := range *obj {
- // TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
- // In the future, we should instead reject values that need rounding.
- const milliScale = -3
- val.RoundUp(milliScale)
- (*obj)[v1.ResourceName(key)] = val
- }
- }
- func SetDefaults_ReplicationController(obj *v1.ReplicationController) {
- var labels map[string]string
- if obj.Spec.Template != nil {
- labels = obj.Spec.Template.Labels
- }
- // TODO: support templates defined elsewhere when we support them in the API
- if labels != nil {
- if len(obj.Spec.Selector) == 0 {
- obj.Spec.Selector = labels
- }
- if len(obj.Labels) == 0 {
- obj.Labels = labels
- }
- }
- if obj.Spec.Replicas == nil {
- obj.Spec.Replicas = new(int32)
- *obj.Spec.Replicas = 1
- }
- }
- func SetDefaults_Volume(obj *v1.Volume) {
- if utilpointer.AllPtrFieldsNil(&obj.VolumeSource) {
- obj.VolumeSource = v1.VolumeSource{
- EmptyDir: &v1.EmptyDirVolumeSource{},
- }
- }
- }
- func SetDefaults_ContainerPort(obj *v1.ContainerPort) {
- if obj.Protocol == "" {
- obj.Protocol = v1.ProtocolTCP
- }
- }
- func SetDefaults_Container(obj *v1.Container) {
- if obj.ImagePullPolicy == "" {
- // Ignore error and assume it has been validated elsewhere
- _, tag, _, _ := parsers.ParseImageName(obj.Image)
- // Check image tag
- if tag == "latest" {
- obj.ImagePullPolicy = v1.PullAlways
- } else {
- obj.ImagePullPolicy = v1.PullIfNotPresent
- }
- }
- if obj.TerminationMessagePath == "" {
- obj.TerminationMessagePath = v1.TerminationMessagePathDefault
- }
- if obj.TerminationMessagePolicy == "" {
- obj.TerminationMessagePolicy = v1.TerminationMessageReadFile
- }
- }
- func SetDefaults_Service(obj *v1.Service) {
- if obj.Spec.SessionAffinity == "" {
- obj.Spec.SessionAffinity = v1.ServiceAffinityNone
- }
- if obj.Spec.SessionAffinity == v1.ServiceAffinityNone {
- obj.Spec.SessionAffinityConfig = nil
- }
- if obj.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
- if obj.Spec.SessionAffinityConfig == nil || obj.Spec.SessionAffinityConfig.ClientIP == nil || obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil {
- timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
- obj.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
- ClientIP: &v1.ClientIPConfig{
- TimeoutSeconds: &timeoutSeconds,
- },
- }
- }
- }
- if obj.Spec.Type == "" {
- obj.Spec.Type = v1.ServiceTypeClusterIP
- }
- for i := range obj.Spec.Ports {
- sp := &obj.Spec.Ports[i]
- if sp.Protocol == "" {
- sp.Protocol = v1.ProtocolTCP
- }
- if sp.TargetPort == intstr.FromInt(0) || sp.TargetPort == intstr.FromString("") {
- sp.TargetPort = intstr.FromInt(int(sp.Port))
- }
- }
- // Defaults ExternalTrafficPolicy field for NodePort / LoadBalancer service
- // to Global for consistency.
- if (obj.Spec.Type == v1.ServiceTypeNodePort ||
- obj.Spec.Type == v1.ServiceTypeLoadBalancer) &&
- obj.Spec.ExternalTrafficPolicy == "" {
- obj.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
- }
- // if dualstack feature gate is on then we need to default
- // Spec.IPFamily correctly. This is to cover the case
- // when an existing cluster have been converted to dualstack
- // i.e. it already contain services with Spec.IPFamily==nil
- if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) &&
- obj.Spec.Type != v1.ServiceTypeExternalName &&
- obj.Spec.ClusterIP != "" && /*has an ip already set*/
- obj.Spec.ClusterIP != "None" && /* not converting from ExternalName to other */
- obj.Spec.IPFamily == nil /* family was not previously set */ {
- // there is a change that the ClusterIP (set by user) is unparsable.
- // in this case, the family will be set mistakenly to ipv4 (because
- // the util function does not parse errors *sigh*). The error
- // will be caught in validation which asserts the validity of the
- // IP and the service object will not be persisted with the wrong IP
- // family
- ipv6 := v1.IPv6Protocol
- ipv4 := v1.IPv4Protocol
- if utilnet.IsIPv6String(obj.Spec.ClusterIP) {
- obj.Spec.IPFamily = &ipv6
- } else {
- obj.Spec.IPFamily = &ipv4
- }
- }
- }
- func SetDefaults_Pod(obj *v1.Pod) {
- // If limits are specified, but requests are not, default requests to limits
- // This is done here rather than a more specific defaulting pass on v1.ResourceRequirements
- // because we only want this defaulting semantic to take place on a v1.Pod and not a v1.PodTemplate
- for i := range obj.Spec.Containers {
- // set requests to limits if requests are not specified, but limits are
- if obj.Spec.Containers[i].Resources.Limits != nil {
- if obj.Spec.Containers[i].Resources.Requests == nil {
- obj.Spec.Containers[i].Resources.Requests = make(v1.ResourceList)
- }
- for key, value := range obj.Spec.Containers[i].Resources.Limits {
- if _, exists := obj.Spec.Containers[i].Resources.Requests[key]; !exists {
- obj.Spec.Containers[i].Resources.Requests[key] = value.DeepCopy()
- }
- }
- }
- }
- for i := range obj.Spec.InitContainers {
- if obj.Spec.InitContainers[i].Resources.Limits != nil {
- if obj.Spec.InitContainers[i].Resources.Requests == nil {
- obj.Spec.InitContainers[i].Resources.Requests = make(v1.ResourceList)
- }
- for key, value := range obj.Spec.InitContainers[i].Resources.Limits {
- if _, exists := obj.Spec.InitContainers[i].Resources.Requests[key]; !exists {
- obj.Spec.InitContainers[i].Resources.Requests[key] = value.DeepCopy()
- }
- }
- }
- }
- if obj.Spec.EnableServiceLinks == nil {
- enableServiceLinks := v1.DefaultEnableServiceLinks
- obj.Spec.EnableServiceLinks = &enableServiceLinks
- }
- }
- func SetDefaults_PodSpec(obj *v1.PodSpec) {
- // New fields added here will break upgrade tests:
- // https://github.com/kubernetes/kubernetes/issues/69445
- // In most cases the new defaulted field can added to SetDefaults_Pod instead of here, so
- // that it only materializes in the Pod object and not all objects with a PodSpec field.
- if obj.DNSPolicy == "" {
- obj.DNSPolicy = v1.DNSClusterFirst
- }
- if obj.RestartPolicy == "" {
- obj.RestartPolicy = v1.RestartPolicyAlways
- }
- if obj.HostNetwork {
- defaultHostNetworkPorts(&obj.Containers)
- defaultHostNetworkPorts(&obj.InitContainers)
- }
- if obj.SecurityContext == nil {
- obj.SecurityContext = &v1.PodSecurityContext{}
- }
- if obj.TerminationGracePeriodSeconds == nil {
- period := int64(v1.DefaultTerminationGracePeriodSeconds)
- obj.TerminationGracePeriodSeconds = &period
- }
- if obj.SchedulerName == "" {
- obj.SchedulerName = v1.DefaultSchedulerName
- }
- }
- func SetDefaults_Probe(obj *v1.Probe) {
- if obj.TimeoutSeconds == 0 {
- obj.TimeoutSeconds = 1
- }
- if obj.PeriodSeconds == 0 {
- obj.PeriodSeconds = 10
- }
- if obj.SuccessThreshold == 0 {
- obj.SuccessThreshold = 1
- }
- if obj.FailureThreshold == 0 {
- obj.FailureThreshold = 3
- }
- }
- func SetDefaults_SecretVolumeSource(obj *v1.SecretVolumeSource) {
- if obj.DefaultMode == nil {
- perm := int32(v1.SecretVolumeSourceDefaultMode)
- obj.DefaultMode = &perm
- }
- }
- func SetDefaults_ConfigMapVolumeSource(obj *v1.ConfigMapVolumeSource) {
- if obj.DefaultMode == nil {
- perm := int32(v1.ConfigMapVolumeSourceDefaultMode)
- obj.DefaultMode = &perm
- }
- }
- func SetDefaults_DownwardAPIVolumeSource(obj *v1.DownwardAPIVolumeSource) {
- if obj.DefaultMode == nil {
- perm := int32(v1.DownwardAPIVolumeSourceDefaultMode)
- obj.DefaultMode = &perm
- }
- }
- func SetDefaults_Secret(obj *v1.Secret) {
- if obj.Type == "" {
- obj.Type = v1.SecretTypeOpaque
- }
- }
- func SetDefaults_ProjectedVolumeSource(obj *v1.ProjectedVolumeSource) {
- if obj.DefaultMode == nil {
- perm := int32(v1.ProjectedVolumeSourceDefaultMode)
- obj.DefaultMode = &perm
- }
- }
- func SetDefaults_ServiceAccountTokenProjection(obj *v1.ServiceAccountTokenProjection) {
- hour := int64(time.Hour.Seconds())
- if obj.ExpirationSeconds == nil {
- obj.ExpirationSeconds = &hour
- }
- }
- func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) {
- if obj.Status.Phase == "" {
- obj.Status.Phase = v1.VolumePending
- }
- if obj.Spec.PersistentVolumeReclaimPolicy == "" {
- obj.Spec.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimRetain
- }
- if obj.Spec.VolumeMode == nil {
- obj.Spec.VolumeMode = new(v1.PersistentVolumeMode)
- *obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem
- }
- }
- func SetDefaults_PersistentVolumeClaim(obj *v1.PersistentVolumeClaim) {
- if obj.Status.Phase == "" {
- obj.Status.Phase = v1.ClaimPending
- }
- if obj.Spec.VolumeMode == nil {
- obj.Spec.VolumeMode = new(v1.PersistentVolumeMode)
- *obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem
- }
- }
- func SetDefaults_ISCSIVolumeSource(obj *v1.ISCSIVolumeSource) {
- if obj.ISCSIInterface == "" {
- obj.ISCSIInterface = "default"
- }
- }
- func SetDefaults_ISCSIPersistentVolumeSource(obj *v1.ISCSIPersistentVolumeSource) {
- if obj.ISCSIInterface == "" {
- obj.ISCSIInterface = "default"
- }
- }
- func SetDefaults_AzureDiskVolumeSource(obj *v1.AzureDiskVolumeSource) {
- if obj.CachingMode == nil {
- obj.CachingMode = new(v1.AzureDataDiskCachingMode)
- *obj.CachingMode = v1.AzureDataDiskCachingReadWrite
- }
- if obj.Kind == nil {
- obj.Kind = new(v1.AzureDataDiskKind)
- *obj.Kind = v1.AzureSharedBlobDisk
- }
- if obj.FSType == nil {
- obj.FSType = new(string)
- *obj.FSType = "ext4"
- }
- if obj.ReadOnly == nil {
- obj.ReadOnly = new(bool)
- *obj.ReadOnly = false
- }
- }
- func SetDefaults_Endpoints(obj *v1.Endpoints) {
- for i := range obj.Subsets {
- ss := &obj.Subsets[i]
- for i := range ss.Ports {
- ep := &ss.Ports[i]
- if ep.Protocol == "" {
- ep.Protocol = v1.ProtocolTCP
- }
- }
- }
- }
- func SetDefaults_HTTPGetAction(obj *v1.HTTPGetAction) {
- if obj.Path == "" {
- obj.Path = "/"
- }
- if obj.Scheme == "" {
- obj.Scheme = v1.URISchemeHTTP
- }
- }
- func SetDefaults_NamespaceStatus(obj *v1.NamespaceStatus) {
- if obj.Phase == "" {
- obj.Phase = v1.NamespaceActive
- }
- }
- func SetDefaults_NodeStatus(obj *v1.NodeStatus) {
- if obj.Allocatable == nil && obj.Capacity != nil {
- obj.Allocatable = make(v1.ResourceList, len(obj.Capacity))
- for key, value := range obj.Capacity {
- obj.Allocatable[key] = value.DeepCopy()
- }
- obj.Allocatable = obj.Capacity
- }
- }
- func SetDefaults_ObjectFieldSelector(obj *v1.ObjectFieldSelector) {
- if obj.APIVersion == "" {
- obj.APIVersion = "v1"
- }
- }
- func SetDefaults_LimitRangeItem(obj *v1.LimitRangeItem) {
- // for container limits, we apply default values
- if obj.Type == v1.LimitTypeContainer {
- if obj.Default == nil {
- obj.Default = make(v1.ResourceList)
- }
- if obj.DefaultRequest == nil {
- obj.DefaultRequest = make(v1.ResourceList)
- }
- // If a default limit is unspecified, but the max is specified, default the limit to the max
- for key, value := range obj.Max {
- if _, exists := obj.Default[key]; !exists {
- obj.Default[key] = value.DeepCopy()
- }
- }
- // If a default limit is specified, but the default request is not, default request to limit
- for key, value := range obj.Default {
- if _, exists := obj.DefaultRequest[key]; !exists {
- obj.DefaultRequest[key] = value.DeepCopy()
- }
- }
- // If a default request is not specified, but the min is provided, default request to the min
- for key, value := range obj.Min {
- if _, exists := obj.DefaultRequest[key]; !exists {
- obj.DefaultRequest[key] = value.DeepCopy()
- }
- }
- }
- }
- func SetDefaults_ConfigMap(obj *v1.ConfigMap) {
- if obj.Data == nil {
- obj.Data = make(map[string]string)
- }
- }
- // With host networking default all container ports to host ports.
- func defaultHostNetworkPorts(containers *[]v1.Container) {
- for i := range *containers {
- for j := range (*containers)[i].Ports {
- if (*containers)[i].Ports[j].HostPort == 0 {
- (*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
- }
- }
- }
- }
- func SetDefaults_RBDVolumeSource(obj *v1.RBDVolumeSource) {
- if obj.RBDPool == "" {
- obj.RBDPool = "rbd"
- }
- if obj.RadosUser == "" {
- obj.RadosUser = "admin"
- }
- if obj.Keyring == "" {
- obj.Keyring = "/etc/ceph/keyring"
- }
- }
- func SetDefaults_RBDPersistentVolumeSource(obj *v1.RBDPersistentVolumeSource) {
- if obj.RBDPool == "" {
- obj.RBDPool = "rbd"
- }
- if obj.RadosUser == "" {
- obj.RadosUser = "admin"
- }
- if obj.Keyring == "" {
- obj.Keyring = "/etc/ceph/keyring"
- }
- }
- func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
- if obj.StorageMode == "" {
- obj.StorageMode = "ThinProvisioned"
- }
- if obj.FSType == "" {
- obj.FSType = "xfs"
- }
- }
- func SetDefaults_ScaleIOPersistentVolumeSource(obj *v1.ScaleIOPersistentVolumeSource) {
- if obj.StorageMode == "" {
- obj.StorageMode = "ThinProvisioned"
- }
- if obj.FSType == "" {
- obj.FSType = "xfs"
- }
- }
- func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) {
- typeVol := v1.HostPathUnset
- if obj.Type == nil {
- obj.Type = &typeVol
- }
- }
|