1/* 2Copyright 2014 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 types 18 19import ( 20 "fmt" 21 22 v1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/kubernetes/pkg/apis/scheduling" 25) 26 27// Annotation keys for annotations used in this package. 28const ( 29 ConfigSourceAnnotationKey = "kubernetes.io/config.source" 30 ConfigMirrorAnnotationKey = v1.MirrorPodAnnotationKey 31 ConfigFirstSeenAnnotationKey = "kubernetes.io/config.seen" 32 ConfigHashAnnotationKey = "kubernetes.io/config.hash" 33) 34 35// PodOperation defines what changes will be made on a pod configuration. 36type PodOperation int 37 38// These constants identify the PodOperations that can be made on a pod configuration. 39const ( 40 // SET is the current pod configuration. 41 SET PodOperation = iota 42 // ADD signifies pods that are new to this source. 43 ADD 44 // DELETE signifies pods that are gracefully deleted from this source. 45 DELETE 46 // REMOVE signifies pods that have been removed from this source. 47 REMOVE 48 // UPDATE signifies pods have been updated in this source. 49 UPDATE 50 // RECONCILE signifies pods that have unexpected status in this source, 51 // kubelet should reconcile status with this source. 52 RECONCILE 53) 54 55// These constants identify the sources of pods. 56const ( 57 // Filesource idenitified updates from a file. 58 FileSource = "file" 59 // HTTPSource identifies updates from querying a web page. 60 HTTPSource = "http" 61 // ApiserverSource identifies updates from Kubernetes API Server. 62 ApiserverSource = "api" 63 // AllSource identifies updates from all sources. 64 AllSource = "*" 65) 66 67// NamespaceDefault is a string representing the default namespace. 68const NamespaceDefault = metav1.NamespaceDefault 69 70// PodUpdate defines an operation sent on the channel. You can add or remove single services by 71// sending an array of size one and Op == ADD|REMOVE (with REMOVE, only the ID is required). 72// For setting the state of the system to a given state for this source configuration, set 73// Pods as desired and Op to SET, which will reset the system state to that specified in this 74// operation for this source channel. To remove all pods, set Pods to empty object and Op to SET. 75// 76// Additionally, Pods should never be nil - it should always point to an empty slice. While 77// functionally similar, this helps our unit tests properly check that the correct PodUpdates 78// are generated. 79type PodUpdate struct { 80 Pods []*v1.Pod 81 Op PodOperation 82 Source string 83} 84 85// GetValidatedSources gets all validated sources from the specified sources. 86func GetValidatedSources(sources []string) ([]string, error) { 87 validated := make([]string, 0, len(sources)) 88 for _, source := range sources { 89 switch source { 90 case AllSource: 91 return []string{FileSource, HTTPSource, ApiserverSource}, nil 92 case FileSource, HTTPSource, ApiserverSource: 93 validated = append(validated, source) 94 case "": 95 // Skip 96 default: 97 return []string{}, fmt.Errorf("unknown pod source %q", source) 98 } 99 } 100 return validated, nil 101} 102 103// GetPodSource returns the source of the pod based on the annotation. 104func GetPodSource(pod *v1.Pod) (string, error) { 105 if pod.Annotations != nil { 106 if source, ok := pod.Annotations[ConfigSourceAnnotationKey]; ok { 107 return source, nil 108 } 109 } 110 return "", fmt.Errorf("cannot get source of pod %q", pod.UID) 111} 112 113// SyncPodType classifies pod updates, eg: create, update. 114type SyncPodType int 115 116const ( 117 // SyncPodSync is when the pod is synced to ensure desired state 118 SyncPodSync SyncPodType = iota 119 // SyncPodUpdate is when the pod is updated from source 120 SyncPodUpdate 121 // SyncPodCreate is when the pod is created from source 122 SyncPodCreate 123 // SyncPodKill is when the pod should have no running containers. A pod stopped in this way could be 124 // restarted in the future due config changes. 125 SyncPodKill 126) 127 128func (sp SyncPodType) String() string { 129 switch sp { 130 case SyncPodCreate: 131 return "create" 132 case SyncPodUpdate: 133 return "update" 134 case SyncPodSync: 135 return "sync" 136 case SyncPodKill: 137 return "kill" 138 default: 139 return "unknown" 140 } 141} 142 143// IsMirrorPod returns true if the passed Pod is a Mirror Pod. 144func IsMirrorPod(pod *v1.Pod) bool { 145 _, ok := pod.Annotations[ConfigMirrorAnnotationKey] 146 return ok 147} 148 149// IsStaticPod returns true if the pod is a static pod. 150func IsStaticPod(pod *v1.Pod) bool { 151 source, err := GetPodSource(pod) 152 return err == nil && source != ApiserverSource 153} 154 155// IsCriticalPod returns true if pod's priority is greater than or equal to SystemCriticalPriority. 156func IsCriticalPod(pod *v1.Pod) bool { 157 if IsStaticPod(pod) { 158 return true 159 } 160 if IsMirrorPod(pod) { 161 return true 162 } 163 if pod.Spec.Priority != nil && IsCriticalPodBasedOnPriority(*pod.Spec.Priority) { 164 return true 165 } 166 return false 167} 168 169// Preemptable returns true if preemptor pod can preempt preemptee pod 170// if preemptee is not critical or if preemptor's priority is greater than preemptee's priority 171func Preemptable(preemptor, preemptee *v1.Pod) bool { 172 if IsCriticalPod(preemptor) && !IsCriticalPod(preemptee) { 173 return true 174 } 175 if (preemptor != nil && preemptor.Spec.Priority != nil) && 176 (preemptee != nil && preemptee.Spec.Priority != nil) { 177 return *(preemptor.Spec.Priority) > *(preemptee.Spec.Priority) 178 } 179 180 return false 181} 182 183// IsCriticalPodBasedOnPriority checks if the given pod is a critical pod based on priority resolved from pod Spec. 184func IsCriticalPodBasedOnPriority(priority int32) bool { 185 return priority >= scheduling.SystemCriticalPriority 186} 187 188// IsNodeCriticalPod checks if the given pod is a system-node-critical 189func IsNodeCriticalPod(pod *v1.Pod) bool { 190 return IsCriticalPod(pod) && (pod.Spec.PriorityClassName == scheduling.SystemNodeCritical) 191} 192