k8s.io/kubernetes@v1.29.3/pkg/kubelet/kuberuntime/labels_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package kuberuntime 18 19 import ( 20 "reflect" 21 "testing" 22 23 v1 "k8s.io/api/core/v1" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/util/intstr" 26 utilfeature "k8s.io/apiserver/pkg/util/feature" 27 featuregatetesting "k8s.io/component-base/featuregate/testing" 28 "k8s.io/kubernetes/pkg/features" 29 kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" 30 ) 31 32 func TestContainerLabels(t *testing.T) { 33 deletionGracePeriod := int64(10) 34 terminationGracePeriod := int64(10) 35 lifecycle := &v1.Lifecycle{ 36 // Left PostStart as nil 37 PreStop: &v1.LifecycleHandler{ 38 Exec: &v1.ExecAction{ 39 Command: []string{"action1", "action2"}, 40 }, 41 HTTPGet: &v1.HTTPGetAction{ 42 Path: "path", 43 Host: "host", 44 Port: intstr.FromInt32(8080), 45 Scheme: "scheme", 46 }, 47 TCPSocket: &v1.TCPSocketAction{ 48 Port: intstr.FromString("80"), 49 }, 50 }, 51 } 52 container := &v1.Container{ 53 Name: "test_container", 54 TerminationMessagePath: "/somepath", 55 Lifecycle: lifecycle, 56 } 57 pod := &v1.Pod{ 58 ObjectMeta: metav1.ObjectMeta{ 59 Name: "test_pod", 60 Namespace: "test_pod_namespace", 61 UID: "test_pod_uid", 62 DeletionGracePeriodSeconds: &deletionGracePeriod, 63 }, 64 Spec: v1.PodSpec{ 65 Containers: []v1.Container{*container}, 66 TerminationGracePeriodSeconds: &terminationGracePeriod, 67 }, 68 } 69 70 var tests = []struct { 71 description string 72 expected *labeledContainerInfo 73 }{ 74 { 75 "Regular containers", 76 &labeledContainerInfo{ 77 PodName: pod.Name, 78 PodNamespace: pod.Namespace, 79 PodUID: pod.UID, 80 ContainerName: container.Name, 81 }, 82 }, 83 } 84 85 // Test whether we can get right information from label 86 for _, test := range tests { 87 labels := newContainerLabels(container, pod) 88 containerInfo := getContainerInfoFromLabels(labels) 89 if !reflect.DeepEqual(containerInfo, test.expected) { 90 t.Errorf("%v: expected %v, got %v", test.description, test.expected, containerInfo) 91 } 92 } 93 } 94 95 func TestContainerAnnotations(t *testing.T) { 96 restartCount := 5 97 deletionGracePeriod := int64(10) 98 terminationGracePeriod := int64(10) 99 opts := &kubecontainer.RunContainerOptions{ 100 Annotations: []kubecontainer.Annotation{ 101 {Name: "Foo", Value: "bar"}, 102 }, 103 } 104 lifecycle := &v1.Lifecycle{ 105 // Left PostStart as nil 106 PreStop: &v1.LifecycleHandler{ 107 Exec: &v1.ExecAction{ 108 Command: []string{"action1", "action2"}, 109 }, 110 HTTPGet: &v1.HTTPGetAction{ 111 Path: "path", 112 Host: "host", 113 Port: intstr.FromInt32(8080), 114 Scheme: "scheme", 115 }, 116 TCPSocket: &v1.TCPSocketAction{ 117 Port: intstr.FromString("80"), 118 }, 119 }, 120 } 121 containerPorts := []v1.ContainerPort{ 122 { 123 Name: "http", 124 HostPort: 80, 125 ContainerPort: 8080, 126 Protocol: v1.ProtocolTCP, 127 }, 128 { 129 Name: "https", 130 HostPort: 443, 131 ContainerPort: 6443, 132 Protocol: v1.ProtocolTCP, 133 }, 134 } 135 container := &v1.Container{ 136 Name: "test_container", 137 Ports: containerPorts, 138 TerminationMessagePath: "/somepath", 139 Lifecycle: lifecycle, 140 } 141 pod := &v1.Pod{ 142 ObjectMeta: metav1.ObjectMeta{ 143 Name: "test_pod", 144 Namespace: "test_pod_namespace", 145 UID: "test_pod_uid", 146 DeletionGracePeriodSeconds: &deletionGracePeriod, 147 }, 148 Spec: v1.PodSpec{ 149 Containers: []v1.Container{*container}, 150 TerminationGracePeriodSeconds: &terminationGracePeriod, 151 }, 152 } 153 expected := &annotatedContainerInfo{ 154 ContainerPorts: containerPorts, 155 PodDeletionGracePeriod: pod.DeletionGracePeriodSeconds, 156 PodTerminationGracePeriod: pod.Spec.TerminationGracePeriodSeconds, 157 Hash: kubecontainer.HashContainer(container), 158 HashWithoutResources: kubecontainer.HashContainerWithoutResources(container), 159 RestartCount: restartCount, 160 TerminationMessagePath: container.TerminationMessagePath, 161 PreStopHandler: container.Lifecycle.PreStop, 162 } 163 164 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true)() 165 // Test whether we can get right information from label 166 annotations := newContainerAnnotations(container, pod, restartCount, opts) 167 containerInfo := getContainerInfoFromAnnotations(annotations) 168 if !reflect.DeepEqual(containerInfo, expected) { 169 t.Errorf("expected %v, got %v", expected, containerInfo) 170 } 171 if v, ok := annotations[opts.Annotations[0].Name]; !ok || v != opts.Annotations[0].Value { 172 t.Errorf("expected annotation %s to exist got %v, %v", opts.Annotations[0].Name, ok, v) 173 } 174 175 // Test when DeletionGracePeriodSeconds, TerminationGracePeriodSeconds and Lifecycle are nil, 176 // the information got from annotations should also be nil 177 container.Lifecycle = nil 178 pod.DeletionGracePeriodSeconds = nil 179 pod.Spec.TerminationGracePeriodSeconds = nil 180 expected.PodDeletionGracePeriod = nil 181 expected.PodTerminationGracePeriod = nil 182 expected.PreStopHandler = nil 183 // Because container is changed, the Hash should be updated 184 expected.Hash = kubecontainer.HashContainer(container) 185 expected.HashWithoutResources = kubecontainer.HashContainerWithoutResources(container) 186 annotations = newContainerAnnotations(container, pod, restartCount, opts) 187 containerInfo = getContainerInfoFromAnnotations(annotations) 188 if !reflect.DeepEqual(containerInfo, expected) { 189 t.Errorf("expected %v, got %v", expected, containerInfo) 190 } 191 if v, ok := annotations[opts.Annotations[0].Name]; !ok || v != opts.Annotations[0].Value { 192 t.Errorf("expected annotation %s to exist got %v, %v", opts.Annotations[0].Name, ok, v) 193 } 194 } 195 196 func TestPodLabels(t *testing.T) { 197 pod := &v1.Pod{ 198 ObjectMeta: metav1.ObjectMeta{ 199 Name: "test_pod", 200 Namespace: "test_pod_namespace", 201 UID: "test_pod_uid", 202 Labels: map[string]string{"foo": "bar"}, 203 }, 204 Spec: v1.PodSpec{ 205 Containers: []v1.Container{}, 206 }, 207 } 208 expected := &labeledPodSandboxInfo{ 209 Labels: pod.Labels, 210 PodName: pod.Name, 211 PodNamespace: pod.Namespace, 212 PodUID: pod.UID, 213 } 214 215 // Test whether we can get right information from label 216 labels := newPodLabels(pod) 217 podSandboxInfo := getPodSandboxInfoFromLabels(labels) 218 if !reflect.DeepEqual(podSandboxInfo, expected) { 219 t.Errorf("expected %v, got %v", expected, podSandboxInfo) 220 } 221 } 222 223 func TestPodAnnotations(t *testing.T) { 224 pod := &v1.Pod{ 225 ObjectMeta: metav1.ObjectMeta{ 226 Name: "test_pod", 227 Namespace: "test_pod_namespace", 228 UID: "test_pod_uid", 229 Annotations: map[string]string{"foo": "bar"}, 230 }, 231 Spec: v1.PodSpec{ 232 Containers: []v1.Container{}, 233 }, 234 } 235 expected := &annotatedPodSandboxInfo{ 236 Annotations: map[string]string{"foo": "bar"}, 237 } 238 239 // Test whether we can get right information from annotations 240 annotations := newPodAnnotations(pod) 241 podSandboxInfo := getPodSandboxInfoFromAnnotations(annotations) 242 if !reflect.DeepEqual(podSandboxInfo, expected) { 243 t.Errorf("expected %v, got %v", expected, podSandboxInfo) 244 } 245 }