aboutsummaryrefslogtreecommitdiff
path: root/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
committerMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
commita031b83a09a8628435317a03f199cdc18b78262f (patch)
treebc017a96769ce6de33745b8b0b1304ccf38e9df0 /vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go
parent2b74391cd5281f6fdf391ff8ad50fd1490f6bf89 (diff)
downloadpodman-a031b83a09a8628435317a03f199cdc18b78262f.tar.gz
podman-a031b83a09a8628435317a03f199cdc18b78262f.tar.bz2
podman-a031b83a09a8628435317a03f199cdc18b78262f.zip
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go')
-rw-r--r--vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go358
1 files changed, 358 insertions, 0 deletions
diff --git a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go
new file mode 100644
index 000000000..aa7b0a4a8
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go
@@ -0,0 +1,358 @@
+/*
+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 (
+ "encoding/json"
+ "fmt"
+ "time"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/util/intstr"
+ "k8s.io/kubernetes/pkg/api/v1"
+)
+
+// FindPort locates the container port for the given pod and portName. If the
+// targetPort is a number, use that. If the targetPort is a string, look that
+// string up in all named ports in all containers in the target pod. If no
+// match is found, fail.
+func FindPort(pod *v1.Pod, svcPort *v1.ServicePort) (int, error) {
+ portName := svcPort.TargetPort
+ switch portName.Type {
+ case intstr.String:
+ name := portName.StrVal
+ for _, container := range pod.Spec.Containers {
+ for _, port := range container.Ports {
+ if port.Name == name && port.Protocol == svcPort.Protocol {
+ return int(port.ContainerPort), nil
+ }
+ }
+ }
+ case intstr.Int:
+ return portName.IntValue(), nil
+ }
+
+ return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
+}
+
+// TODO: remove this function when init containers becomes a stable feature
+func SetInitContainersAndStatuses(pod *v1.Pod) error {
+ var initContainersAnnotation string
+ initContainersAnnotation = pod.Annotations[v1.PodInitContainersAnnotationKey]
+ initContainersAnnotation = pod.Annotations[v1.PodInitContainersBetaAnnotationKey]
+ if len(initContainersAnnotation) > 0 {
+ var values []v1.Container
+ if err := json.Unmarshal([]byte(initContainersAnnotation), &values); err != nil {
+ return err
+ }
+ pod.Spec.InitContainers = values
+ }
+
+ var initContainerStatusesAnnotation string
+ initContainerStatusesAnnotation = pod.Annotations[v1.PodInitContainerStatusesAnnotationKey]
+ initContainerStatusesAnnotation = pod.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey]
+ if len(initContainerStatusesAnnotation) > 0 {
+ var values []v1.ContainerStatus
+ if err := json.Unmarshal([]byte(initContainerStatusesAnnotation), &values); err != nil {
+ return err
+ }
+ pod.Status.InitContainerStatuses = values
+ }
+ return nil
+}
+
+// TODO: remove this function when init containers becomes a stable feature
+func SetInitContainersAnnotations(pod *v1.Pod) error {
+ if len(pod.Spec.InitContainers) > 0 {
+ value, err := json.Marshal(pod.Spec.InitContainers)
+ if err != nil {
+ return err
+ }
+ if pod.Annotations == nil {
+ pod.Annotations = make(map[string]string)
+ }
+ pod.Annotations[v1.PodInitContainersAnnotationKey] = string(value)
+ pod.Annotations[v1.PodInitContainersBetaAnnotationKey] = string(value)
+ }
+ return nil
+}
+
+// TODO: remove this function when init containers becomes a stable feature
+func SetInitContainersStatusesAnnotations(pod *v1.Pod) error {
+ if len(pod.Status.InitContainerStatuses) > 0 {
+ value, err := json.Marshal(pod.Status.InitContainerStatuses)
+ if err != nil {
+ return err
+ }
+ if pod.Annotations == nil {
+ pod.Annotations = make(map[string]string)
+ }
+ pod.Annotations[v1.PodInitContainerStatusesAnnotationKey] = string(value)
+ pod.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey] = string(value)
+ } else {
+ delete(pod.Annotations, v1.PodInitContainerStatusesAnnotationKey)
+ delete(pod.Annotations, v1.PodInitContainerStatusesBetaAnnotationKey)
+ }
+ return nil
+}
+
+// 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 *v1.Pod, visitor Visitor) bool {
+ for _, reference := range pod.Spec.ImagePullSecrets {
+ if !visitor(reference.Name) {
+ return false
+ }
+ }
+ for i := range pod.Spec.InitContainers {
+ if !visitContainerSecretNames(&pod.Spec.InitContainers[i], visitor) {
+ return false
+ }
+ }
+ for i := range pod.Spec.Containers {
+ if !visitContainerSecretNames(&pod.Spec.Containers[i], visitor) {
+ return false
+ }
+ }
+ var source *v1.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.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
+ }
+ }
+ }
+ return true
+}
+
+func visitContainerSecretNames(container *v1.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 *v1.Pod, visitor Visitor) bool {
+ for i := range pod.Spec.InitContainers {
+ if !visitContainerConfigmapNames(&pod.Spec.InitContainers[i], visitor) {
+ return false
+ }
+ }
+ for i := range pod.Spec.Containers {
+ if !visitContainerConfigmapNames(&pod.Spec.Containers[i], visitor) {
+ return false
+ }
+ }
+ var source *v1.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 *v1.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
+}
+
+// GetContainerStatus extracts the status of container "name" from "statuses".
+// It also returns if "name" exists.
+func GetContainerStatus(statuses []v1.ContainerStatus, name string) (v1.ContainerStatus, bool) {
+ for i := range statuses {
+ if statuses[i].Name == name {
+ return statuses[i], true
+ }
+ }
+ return v1.ContainerStatus{}, false
+}
+
+// GetExistingContainerStatus extracts the status of container "name" from "statuses",
+// and returns empty status if "name" does not exist.
+func GetExistingContainerStatus(statuses []v1.ContainerStatus, name string) v1.ContainerStatus {
+ for i := range statuses {
+ if statuses[i].Name == name {
+ return statuses[i]
+ }
+ }
+ return v1.ContainerStatus{}
+}
+
+// IsPodAvailable returns true if a pod is available; false otherwise.
+// Precondition for an available pod is that it must be ready. On top
+// of that, there are two cases when a pod can be considered available:
+// 1. minReadySeconds == 0, or
+// 2. LastTransitionTime (is set) + minReadySeconds < current time
+func IsPodAvailable(pod *v1.Pod, minReadySeconds int32, now metav1.Time) bool {
+ if !IsPodReady(pod) {
+ return false
+ }
+
+ c := GetPodReadyCondition(pod.Status)
+ minReadySecondsDuration := time.Duration(minReadySeconds) * time.Second
+ if minReadySeconds == 0 || !c.LastTransitionTime.IsZero() && c.LastTransitionTime.Add(minReadySecondsDuration).Before(now.Time) {
+ return true
+ }
+ return false
+}
+
+// IsPodReady returns true if a pod is ready; false otherwise.
+func IsPodReady(pod *v1.Pod) bool {
+ return IsPodReadyConditionTrue(pod.Status)
+}
+
+// IsPodReady retruns true if a pod is ready; false otherwise.
+func IsPodReadyConditionTrue(status v1.PodStatus) bool {
+ condition := GetPodReadyCondition(status)
+ return condition != nil && condition.Status == v1.ConditionTrue
+}
+
+// Extracts the pod ready condition from the given status and returns that.
+// Returns nil if the condition is not present.
+func GetPodReadyCondition(status v1.PodStatus) *v1.PodCondition {
+ _, condition := GetPodCondition(&status, v1.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 *v1.PodStatus, conditionType v1.PodConditionType) (int, *v1.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
+}
+
+// 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 *v1.PodStatus, condition *v1.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
+ } else {
+ // 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
+ }
+}