labels.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. Copyright 2016 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 kuberuntime
  14. import (
  15. "encoding/json"
  16. "strconv"
  17. "k8s.io/api/core/v1"
  18. kubetypes "k8s.io/apimachinery/pkg/types"
  19. "k8s.io/klog"
  20. kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
  21. "k8s.io/kubernetes/pkg/kubelet/types"
  22. "k8s.io/kubernetes/pkg/kubelet/util/format"
  23. )
  24. const (
  25. // TODO: change those label names to follow kubernetes's format
  26. podDeletionGracePeriodLabel = "io.kubernetes.pod.deletionGracePeriod"
  27. podTerminationGracePeriodLabel = "io.kubernetes.pod.terminationGracePeriod"
  28. containerHashLabel = "io.kubernetes.container.hash"
  29. containerRestartCountLabel = "io.kubernetes.container.restartCount"
  30. containerTerminationMessagePathLabel = "io.kubernetes.container.terminationMessagePath"
  31. containerTerminationMessagePolicyLabel = "io.kubernetes.container.terminationMessagePolicy"
  32. containerPreStopHandlerLabel = "io.kubernetes.container.preStopHandler"
  33. containerPortsLabel = "io.kubernetes.container.ports"
  34. )
  35. type labeledPodSandboxInfo struct {
  36. // Labels from v1.Pod
  37. Labels map[string]string
  38. PodName string
  39. PodNamespace string
  40. PodUID kubetypes.UID
  41. }
  42. type annotatedPodSandboxInfo struct {
  43. // Annotations from v1.Pod
  44. Annotations map[string]string
  45. }
  46. type labeledContainerInfo struct {
  47. ContainerName string
  48. PodName string
  49. PodNamespace string
  50. PodUID kubetypes.UID
  51. }
  52. type annotatedContainerInfo struct {
  53. Hash uint64
  54. RestartCount int
  55. PodDeletionGracePeriod *int64
  56. PodTerminationGracePeriod *int64
  57. TerminationMessagePath string
  58. TerminationMessagePolicy v1.TerminationMessagePolicy
  59. PreStopHandler *v1.Handler
  60. ContainerPorts []v1.ContainerPort
  61. }
  62. // newPodLabels creates pod labels from v1.Pod.
  63. func newPodLabels(pod *v1.Pod) map[string]string {
  64. labels := map[string]string{}
  65. // Get labels from v1.Pod
  66. for k, v := range pod.Labels {
  67. labels[k] = v
  68. }
  69. labels[types.KubernetesPodNameLabel] = pod.Name
  70. labels[types.KubernetesPodNamespaceLabel] = pod.Namespace
  71. labels[types.KubernetesPodUIDLabel] = string(pod.UID)
  72. return labels
  73. }
  74. // newPodAnnotations creates pod annotations from v1.Pod.
  75. func newPodAnnotations(pod *v1.Pod) map[string]string {
  76. return pod.Annotations
  77. }
  78. // newContainerLabels creates container labels from v1.Container and v1.Pod.
  79. func newContainerLabels(container *v1.Container, pod *v1.Pod) map[string]string {
  80. labels := map[string]string{}
  81. labels[types.KubernetesPodNameLabel] = pod.Name
  82. labels[types.KubernetesPodNamespaceLabel] = pod.Namespace
  83. labels[types.KubernetesPodUIDLabel] = string(pod.UID)
  84. labels[types.KubernetesContainerNameLabel] = container.Name
  85. return labels
  86. }
  87. // newContainerAnnotations creates container annotations from v1.Container and v1.Pod.
  88. func newContainerAnnotations(container *v1.Container, pod *v1.Pod, restartCount int, opts *kubecontainer.RunContainerOptions) map[string]string {
  89. annotations := map[string]string{}
  90. // Kubelet always overrides device plugin annotations if they are conflicting
  91. for _, a := range opts.Annotations {
  92. annotations[a.Name] = a.Value
  93. }
  94. annotations[containerHashLabel] = strconv.FormatUint(kubecontainer.HashContainer(container), 16)
  95. annotations[containerRestartCountLabel] = strconv.Itoa(restartCount)
  96. annotations[containerTerminationMessagePathLabel] = container.TerminationMessagePath
  97. annotations[containerTerminationMessagePolicyLabel] = string(container.TerminationMessagePolicy)
  98. if pod.DeletionGracePeriodSeconds != nil {
  99. annotations[podDeletionGracePeriodLabel] = strconv.FormatInt(*pod.DeletionGracePeriodSeconds, 10)
  100. }
  101. if pod.Spec.TerminationGracePeriodSeconds != nil {
  102. annotations[podTerminationGracePeriodLabel] = strconv.FormatInt(*pod.Spec.TerminationGracePeriodSeconds, 10)
  103. }
  104. if container.Lifecycle != nil && container.Lifecycle.PreStop != nil {
  105. // Using json encoding so that the PreStop handler object is readable after writing as a label
  106. rawPreStop, err := json.Marshal(container.Lifecycle.PreStop)
  107. if err != nil {
  108. klog.Errorf("Unable to marshal lifecycle PreStop handler for container %q of pod %q: %v", container.Name, format.Pod(pod), err)
  109. } else {
  110. annotations[containerPreStopHandlerLabel] = string(rawPreStop)
  111. }
  112. }
  113. if len(container.Ports) > 0 {
  114. rawContainerPorts, err := json.Marshal(container.Ports)
  115. if err != nil {
  116. klog.Errorf("Unable to marshal container ports for container %q for pod %q: %v", container.Name, format.Pod(pod), err)
  117. } else {
  118. annotations[containerPortsLabel] = string(rawContainerPorts)
  119. }
  120. }
  121. return annotations
  122. }
  123. // getPodSandboxInfoFromLabels gets labeledPodSandboxInfo from labels.
  124. func getPodSandboxInfoFromLabels(labels map[string]string) *labeledPodSandboxInfo {
  125. podSandboxInfo := &labeledPodSandboxInfo{
  126. Labels: make(map[string]string),
  127. PodName: getStringValueFromLabel(labels, types.KubernetesPodNameLabel),
  128. PodNamespace: getStringValueFromLabel(labels, types.KubernetesPodNamespaceLabel),
  129. PodUID: kubetypes.UID(getStringValueFromLabel(labels, types.KubernetesPodUIDLabel)),
  130. }
  131. // Remain only labels from v1.Pod
  132. for k, v := range labels {
  133. if k != types.KubernetesPodNameLabel && k != types.KubernetesPodNamespaceLabel && k != types.KubernetesPodUIDLabel {
  134. podSandboxInfo.Labels[k] = v
  135. }
  136. }
  137. return podSandboxInfo
  138. }
  139. // getPodSandboxInfoFromAnnotations gets annotatedPodSandboxInfo from annotations.
  140. func getPodSandboxInfoFromAnnotations(annotations map[string]string) *annotatedPodSandboxInfo {
  141. return &annotatedPodSandboxInfo{
  142. Annotations: annotations,
  143. }
  144. }
  145. // getContainerInfoFromLabels gets labeledContainerInfo from labels.
  146. func getContainerInfoFromLabels(labels map[string]string) *labeledContainerInfo {
  147. return &labeledContainerInfo{
  148. PodName: getStringValueFromLabel(labels, types.KubernetesPodNameLabel),
  149. PodNamespace: getStringValueFromLabel(labels, types.KubernetesPodNamespaceLabel),
  150. PodUID: kubetypes.UID(getStringValueFromLabel(labels, types.KubernetesPodUIDLabel)),
  151. ContainerName: getStringValueFromLabel(labels, types.KubernetesContainerNameLabel),
  152. }
  153. }
  154. // getContainerInfoFromAnnotations gets annotatedContainerInfo from annotations.
  155. func getContainerInfoFromAnnotations(annotations map[string]string) *annotatedContainerInfo {
  156. var err error
  157. containerInfo := &annotatedContainerInfo{
  158. TerminationMessagePath: getStringValueFromLabel(annotations, containerTerminationMessagePathLabel),
  159. TerminationMessagePolicy: v1.TerminationMessagePolicy(getStringValueFromLabel(annotations, containerTerminationMessagePolicyLabel)),
  160. }
  161. if containerInfo.Hash, err = getUint64ValueFromLabel(annotations, containerHashLabel); err != nil {
  162. klog.Errorf("Unable to get %q from annotations %q: %v", containerHashLabel, annotations, err)
  163. }
  164. if containerInfo.RestartCount, err = getIntValueFromLabel(annotations, containerRestartCountLabel); err != nil {
  165. klog.Errorf("Unable to get %q from annotations %q: %v", containerRestartCountLabel, annotations, err)
  166. }
  167. if containerInfo.PodDeletionGracePeriod, err = getInt64PointerFromLabel(annotations, podDeletionGracePeriodLabel); err != nil {
  168. klog.Errorf("Unable to get %q from annotations %q: %v", podDeletionGracePeriodLabel, annotations, err)
  169. }
  170. if containerInfo.PodTerminationGracePeriod, err = getInt64PointerFromLabel(annotations, podTerminationGracePeriodLabel); err != nil {
  171. klog.Errorf("Unable to get %q from annotations %q: %v", podTerminationGracePeriodLabel, annotations, err)
  172. }
  173. preStopHandler := &v1.Handler{}
  174. if found, err := getJSONObjectFromLabel(annotations, containerPreStopHandlerLabel, preStopHandler); err != nil {
  175. klog.Errorf("Unable to get %q from annotations %q: %v", containerPreStopHandlerLabel, annotations, err)
  176. } else if found {
  177. containerInfo.PreStopHandler = preStopHandler
  178. }
  179. containerPorts := []v1.ContainerPort{}
  180. if found, err := getJSONObjectFromLabel(annotations, containerPortsLabel, &containerPorts); err != nil {
  181. klog.Errorf("Unable to get %q from annotations %q: %v", containerPortsLabel, annotations, err)
  182. } else if found {
  183. containerInfo.ContainerPorts = containerPorts
  184. }
  185. return containerInfo
  186. }
  187. func getStringValueFromLabel(labels map[string]string, label string) string {
  188. if value, found := labels[label]; found {
  189. return value
  190. }
  191. // Do not report error, because there should be many old containers without label now.
  192. klog.V(3).Infof("Container doesn't have label %s, it may be an old or invalid container", label)
  193. // Return empty string "" for these containers, the caller will get value by other ways.
  194. return ""
  195. }
  196. func getIntValueFromLabel(labels map[string]string, label string) (int, error) {
  197. if strValue, found := labels[label]; found {
  198. intValue, err := strconv.Atoi(strValue)
  199. if err != nil {
  200. // This really should not happen. Just set value to 0 to handle this abnormal case
  201. return 0, err
  202. }
  203. return intValue, nil
  204. }
  205. // Do not report error, because there should be many old containers without label now.
  206. klog.V(3).Infof("Container doesn't have label %s, it may be an old or invalid container", label)
  207. // Just set the value to 0
  208. return 0, nil
  209. }
  210. func getUint64ValueFromLabel(labels map[string]string, label string) (uint64, error) {
  211. if strValue, found := labels[label]; found {
  212. intValue, err := strconv.ParseUint(strValue, 16, 64)
  213. if err != nil {
  214. // This really should not happen. Just set value to 0 to handle this abnormal case
  215. return 0, err
  216. }
  217. return intValue, nil
  218. }
  219. // Do not report error, because there should be many old containers without label now.
  220. klog.V(3).Infof("Container doesn't have label %s, it may be an old or invalid container", label)
  221. // Just set the value to 0
  222. return 0, nil
  223. }
  224. func getInt64PointerFromLabel(labels map[string]string, label string) (*int64, error) {
  225. if strValue, found := labels[label]; found {
  226. int64Value, err := strconv.ParseInt(strValue, 10, 64)
  227. if err != nil {
  228. return nil, err
  229. }
  230. return &int64Value, nil
  231. }
  232. // If the label is not found, return pointer nil.
  233. return nil, nil
  234. }
  235. // getJSONObjectFromLabel returns a bool value indicating whether an object is found.
  236. func getJSONObjectFromLabel(labels map[string]string, label string, value interface{}) (bool, error) {
  237. if strValue, found := labels[label]; found {
  238. err := json.Unmarshal([]byte(strValue), value)
  239. return found, err
  240. }
  241. // If the label is not found, return not found.
  242. return false, nil
  243. }