1
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 }
316
View as plain text