defaults.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package v1
  14. import (
  15. "time"
  16. "k8s.io/api/core/v1"
  17. "k8s.io/apimachinery/pkg/runtime"
  18. "k8s.io/apimachinery/pkg/util/intstr"
  19. "k8s.io/kubernetes/pkg/util/parsers"
  20. utilpointer "k8s.io/utils/pointer"
  21. utilfeature "k8s.io/apiserver/pkg/util/feature"
  22. "k8s.io/kubernetes/pkg/features"
  23. utilnet "k8s.io/utils/net"
  24. )
  25. func addDefaultingFuncs(scheme *runtime.Scheme) error {
  26. return RegisterDefaults(scheme)
  27. }
  28. func SetDefaults_ResourceList(obj *v1.ResourceList) {
  29. for key, val := range *obj {
  30. // TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
  31. // In the future, we should instead reject values that need rounding.
  32. const milliScale = -3
  33. val.RoundUp(milliScale)
  34. (*obj)[v1.ResourceName(key)] = val
  35. }
  36. }
  37. func SetDefaults_ReplicationController(obj *v1.ReplicationController) {
  38. var labels map[string]string
  39. if obj.Spec.Template != nil {
  40. labels = obj.Spec.Template.Labels
  41. }
  42. // TODO: support templates defined elsewhere when we support them in the API
  43. if labels != nil {
  44. if len(obj.Spec.Selector) == 0 {
  45. obj.Spec.Selector = labels
  46. }
  47. if len(obj.Labels) == 0 {
  48. obj.Labels = labels
  49. }
  50. }
  51. if obj.Spec.Replicas == nil {
  52. obj.Spec.Replicas = new(int32)
  53. *obj.Spec.Replicas = 1
  54. }
  55. }
  56. func SetDefaults_Volume(obj *v1.Volume) {
  57. if utilpointer.AllPtrFieldsNil(&obj.VolumeSource) {
  58. obj.VolumeSource = v1.VolumeSource{
  59. EmptyDir: &v1.EmptyDirVolumeSource{},
  60. }
  61. }
  62. }
  63. func SetDefaults_ContainerPort(obj *v1.ContainerPort) {
  64. if obj.Protocol == "" {
  65. obj.Protocol = v1.ProtocolTCP
  66. }
  67. }
  68. func SetDefaults_Container(obj *v1.Container) {
  69. if obj.ImagePullPolicy == "" {
  70. // Ignore error and assume it has been validated elsewhere
  71. _, tag, _, _ := parsers.ParseImageName(obj.Image)
  72. // Check image tag
  73. if tag == "latest" {
  74. obj.ImagePullPolicy = v1.PullAlways
  75. } else {
  76. obj.ImagePullPolicy = v1.PullIfNotPresent
  77. }
  78. }
  79. if obj.TerminationMessagePath == "" {
  80. obj.TerminationMessagePath = v1.TerminationMessagePathDefault
  81. }
  82. if obj.TerminationMessagePolicy == "" {
  83. obj.TerminationMessagePolicy = v1.TerminationMessageReadFile
  84. }
  85. }
  86. func SetDefaults_Service(obj *v1.Service) {
  87. if obj.Spec.SessionAffinity == "" {
  88. obj.Spec.SessionAffinity = v1.ServiceAffinityNone
  89. }
  90. if obj.Spec.SessionAffinity == v1.ServiceAffinityNone {
  91. obj.Spec.SessionAffinityConfig = nil
  92. }
  93. if obj.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
  94. if obj.Spec.SessionAffinityConfig == nil || obj.Spec.SessionAffinityConfig.ClientIP == nil || obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil {
  95. timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
  96. obj.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
  97. ClientIP: &v1.ClientIPConfig{
  98. TimeoutSeconds: &timeoutSeconds,
  99. },
  100. }
  101. }
  102. }
  103. if obj.Spec.Type == "" {
  104. obj.Spec.Type = v1.ServiceTypeClusterIP
  105. }
  106. for i := range obj.Spec.Ports {
  107. sp := &obj.Spec.Ports[i]
  108. if sp.Protocol == "" {
  109. sp.Protocol = v1.ProtocolTCP
  110. }
  111. if sp.TargetPort == intstr.FromInt(0) || sp.TargetPort == intstr.FromString("") {
  112. sp.TargetPort = intstr.FromInt(int(sp.Port))
  113. }
  114. }
  115. // Defaults ExternalTrafficPolicy field for NodePort / LoadBalancer service
  116. // to Global for consistency.
  117. if (obj.Spec.Type == v1.ServiceTypeNodePort ||
  118. obj.Spec.Type == v1.ServiceTypeLoadBalancer) &&
  119. obj.Spec.ExternalTrafficPolicy == "" {
  120. obj.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
  121. }
  122. // if dualstack feature gate is on then we need to default
  123. // Spec.IPFamily correctly. This is to cover the case
  124. // when an existing cluster have been converted to dualstack
  125. // i.e. it already contain services with Spec.IPFamily==nil
  126. if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) &&
  127. obj.Spec.Type != v1.ServiceTypeExternalName &&
  128. obj.Spec.ClusterIP != "" && /*has an ip already set*/
  129. obj.Spec.ClusterIP != "None" && /* not converting from ExternalName to other */
  130. obj.Spec.IPFamily == nil /* family was not previously set */ {
  131. // there is a change that the ClusterIP (set by user) is unparsable.
  132. // in this case, the family will be set mistakenly to ipv4 (because
  133. // the util function does not parse errors *sigh*). The error
  134. // will be caught in validation which asserts the validity of the
  135. // IP and the service object will not be persisted with the wrong IP
  136. // family
  137. ipv6 := v1.IPv6Protocol
  138. ipv4 := v1.IPv4Protocol
  139. if utilnet.IsIPv6String(obj.Spec.ClusterIP) {
  140. obj.Spec.IPFamily = &ipv6
  141. } else {
  142. obj.Spec.IPFamily = &ipv4
  143. }
  144. }
  145. }
  146. func SetDefaults_Pod(obj *v1.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 v1.ResourceRequirements
  149. // because we only want this defaulting semantic to take place on a v1.Pod and not a v1.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(v1.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.DeepCopy()
  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(v1.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.DeepCopy()
  171. }
  172. }
  173. }
  174. }
  175. if obj.Spec.EnableServiceLinks == nil {
  176. enableServiceLinks := v1.DefaultEnableServiceLinks
  177. obj.Spec.EnableServiceLinks = &enableServiceLinks
  178. }
  179. }
  180. func SetDefaults_PodSpec(obj *v1.PodSpec) {
  181. // New fields added here will break upgrade tests:
  182. // https://github.com/kubernetes/kubernetes/issues/69445
  183. // In most cases the new defaulted field can added to SetDefaults_Pod instead of here, so
  184. // that it only materializes in the Pod object and not all objects with a PodSpec field.
  185. if obj.DNSPolicy == "" {
  186. obj.DNSPolicy = v1.DNSClusterFirst
  187. }
  188. if obj.RestartPolicy == "" {
  189. obj.RestartPolicy = v1.RestartPolicyAlways
  190. }
  191. if obj.HostNetwork {
  192. defaultHostNetworkPorts(&obj.Containers)
  193. defaultHostNetworkPorts(&obj.InitContainers)
  194. }
  195. if obj.SecurityContext == nil {
  196. obj.SecurityContext = &v1.PodSecurityContext{}
  197. }
  198. if obj.TerminationGracePeriodSeconds == nil {
  199. period := int64(v1.DefaultTerminationGracePeriodSeconds)
  200. obj.TerminationGracePeriodSeconds = &period
  201. }
  202. if obj.SchedulerName == "" {
  203. obj.SchedulerName = v1.DefaultSchedulerName
  204. }
  205. }
  206. func SetDefaults_Probe(obj *v1.Probe) {
  207. if obj.TimeoutSeconds == 0 {
  208. obj.TimeoutSeconds = 1
  209. }
  210. if obj.PeriodSeconds == 0 {
  211. obj.PeriodSeconds = 10
  212. }
  213. if obj.SuccessThreshold == 0 {
  214. obj.SuccessThreshold = 1
  215. }
  216. if obj.FailureThreshold == 0 {
  217. obj.FailureThreshold = 3
  218. }
  219. }
  220. func SetDefaults_SecretVolumeSource(obj *v1.SecretVolumeSource) {
  221. if obj.DefaultMode == nil {
  222. perm := int32(v1.SecretVolumeSourceDefaultMode)
  223. obj.DefaultMode = &perm
  224. }
  225. }
  226. func SetDefaults_ConfigMapVolumeSource(obj *v1.ConfigMapVolumeSource) {
  227. if obj.DefaultMode == nil {
  228. perm := int32(v1.ConfigMapVolumeSourceDefaultMode)
  229. obj.DefaultMode = &perm
  230. }
  231. }
  232. func SetDefaults_DownwardAPIVolumeSource(obj *v1.DownwardAPIVolumeSource) {
  233. if obj.DefaultMode == nil {
  234. perm := int32(v1.DownwardAPIVolumeSourceDefaultMode)
  235. obj.DefaultMode = &perm
  236. }
  237. }
  238. func SetDefaults_Secret(obj *v1.Secret) {
  239. if obj.Type == "" {
  240. obj.Type = v1.SecretTypeOpaque
  241. }
  242. }
  243. func SetDefaults_ProjectedVolumeSource(obj *v1.ProjectedVolumeSource) {
  244. if obj.DefaultMode == nil {
  245. perm := int32(v1.ProjectedVolumeSourceDefaultMode)
  246. obj.DefaultMode = &perm
  247. }
  248. }
  249. func SetDefaults_ServiceAccountTokenProjection(obj *v1.ServiceAccountTokenProjection) {
  250. hour := int64(time.Hour.Seconds())
  251. if obj.ExpirationSeconds == nil {
  252. obj.ExpirationSeconds = &hour
  253. }
  254. }
  255. func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) {
  256. if obj.Status.Phase == "" {
  257. obj.Status.Phase = v1.VolumePending
  258. }
  259. if obj.Spec.PersistentVolumeReclaimPolicy == "" {
  260. obj.Spec.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimRetain
  261. }
  262. if obj.Spec.VolumeMode == nil {
  263. obj.Spec.VolumeMode = new(v1.PersistentVolumeMode)
  264. *obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem
  265. }
  266. }
  267. func SetDefaults_PersistentVolumeClaim(obj *v1.PersistentVolumeClaim) {
  268. if obj.Status.Phase == "" {
  269. obj.Status.Phase = v1.ClaimPending
  270. }
  271. if obj.Spec.VolumeMode == nil {
  272. obj.Spec.VolumeMode = new(v1.PersistentVolumeMode)
  273. *obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem
  274. }
  275. }
  276. func SetDefaults_ISCSIVolumeSource(obj *v1.ISCSIVolumeSource) {
  277. if obj.ISCSIInterface == "" {
  278. obj.ISCSIInterface = "default"
  279. }
  280. }
  281. func SetDefaults_ISCSIPersistentVolumeSource(obj *v1.ISCSIPersistentVolumeSource) {
  282. if obj.ISCSIInterface == "" {
  283. obj.ISCSIInterface = "default"
  284. }
  285. }
  286. func SetDefaults_AzureDiskVolumeSource(obj *v1.AzureDiskVolumeSource) {
  287. if obj.CachingMode == nil {
  288. obj.CachingMode = new(v1.AzureDataDiskCachingMode)
  289. *obj.CachingMode = v1.AzureDataDiskCachingReadWrite
  290. }
  291. if obj.Kind == nil {
  292. obj.Kind = new(v1.AzureDataDiskKind)
  293. *obj.Kind = v1.AzureSharedBlobDisk
  294. }
  295. if obj.FSType == nil {
  296. obj.FSType = new(string)
  297. *obj.FSType = "ext4"
  298. }
  299. if obj.ReadOnly == nil {
  300. obj.ReadOnly = new(bool)
  301. *obj.ReadOnly = false
  302. }
  303. }
  304. func SetDefaults_Endpoints(obj *v1.Endpoints) {
  305. for i := range obj.Subsets {
  306. ss := &obj.Subsets[i]
  307. for i := range ss.Ports {
  308. ep := &ss.Ports[i]
  309. if ep.Protocol == "" {
  310. ep.Protocol = v1.ProtocolTCP
  311. }
  312. }
  313. }
  314. }
  315. func SetDefaults_HTTPGetAction(obj *v1.HTTPGetAction) {
  316. if obj.Path == "" {
  317. obj.Path = "/"
  318. }
  319. if obj.Scheme == "" {
  320. obj.Scheme = v1.URISchemeHTTP
  321. }
  322. }
  323. func SetDefaults_NamespaceStatus(obj *v1.NamespaceStatus) {
  324. if obj.Phase == "" {
  325. obj.Phase = v1.NamespaceActive
  326. }
  327. }
  328. func SetDefaults_NodeStatus(obj *v1.NodeStatus) {
  329. if obj.Allocatable == nil && obj.Capacity != nil {
  330. obj.Allocatable = make(v1.ResourceList, len(obj.Capacity))
  331. for key, value := range obj.Capacity {
  332. obj.Allocatable[key] = value.DeepCopy()
  333. }
  334. obj.Allocatable = obj.Capacity
  335. }
  336. }
  337. func SetDefaults_ObjectFieldSelector(obj *v1.ObjectFieldSelector) {
  338. if obj.APIVersion == "" {
  339. obj.APIVersion = "v1"
  340. }
  341. }
  342. func SetDefaults_LimitRangeItem(obj *v1.LimitRangeItem) {
  343. // for container limits, we apply default values
  344. if obj.Type == v1.LimitTypeContainer {
  345. if obj.Default == nil {
  346. obj.Default = make(v1.ResourceList)
  347. }
  348. if obj.DefaultRequest == nil {
  349. obj.DefaultRequest = make(v1.ResourceList)
  350. }
  351. // If a default limit is unspecified, but the max is specified, default the limit to the max
  352. for key, value := range obj.Max {
  353. if _, exists := obj.Default[key]; !exists {
  354. obj.Default[key] = value.DeepCopy()
  355. }
  356. }
  357. // If a default limit is specified, but the default request is not, default request to limit
  358. for key, value := range obj.Default {
  359. if _, exists := obj.DefaultRequest[key]; !exists {
  360. obj.DefaultRequest[key] = value.DeepCopy()
  361. }
  362. }
  363. // If a default request is not specified, but the min is provided, default request to the min
  364. for key, value := range obj.Min {
  365. if _, exists := obj.DefaultRequest[key]; !exists {
  366. obj.DefaultRequest[key] = value.DeepCopy()
  367. }
  368. }
  369. }
  370. }
  371. func SetDefaults_ConfigMap(obj *v1.ConfigMap) {
  372. if obj.Data == nil {
  373. obj.Data = make(map[string]string)
  374. }
  375. }
  376. // With host networking default all container ports to host ports.
  377. func defaultHostNetworkPorts(containers *[]v1.Container) {
  378. for i := range *containers {
  379. for j := range (*containers)[i].Ports {
  380. if (*containers)[i].Ports[j].HostPort == 0 {
  381. (*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
  382. }
  383. }
  384. }
  385. }
  386. func SetDefaults_RBDVolumeSource(obj *v1.RBDVolumeSource) {
  387. if obj.RBDPool == "" {
  388. obj.RBDPool = "rbd"
  389. }
  390. if obj.RadosUser == "" {
  391. obj.RadosUser = "admin"
  392. }
  393. if obj.Keyring == "" {
  394. obj.Keyring = "/etc/ceph/keyring"
  395. }
  396. }
  397. func SetDefaults_RBDPersistentVolumeSource(obj *v1.RBDPersistentVolumeSource) {
  398. if obj.RBDPool == "" {
  399. obj.RBDPool = "rbd"
  400. }
  401. if obj.RadosUser == "" {
  402. obj.RadosUser = "admin"
  403. }
  404. if obj.Keyring == "" {
  405. obj.Keyring = "/etc/ceph/keyring"
  406. }
  407. }
  408. func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
  409. if obj.StorageMode == "" {
  410. obj.StorageMode = "ThinProvisioned"
  411. }
  412. if obj.FSType == "" {
  413. obj.FSType = "xfs"
  414. }
  415. }
  416. func SetDefaults_ScaleIOPersistentVolumeSource(obj *v1.ScaleIOPersistentVolumeSource) {
  417. if obj.StorageMode == "" {
  418. obj.StorageMode = "ThinProvisioned"
  419. }
  420. if obj.FSType == "" {
  421. obj.FSType = "xfs"
  422. }
  423. }
  424. func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) {
  425. typeVol := v1.HostPathUnset
  426. if obj.Type == nil {
  427. obj.Type = &typeVol
  428. }
  429. }