123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- /*
- 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 pod
- import (
- "strings"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- utilfeature "k8s.io/apiserver/pkg/util/feature"
- api "k8s.io/kubernetes/pkg/apis/core"
- "k8s.io/kubernetes/pkg/features"
- "k8s.io/kubernetes/pkg/security/apparmor"
- )
- // ContainerVisitor is called with each container spec, and returns true
- // if visiting should continue.
- type ContainerVisitor func(container *api.Container) (shouldContinue bool)
- // VisitContainers invokes the visitor function with a pointer to the container
- // spec of every container in the given pod spec. If visitor returns false,
- // visiting is short-circuited. VisitContainers returns true if visiting completes,
- // false if visiting was short-circuited.
- func VisitContainers(podSpec *api.PodSpec, visitor ContainerVisitor) bool {
- for i := range podSpec.InitContainers {
- if !visitor(&podSpec.InitContainers[i]) {
- return false
- }
- }
- for i := range podSpec.Containers {
- if !visitor(&podSpec.Containers[i]) {
- return false
- }
- }
- if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) {
- for i := range podSpec.EphemeralContainers {
- if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon)) {
- return false
- }
- }
- }
- return true
- }
- // Visitor is called with each object name, and returns true if visiting should continue
- type Visitor func(name string) (shouldContinue bool)
- // VisitPodSecretNames invokes the visitor function with the name of every secret
- // referenced by the pod spec. If visitor returns false, visiting is short-circuited.
- // Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
- // Returns true if visiting completed, false if visiting was short-circuited.
- func VisitPodSecretNames(pod *api.Pod, visitor Visitor) bool {
- for _, reference := range pod.Spec.ImagePullSecrets {
- if !visitor(reference.Name) {
- return false
- }
- }
- VisitContainers(&pod.Spec, func(c *api.Container) bool {
- return visitContainerSecretNames(c, visitor)
- })
- var source *api.VolumeSource
- for i := range pod.Spec.Volumes {
- source = &pod.Spec.Volumes[i].VolumeSource
- switch {
- case source.AzureFile != nil:
- if len(source.AzureFile.SecretName) > 0 && !visitor(source.AzureFile.SecretName) {
- return false
- }
- case source.CephFS != nil:
- if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) {
- return false
- }
- case source.Cinder != nil:
- if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) {
- return false
- }
- case source.FlexVolume != nil:
- if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) {
- return false
- }
- case source.Projected != nil:
- for j := range source.Projected.Sources {
- if source.Projected.Sources[j].Secret != nil {
- if !visitor(source.Projected.Sources[j].Secret.Name) {
- return false
- }
- }
- }
- case source.RBD != nil:
- if source.RBD.SecretRef != nil && !visitor(source.RBD.SecretRef.Name) {
- return false
- }
- case source.Secret != nil:
- if !visitor(source.Secret.SecretName) {
- return false
- }
- case source.ScaleIO != nil:
- if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
- return false
- }
- case source.ISCSI != nil:
- if source.ISCSI.SecretRef != nil && !visitor(source.ISCSI.SecretRef.Name) {
- return false
- }
- case source.StorageOS != nil:
- if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Name) {
- return false
- }
- case source.CSI != nil:
- if source.CSI.NodePublishSecretRef != nil && !visitor(source.CSI.NodePublishSecretRef.Name) {
- return false
- }
- }
- }
- return true
- }
- func visitContainerSecretNames(container *api.Container, visitor Visitor) bool {
- for _, env := range container.EnvFrom {
- if env.SecretRef != nil {
- if !visitor(env.SecretRef.Name) {
- return false
- }
- }
- }
- for _, envVar := range container.Env {
- if envVar.ValueFrom != nil && envVar.ValueFrom.SecretKeyRef != nil {
- if !visitor(envVar.ValueFrom.SecretKeyRef.Name) {
- return false
- }
- }
- }
- return true
- }
- // VisitPodConfigmapNames invokes the visitor function with the name of every configmap
- // referenced by the pod spec. If visitor returns false, visiting is short-circuited.
- // Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
- // Returns true if visiting completed, false if visiting was short-circuited.
- func VisitPodConfigmapNames(pod *api.Pod, visitor Visitor) bool {
- VisitContainers(&pod.Spec, func(c *api.Container) bool {
- return visitContainerConfigmapNames(c, visitor)
- })
- var source *api.VolumeSource
- for i := range pod.Spec.Volumes {
- source = &pod.Spec.Volumes[i].VolumeSource
- switch {
- case source.Projected != nil:
- for j := range source.Projected.Sources {
- if source.Projected.Sources[j].ConfigMap != nil {
- if !visitor(source.Projected.Sources[j].ConfigMap.Name) {
- return false
- }
- }
- }
- case source.ConfigMap != nil:
- if !visitor(source.ConfigMap.Name) {
- return false
- }
- }
- }
- return true
- }
- func visitContainerConfigmapNames(container *api.Container, visitor Visitor) bool {
- for _, env := range container.EnvFrom {
- if env.ConfigMapRef != nil {
- if !visitor(env.ConfigMapRef.Name) {
- return false
- }
- }
- }
- for _, envVar := range container.Env {
- if envVar.ValueFrom != nil && envVar.ValueFrom.ConfigMapKeyRef != nil {
- if !visitor(envVar.ValueFrom.ConfigMapKeyRef.Name) {
- return false
- }
- }
- }
- return true
- }
- // IsPodReady returns true if a pod is ready; false otherwise.
- func IsPodReady(pod *api.Pod) bool {
- return IsPodReadyConditionTrue(pod.Status)
- }
- // IsPodReadyConditionTrue returns true if a pod is ready; false otherwise.
- func IsPodReadyConditionTrue(status api.PodStatus) bool {
- condition := GetPodReadyCondition(status)
- return condition != nil && condition.Status == api.ConditionTrue
- }
- // GetPodReadyCondition extracts the pod ready condition from the given status and returns that.
- // Returns nil if the condition is not present.
- func GetPodReadyCondition(status api.PodStatus) *api.PodCondition {
- _, condition := GetPodCondition(&status, api.PodReady)
- return condition
- }
- // GetPodCondition extracts the provided condition from the given status and returns that.
- // Returns nil and -1 if the condition is not present, and the index of the located condition.
- func GetPodCondition(status *api.PodStatus, conditionType api.PodConditionType) (int, *api.PodCondition) {
- if status == nil {
- return -1, nil
- }
- for i := range status.Conditions {
- if status.Conditions[i].Type == conditionType {
- return i, &status.Conditions[i]
- }
- }
- return -1, nil
- }
- // UpdatePodCondition updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
- // status has changed.
- // Returns true if pod condition has changed or has been added.
- func UpdatePodCondition(status *api.PodStatus, condition *api.PodCondition) bool {
- condition.LastTransitionTime = metav1.Now()
- // Try to find this pod condition.
- conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
- if oldCondition == nil {
- // We are adding new pod condition.
- status.Conditions = append(status.Conditions, *condition)
- return true
- }
- // We are updating an existing condition, so we need to check if it has changed.
- if condition.Status == oldCondition.Status {
- condition.LastTransitionTime = oldCondition.LastTransitionTime
- }
- isEqual := condition.Status == oldCondition.Status &&
- condition.Reason == oldCondition.Reason &&
- condition.Message == oldCondition.Message &&
- condition.LastProbeTime.Equal(&oldCondition.LastProbeTime) &&
- condition.LastTransitionTime.Equal(&oldCondition.LastTransitionTime)
- status.Conditions[conditionIndex] = *condition
- // Return true if one of the fields have changed.
- return !isEqual
- }
- // DropDisabledTemplateFields removes disabled fields from the pod template metadata and spec.
- // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a PodTemplateSpec
- func DropDisabledTemplateFields(podTemplate, oldPodTemplate *api.PodTemplateSpec) {
- var (
- podSpec *api.PodSpec
- podAnnotations map[string]string
- oldPodSpec *api.PodSpec
- oldPodAnnotations map[string]string
- )
- if podTemplate != nil {
- podSpec = &podTemplate.Spec
- podAnnotations = podTemplate.Annotations
- }
- if oldPodTemplate != nil {
- oldPodSpec = &oldPodTemplate.Spec
- oldPodAnnotations = oldPodTemplate.Annotations
- }
- dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
- }
- // DropDisabledPodFields removes disabled fields from the pod metadata and spec.
- // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a Pod
- func DropDisabledPodFields(pod, oldPod *api.Pod) {
- var (
- podSpec *api.PodSpec
- podAnnotations map[string]string
- oldPodSpec *api.PodSpec
- oldPodAnnotations map[string]string
- podStatus *api.PodStatus
- oldPodStatus *api.PodStatus
- )
- if pod != nil {
- podSpec = &pod.Spec
- podAnnotations = pod.Annotations
- podStatus = &pod.Status
- }
- if oldPod != nil {
- oldPodSpec = &oldPod.Spec
- oldPodAnnotations = oldPod.Annotations
- oldPodStatus = &oldPod.Status
- }
- dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
- dropPodStatusDisabledFields(podStatus, oldPodStatus)
- }
- // dropPodStatusDisabledFields removes disabled fields from the pod status
- func dropPodStatusDisabledFields(podStatus *api.PodStatus, oldPodStatus *api.PodStatus) {
- // trim PodIPs down to only one entry (non dual stack).
- if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) &&
- !multiplePodIPsInUse(oldPodStatus) {
- if len(podStatus.PodIPs) != 0 {
- podStatus.PodIPs = podStatus.PodIPs[0:1]
- }
- }
- }
- // dropDisabledFields removes disabled fields from the pod metadata and spec.
- func dropDisabledFields(
- podSpec *api.PodSpec, podAnnotations map[string]string,
- oldPodSpec *api.PodSpec, oldPodAnnotations map[string]string,
- ) {
- // the new spec must always be non-nil
- if podSpec == nil {
- podSpec = &api.PodSpec{}
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequestProjection) &&
- !tokenRequestProjectionInUse(oldPodSpec) {
- for i := range podSpec.Volumes {
- if podSpec.Volumes[i].Projected != nil {
- for j := range podSpec.Volumes[i].Projected.Sources {
- podSpec.Volumes[i].Projected.Sources[j].ServiceAccountToken = nil
- }
- }
- }
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.AppArmor) && !appArmorInUse(oldPodAnnotations) {
- for k := range podAnnotations {
- if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
- delete(podAnnotations, k)
- }
- }
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) && !sysctlsInUse(oldPodSpec) {
- if podSpec.SecurityContext != nil {
- podSpec.SecurityContext.Sysctls = nil
- }
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) && !emptyDirSizeLimitInUse(oldPodSpec) {
- for i := range podSpec.Volumes {
- if podSpec.Volumes[i].EmptyDir != nil {
- podSpec.Volumes[i].EmptyDir.SizeLimit = nil
- }
- }
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpath) && !subpathInUse(oldPodSpec) {
- // drop subpath from the pod if the feature is disabled and the old spec did not specify subpaths
- VisitContainers(podSpec, func(c *api.Container) bool {
- for i := range c.VolumeMounts {
- c.VolumeMounts[i].SubPath = ""
- }
- return true
- })
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) && !ephemeralContainersInUse(oldPodSpec) {
- podSpec.EphemeralContainers = nil
- }
- if (!utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpath) || !utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpathEnvExpansion)) && !subpathExprInUse(oldPodSpec) {
- // drop subpath env expansion from the pod if either of the subpath features is disabled and the old spec did not specify subpath env expansion
- VisitContainers(podSpec, func(c *api.Container) bool {
- for i := range c.VolumeMounts {
- c.VolumeMounts[i].SubPathExpr = ""
- }
- return true
- })
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.StartupProbe) && !startupProbeInUse(oldPodSpec) {
- // drop startupProbe from all containers if the feature is disabled
- VisitContainers(podSpec, func(c *api.Container) bool {
- c.StartupProbe = nil
- return true
- })
- }
- dropDisabledVolumeDevicesFields(podSpec, oldPodSpec)
- dropDisabledRunAsGroupField(podSpec, oldPodSpec)
- dropDisabledGMSAFields(podSpec, oldPodSpec)
- if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && !runtimeClassInUse(oldPodSpec) {
- // Set RuntimeClassName to nil only if feature is disabled and it is not used
- podSpec.RuntimeClassName = nil
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.PodOverhead) && !overheadInUse(oldPodSpec) {
- // Set Overhead to nil only if the feature is disabled and it is not used
- podSpec.Overhead = nil
- }
- dropDisabledProcMountField(podSpec, oldPodSpec)
- dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec)
- if !utilfeature.DefaultFeatureGate.Enabled(features.NonPreemptingPriority) &&
- !podPriorityInUse(oldPodSpec) {
- // Set to nil pod's PreemptionPolicy fields if the feature is disabled and the old pod
- // does not specify any values for these fields.
- podSpec.PreemptionPolicy = nil
- }
- if !utilfeature.DefaultFeatureGate.Enabled(features.EvenPodsSpread) && !topologySpreadConstraintsInUse(oldPodSpec) {
- // Set TopologySpreadConstraints to nil only if feature is disabled and it is not used
- podSpec.TopologySpreadConstraints = nil
- }
- }
- // dropDisabledRunAsGroupField removes disabled fields from PodSpec related
- // to RunAsGroup
- func dropDisabledRunAsGroupField(podSpec, oldPodSpec *api.PodSpec) {
- if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) && !runAsGroupInUse(oldPodSpec) {
- if podSpec.SecurityContext != nil {
- podSpec.SecurityContext.RunAsGroup = nil
- }
- VisitContainers(podSpec, func(c *api.Container) bool {
- if c.SecurityContext != nil {
- c.SecurityContext.RunAsGroup = nil
- }
- return true
- })
- }
- }
- // dropDisabledGMSAFields removes disabled fields related to Windows GMSA
- // from the given PodSpec.
- func dropDisabledGMSAFields(podSpec, oldPodSpec *api.PodSpec) {
- if utilfeature.DefaultFeatureGate.Enabled(features.WindowsGMSA) ||
- gMSAFieldsInUse(oldPodSpec) {
- return
- }
- if podSpec.SecurityContext != nil {
- dropDisabledGMSAFieldsFromWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions)
- }
- dropDisabledGMSAFieldsFromContainers(podSpec.Containers)
- dropDisabledGMSAFieldsFromContainers(podSpec.InitContainers)
- }
- // dropDisabledGMSAFieldsFromWindowsSecurityOptions removes disabled fields
- // related to Windows GMSA from the given WindowsSecurityContextOptions.
- func dropDisabledGMSAFieldsFromWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) {
- if windowsOptions != nil {
- windowsOptions.GMSACredentialSpecName = nil
- windowsOptions.GMSACredentialSpec = nil
- }
- }
- // dropDisabledGMSAFieldsFromContainers removes disabled fields
- func dropDisabledGMSAFieldsFromContainers(containers []api.Container) {
- for i := range containers {
- if containers[i].SecurityContext != nil {
- dropDisabledGMSAFieldsFromWindowsSecurityOptions(containers[i].SecurityContext.WindowsOptions)
- }
- }
- }
- // dropDisabledProcMountField removes disabled fields from PodSpec related
- // to ProcMount only if it is not already used by the old spec
- func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
- if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) && !procMountInUse(oldPodSpec) {
- defaultProcMount := api.DefaultProcMount
- VisitContainers(podSpec, func(c *api.Container) bool {
- if c.SecurityContext != nil && c.SecurityContext.ProcMount != nil {
- // The ProcMount field was improperly forced to non-nil in 1.12.
- // If the feature is disabled, and the existing object is not using any non-default values, and the ProcMount field is present in the incoming object, force to the default value.
- // Note: we cannot force the field to nil when the feature is disabled because it causes a diff against previously persisted data.
- c.SecurityContext.ProcMount = &defaultProcMount
- }
- return true
- })
- }
- }
- // dropDisabledVolumeDevicesFields removes disabled fields from []VolumeDevice if it has not been already populated.
- // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice
- func dropDisabledVolumeDevicesFields(podSpec, oldPodSpec *api.PodSpec) {
- if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeDevicesInUse(oldPodSpec) {
- VisitContainers(podSpec, func(c *api.Container) bool {
- c.VolumeDevices = nil
- return true
- })
- }
- }
- // dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource.
- // This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
- func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
- if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) && !csiInUse(oldPodSpec) {
- for i := range podSpec.Volumes {
- podSpec.Volumes[i].CSI = nil
- }
- }
- }
- func ephemeralContainersInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- return len(podSpec.EphemeralContainers) > 0
- }
- // subpathInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPath feature
- func subpathInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- var inUse bool
- VisitContainers(podSpec, func(c *api.Container) bool {
- for i := range c.VolumeMounts {
- if len(c.VolumeMounts[i].SubPath) > 0 {
- inUse = true
- return false
- }
- }
- return true
- })
- return inUse
- }
- // runtimeClassInUse returns true if the pod spec is non-nil and has a RuntimeClassName set
- func runtimeClassInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- if podSpec.RuntimeClassName != nil {
- return true
- }
- return false
- }
- // overheadInUse returns true if the pod spec is non-nil and has Overhead set
- func overheadInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- if podSpec.Overhead != nil {
- return true
- }
- return false
- }
- // topologySpreadConstraintsInUse returns true if the pod spec is non-nil and has a TopologySpreadConstraints slice
- func topologySpreadConstraintsInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- return len(podSpec.TopologySpreadConstraints) > 0
- }
- // procMountInUse returns true if the pod spec is non-nil and has a SecurityContext's ProcMount field set to a non-default value
- func procMountInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- var inUse bool
- VisitContainers(podSpec, func(c *api.Container) bool {
- if c.SecurityContext == nil || c.SecurityContext.ProcMount == nil {
- return true
- }
- if *c.SecurityContext.ProcMount != api.DefaultProcMount {
- inUse = true
- return false
- }
- return true
- })
- return inUse
- }
- // appArmorInUse returns true if the pod has apparmor related information
- func appArmorInUse(podAnnotations map[string]string) bool {
- for k := range podAnnotations {
- if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
- return true
- }
- }
- return false
- }
- func tokenRequestProjectionInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- for _, v := range podSpec.Volumes {
- if v.Projected == nil {
- continue
- }
- for _, s := range v.Projected.Sources {
- if s.ServiceAccountToken != nil {
- return true
- }
- }
- }
- return false
- }
- // podPriorityInUse returns true if the pod spec is non-nil and has Priority or PriorityClassName set.
- func podPriorityInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- if podSpec.Priority != nil || podSpec.PriorityClassName != "" {
- return true
- }
- return false
- }
- func sysctlsInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- if podSpec.SecurityContext != nil && podSpec.SecurityContext.Sysctls != nil {
- return true
- }
- return false
- }
- // emptyDirSizeLimitInUse returns true if any pod's EmptyDir volumes use SizeLimit.
- func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- for i := range podSpec.Volumes {
- if podSpec.Volumes[i].EmptyDir != nil {
- if podSpec.Volumes[i].EmptyDir.SizeLimit != nil {
- return true
- }
- }
- }
- return false
- }
- // volumeDevicesInUse returns true if the pod spec is non-nil and has VolumeDevices set.
- func volumeDevicesInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- var inUse bool
- VisitContainers(podSpec, func(c *api.Container) bool {
- if c.VolumeDevices != nil {
- inUse = true
- return false
- }
- return true
- })
- return inUse
- }
- // runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set
- func runAsGroupInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- if podSpec.SecurityContext != nil && podSpec.SecurityContext.RunAsGroup != nil {
- return true
- }
- var inUse bool
- VisitContainers(podSpec, func(c *api.Container) bool {
- if c.SecurityContext != nil && c.SecurityContext.RunAsGroup != nil {
- inUse = true
- return false
- }
- return true
- })
- return inUse
- }
- // gMSAFieldsInUse returns true if the pod spec is non-nil and has one of any
- // SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
- func gMSAFieldsInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- if podSpec.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions) {
- return true
- }
- return gMSAFieldsInUseInAnyContainer(podSpec.Containers) ||
- gMSAFieldsInUseInAnyContainer(podSpec.InitContainers)
- }
- // gMSAFieldsInUseInWindowsSecurityOptions returns true if the given WindowsSecurityContextOptions is
- // non-nil and one of its GMSACredentialSpecName or GMSACredentialSpec fields is set.
- func gMSAFieldsInUseInWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) bool {
- if windowsOptions == nil {
- return false
- }
- return windowsOptions.GMSACredentialSpecName != nil ||
- windowsOptions.GMSACredentialSpec != nil
- }
- // gMSAFieldsInUseInAnyContainer returns true if any of the given Containers has its
- // SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
- func gMSAFieldsInUseInAnyContainer(containers []api.Container) bool {
- for _, container := range containers {
- if container.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(container.SecurityContext.WindowsOptions) {
- return true
- }
- }
- return false
- }
- // subpathExprInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPathExpr feature
- func subpathExprInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- var inUse bool
- VisitContainers(podSpec, func(c *api.Container) bool {
- for i := range c.VolumeMounts {
- if len(c.VolumeMounts[i].SubPathExpr) > 0 {
- inUse = true
- return false
- }
- }
- return true
- })
- return inUse
- }
- // startupProbeInUse returns true if the pod spec is non-nil and has a container that has a startupProbe defined
- func startupProbeInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- var inUse bool
- VisitContainers(podSpec, func(c *api.Container) bool {
- if c.StartupProbe != nil {
- inUse = true
- return false
- }
- return true
- })
- return inUse
- }
- // csiInUse returns true if any pod's spec include inline CSI volumes.
- func csiInUse(podSpec *api.PodSpec) bool {
- if podSpec == nil {
- return false
- }
- for i := range podSpec.Volumes {
- if podSpec.Volumes[i].CSI != nil {
- return true
- }
- }
- return false
- }
- // podPriorityInUse returns true if status is not nil and number of PodIPs is greater than one
- func multiplePodIPsInUse(podStatus *api.PodStatus) bool {
- if podStatus == nil {
- return false
- }
- if len(podStatus.PodIPs) > 1 {
- return true
- }
- return false
- }
|