k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/kubelet/config/common_test.go (about) 1 /* 2 Copyright 2015 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 config 18 19 import ( 20 "errors" 21 "reflect" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 26 v1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/runtime" 29 "k8s.io/apimachinery/pkg/types" 30 clientscheme "k8s.io/client-go/kubernetes/scheme" 31 "k8s.io/kubernetes/pkg/api/legacyscheme" 32 "k8s.io/kubernetes/pkg/apis/core" 33 "k8s.io/kubernetes/pkg/apis/core/validation" 34 "k8s.io/kubernetes/pkg/securitycontext" 35 "k8s.io/utils/ptr" 36 ) 37 38 func noDefault(*core.Pod) error { return nil } 39 40 func TestDecodeSinglePod(t *testing.T) { 41 grace := int64(30) 42 enableServiceLinks := v1.DefaultEnableServiceLinks 43 pod := &v1.Pod{ 44 TypeMeta: metav1.TypeMeta{ 45 APIVersion: "", 46 }, 47 ObjectMeta: metav1.ObjectMeta{ 48 Name: "test", 49 UID: "12345", 50 Namespace: "mynamespace", 51 }, 52 Spec: v1.PodSpec{ 53 RestartPolicy: v1.RestartPolicyAlways, 54 DNSPolicy: v1.DNSClusterFirst, 55 TerminationGracePeriodSeconds: &grace, 56 Containers: []v1.Container{{ 57 Name: "image", 58 Image: "test/image", 59 ImagePullPolicy: "IfNotPresent", 60 TerminationMessagePath: "/dev/termination-log", 61 TerminationMessagePolicy: v1.TerminationMessageReadFile, 62 SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), 63 }}, 64 SecurityContext: &v1.PodSecurityContext{}, 65 SchedulerName: v1.DefaultSchedulerName, 66 EnableServiceLinks: &enableServiceLinks, 67 }, 68 Status: v1.PodStatus{ 69 PodIP: "1.2.3.4", 70 PodIPs: []v1.PodIP{ 71 { 72 IP: "1.2.3.4", 73 }, 74 }, 75 }, 76 } 77 json, err := runtime.Encode(clientscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), pod) 78 if err != nil { 79 t.Errorf("unexpected error: %v", err) 80 } 81 parsed, podOut, err := tryDecodeSinglePod(json, noDefault) 82 if !parsed { 83 t.Errorf("expected to have parsed file: (%s)", string(json)) 84 } 85 if err != nil { 86 t.Errorf("unexpected error: %v (%s)", err, string(json)) 87 } 88 if !reflect.DeepEqual(pod, podOut) { 89 t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(json)) 90 } 91 92 for _, gv := range legacyscheme.Scheme.PrioritizedVersionsForGroup(v1.GroupName) { 93 info, _ := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), "application/yaml") 94 encoder := legacyscheme.Codecs.EncoderForVersion(info.Serializer, gv) 95 yaml, err := runtime.Encode(encoder, pod) 96 if err != nil { 97 t.Errorf("unexpected error: %v", err) 98 } 99 parsed, podOut, err = tryDecodeSinglePod(yaml, noDefault) 100 if !parsed { 101 t.Errorf("expected to have parsed file: (%s)", string(yaml)) 102 } 103 if err != nil { 104 t.Errorf("unexpected error: %v (%s)", err, string(yaml)) 105 } 106 if !reflect.DeepEqual(pod, podOut) { 107 t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(yaml)) 108 } 109 } 110 } 111 112 func TestDecodeSinglePodRejectsClusterTrustBundleVolumes(t *testing.T) { 113 grace := int64(30) 114 enableServiceLinks := v1.DefaultEnableServiceLinks 115 pod := &v1.Pod{ 116 TypeMeta: metav1.TypeMeta{ 117 APIVersion: "", 118 }, 119 ObjectMeta: metav1.ObjectMeta{ 120 Name: "test", 121 UID: "12345", 122 Namespace: "mynamespace", 123 }, 124 Spec: v1.PodSpec{ 125 RestartPolicy: v1.RestartPolicyAlways, 126 DNSPolicy: v1.DNSClusterFirst, 127 TerminationGracePeriodSeconds: &grace, 128 Containers: []v1.Container{{ 129 Name: "image", 130 Image: "test/image", 131 ImagePullPolicy: "IfNotPresent", 132 TerminationMessagePath: "/dev/termination-log", 133 TerminationMessagePolicy: v1.TerminationMessageReadFile, 134 SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), 135 VolumeMounts: []v1.VolumeMount{ 136 { 137 Name: "ctb-volume", 138 MountPath: "/var/run/ctb-volume", 139 }, 140 }, 141 }}, 142 Volumes: []v1.Volume{ 143 { 144 Name: "ctb-volume", 145 VolumeSource: v1.VolumeSource{ 146 Projected: &v1.ProjectedVolumeSource{ 147 Sources: []v1.VolumeProjection{ 148 { 149 ClusterTrustBundle: &v1.ClusterTrustBundleProjection{ 150 Name: ptr.To("my-ctb"), 151 Path: "ctb-file", 152 }, 153 }, 154 }, 155 }, 156 }, 157 }, 158 }, 159 SecurityContext: &v1.PodSecurityContext{}, 160 SchedulerName: v1.DefaultSchedulerName, 161 EnableServiceLinks: &enableServiceLinks, 162 }, 163 Status: v1.PodStatus{ 164 PodIP: "1.2.3.4", 165 PodIPs: []v1.PodIP{ 166 { 167 IP: "1.2.3.4", 168 }, 169 }, 170 }, 171 } 172 json, err := runtime.Encode(clientscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), pod) 173 if err != nil { 174 t.Errorf("unexpected error: %v", err) 175 } 176 _, _, err = tryDecodeSinglePod(json, noDefault) 177 if !errors.Is(err, ErrStaticPodTriedToUseClusterTrustBundle) { 178 t.Errorf("Got error %q, want %q", err, ErrStaticPodTriedToUseClusterTrustBundle) 179 } 180 } 181 182 func TestDecodePodList(t *testing.T) { 183 grace := int64(30) 184 enableServiceLinks := v1.DefaultEnableServiceLinks 185 pod := &v1.Pod{ 186 TypeMeta: metav1.TypeMeta{ 187 APIVersion: "", 188 }, 189 ObjectMeta: metav1.ObjectMeta{ 190 Name: "test", 191 UID: "12345", 192 Namespace: "mynamespace", 193 }, 194 Spec: v1.PodSpec{ 195 RestartPolicy: v1.RestartPolicyAlways, 196 DNSPolicy: v1.DNSClusterFirst, 197 TerminationGracePeriodSeconds: &grace, 198 Containers: []v1.Container{{ 199 Name: "image", 200 Image: "test/image", 201 ImagePullPolicy: "IfNotPresent", 202 TerminationMessagePath: "/dev/termination-log", 203 TerminationMessagePolicy: v1.TerminationMessageReadFile, 204 205 SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), 206 }}, 207 SecurityContext: &v1.PodSecurityContext{}, 208 SchedulerName: v1.DefaultSchedulerName, 209 EnableServiceLinks: &enableServiceLinks, 210 }, 211 Status: v1.PodStatus{ 212 PodIP: "1.2.3.4", 213 PodIPs: []v1.PodIP{ 214 { 215 IP: "1.2.3.4", 216 }, 217 }, 218 }, 219 } 220 podList := &v1.PodList{ 221 Items: []v1.Pod{*pod}, 222 } 223 json, err := runtime.Encode(clientscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), podList) 224 if err != nil { 225 t.Errorf("unexpected error: %v", err) 226 } 227 parsed, podListOut, err := tryDecodePodList(json, noDefault) 228 if !parsed { 229 t.Errorf("expected to have parsed file: (%s)", string(json)) 230 } 231 if err != nil { 232 t.Errorf("unexpected error: %v (%s)", err, string(json)) 233 } 234 if !reflect.DeepEqual(podList, &podListOut) { 235 t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", podList, &podListOut, string(json)) 236 } 237 238 for _, gv := range legacyscheme.Scheme.PrioritizedVersionsForGroup(v1.GroupName) { 239 info, _ := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), "application/yaml") 240 encoder := legacyscheme.Codecs.EncoderForVersion(info.Serializer, gv) 241 yaml, err := runtime.Encode(encoder, podList) 242 if err != nil { 243 t.Errorf("unexpected error: %v", err) 244 } 245 246 parsed, podListOut, err = tryDecodePodList(yaml, noDefault) 247 if !parsed { 248 t.Errorf("expected to have parsed file: (%s): %v", string(yaml), err) 249 continue 250 } 251 if err != nil { 252 t.Errorf("unexpected error: %v (%s)", err, string(yaml)) 253 continue 254 } 255 if !reflect.DeepEqual(podList, &podListOut) { 256 t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, &podListOut, string(yaml)) 257 } 258 } 259 } 260 261 func TestStaticPodNameGenerate(t *testing.T) { 262 testCases := []struct { 263 nodeName types.NodeName 264 podName string 265 expected string 266 overwrite string 267 shouldErr bool 268 }{ 269 { 270 "node1", 271 "static-pod1", 272 "static-pod1-node1", 273 "", 274 false, 275 }, 276 { 277 "Node1", 278 "static-pod1", 279 "static-pod1-node1", 280 "", 281 false, 282 }, 283 { 284 "NODE1", 285 "static-pod1", 286 "static-pod1-node1", 287 "static-pod1-NODE1", 288 true, 289 }, 290 } 291 for _, c := range testCases { 292 assert.Equal(t, c.expected, generatePodName(c.podName, c.nodeName), "wrong pod name generated") 293 pod := &core.Pod{} 294 pod.Name = c.podName 295 if c.overwrite != "" { 296 pod.Name = c.overwrite 297 } 298 errs := validation.ValidatePodCreate(pod, validation.PodValidationOptions{}) 299 if c.shouldErr { 300 specNameErrored := false 301 for _, err := range errs { 302 if err.Field == "metadata.name" { 303 specNameErrored = true 304 } 305 } 306 assert.NotEmpty(t, specNameErrored, "expecting error") 307 } else { 308 for _, err := range errs { 309 if err.Field == "metadata.name" { 310 t.Fail() 311 } 312 } 313 } 314 } 315 }