labels.go 11 KB

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