1
16
17 package apiextensions
18
19 import (
20 "reflect"
21 "testing"
22 "time"
23
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 )
26
27 func TestCRDHasFinalizer(t *testing.T) {
28 tests := []struct {
29 name string
30 crd *CustomResourceDefinition
31 finalizerToCheck string
32
33 expected bool
34 }{
35 {
36 name: "missing",
37 crd: &CustomResourceDefinition{
38 ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
39 },
40 finalizerToCheck: "it",
41 expected: false,
42 },
43 {
44 name: "present",
45 crd: &CustomResourceDefinition{
46 ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
47 },
48 finalizerToCheck: "it",
49 expected: true,
50 },
51 }
52 for _, tc := range tests {
53 actual := CRDHasFinalizer(tc.crd, tc.finalizerToCheck)
54 if tc.expected != actual {
55 t.Errorf("%v expected %v, got %v", tc.name, tc.expected, actual)
56 }
57 }
58 }
59
60 func TestCRDRemoveFinalizer(t *testing.T) {
61 tests := []struct {
62 name string
63 crd *CustomResourceDefinition
64 finalizerToCheck string
65
66 expected []string
67 }{
68 {
69 name: "missing",
70 crd: &CustomResourceDefinition{
71 ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
72 },
73 finalizerToCheck: "it",
74 expected: []string{"not-it"},
75 },
76 {
77 name: "present",
78 crd: &CustomResourceDefinition{
79 ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
80 },
81 finalizerToCheck: "it",
82 expected: []string{"not-it"},
83 },
84 }
85 for _, tc := range tests {
86 CRDRemoveFinalizer(tc.crd, tc.finalizerToCheck)
87 if !reflect.DeepEqual(tc.expected, tc.crd.Finalizers) {
88 t.Errorf("%v expected %v, got %v", tc.name, tc.expected, tc.crd.Finalizers)
89 }
90 }
91 }
92
93 func TestSetCRDCondition(t *testing.T) {
94 tests := []struct {
95 name string
96 crdCondition []CustomResourceDefinitionCondition
97 newCondition CustomResourceDefinitionCondition
98 expectedcrdCondition []CustomResourceDefinitionCondition
99 }{
100 {
101 name: "test setCRDcondition when one condition",
102 crdCondition: []CustomResourceDefinitionCondition{
103 {
104 Type: Established,
105 Status: ConditionTrue,
106 Reason: "Accepted",
107 Message: "the initial names have been accepted",
108 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
109 },
110 },
111 newCondition: CustomResourceDefinitionCondition{
112 Type: Established,
113 Status: ConditionFalse,
114 Reason: "NotAccepted",
115 Message: "Not accepted",
116 LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
117 },
118 expectedcrdCondition: []CustomResourceDefinitionCondition{
119 {
120 Type: Established,
121 Status: ConditionFalse,
122 Reason: "NotAccepted",
123 Message: "Not accepted",
124 LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
125 },
126 },
127 },
128 {
129 name: "test setCRDcondition when two condition",
130 crdCondition: []CustomResourceDefinitionCondition{
131 {
132 Type: Established,
133 Status: ConditionTrue,
134 Reason: "Accepted",
135 Message: "the initial names have been accepted",
136 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
137 },
138 {
139 Type: NamesAccepted,
140 Status: ConditionTrue,
141 Reason: "NoConflicts",
142 Message: "no conflicts found",
143 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
144 },
145 },
146 newCondition: CustomResourceDefinitionCondition{
147 Type: NamesAccepted,
148 Status: ConditionFalse,
149 Reason: "Conflicts",
150 Message: "conflicts found",
151 LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
152 },
153 expectedcrdCondition: []CustomResourceDefinitionCondition{
154 {
155 Type: Established,
156 Status: ConditionTrue,
157 Reason: "Accepted",
158 Message: "the initial names have been accepted",
159 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
160 },
161 {
162 Type: NamesAccepted,
163 Status: ConditionFalse,
164 Reason: "Conflicts",
165 Message: "conflicts found",
166 LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
167 },
168 },
169 },
170 {
171 name: "test setCRDcondition when condition needs to be appended",
172 crdCondition: []CustomResourceDefinitionCondition{
173 {
174 Type: Established,
175 Status: ConditionTrue,
176 Reason: "Accepted",
177 Message: "the initial names have been accepted",
178 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
179 },
180 },
181 newCondition: CustomResourceDefinitionCondition{
182 Type: Terminating,
183 Status: ConditionFalse,
184 Reason: "NeverEstablished",
185 Message: "resource was never established",
186 LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
187 },
188 expectedcrdCondition: []CustomResourceDefinitionCondition{
189 {
190 Type: Established,
191 Status: ConditionTrue,
192 Reason: "Accepted",
193 Message: "the initial names have been accepted",
194 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
195 },
196 {
197 Type: Terminating,
198 Status: ConditionFalse,
199 Reason: "NeverEstablished",
200 Message: "resource was never established",
201 LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
202 },
203 },
204 },
205 {
206 name: "set new condition which doesn't have lastTransitionTime set",
207 crdCondition: []CustomResourceDefinitionCondition{
208 {
209 Type: Established,
210 Status: ConditionTrue,
211 Reason: "Accepted",
212 Message: "the initial names have been accepted",
213 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
214 },
215 },
216 newCondition: CustomResourceDefinitionCondition{
217 Type: Established,
218 Status: ConditionFalse,
219 Reason: "NotAccepted",
220 Message: "Not accepted",
221 },
222 expectedcrdCondition: []CustomResourceDefinitionCondition{
223 {
224 Type: Established,
225 Status: ConditionFalse,
226 Reason: "NotAccepted",
227 Message: "Not accepted",
228 LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
229 },
230 },
231 },
232 {
233 name: "append new condition which doesn't have lastTransitionTime set",
234 crdCondition: []CustomResourceDefinitionCondition{
235 {
236 Type: Established,
237 Status: ConditionTrue,
238 Reason: "Accepted",
239 Message: "the initial names have been accepted",
240 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
241 },
242 },
243 newCondition: CustomResourceDefinitionCondition{
244 Type: Terminating,
245 Status: ConditionFalse,
246 Reason: "NeverEstablished",
247 Message: "resource was never established",
248 },
249 expectedcrdCondition: []CustomResourceDefinitionCondition{
250 {
251 Type: Established,
252 Status: ConditionTrue,
253 Reason: "Accepted",
254 Message: "the initial names have been accepted",
255 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
256 },
257 {
258 Type: Terminating,
259 Status: ConditionFalse,
260 Reason: "NeverEstablished",
261 Message: "resource was never established",
262 LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
263 },
264 },
265 },
266 }
267 for _, tc := range tests {
268 crd := generateCRDwithCondition(tc.crdCondition)
269 SetCRDCondition(crd, tc.newCondition)
270 if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
271 t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
272 }
273 for i := range tc.expectedcrdCondition {
274 if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
275 t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition[i], crd.Status.Conditions[i])
276 }
277 if crd.Status.Conditions[i].LastTransitionTime.IsZero() {
278 t.Errorf("%q/%d lastTransitionTime should not be null: %v", tc.name, i, crd.Status.Conditions[i])
279 }
280 }
281 }
282 }
283
284 func TestRemoveCRDCondition(t *testing.T) {
285 tests := []struct {
286 name string
287 crdCondition []CustomResourceDefinitionCondition
288 conditionType CustomResourceDefinitionConditionType
289 expectedcrdCondition []CustomResourceDefinitionCondition
290 }{
291 {
292 name: "test remove CRDCondition when the conditionType meets",
293 crdCondition: []CustomResourceDefinitionCondition{
294 {
295 Type: Established,
296 Status: ConditionTrue,
297 Reason: "Accepted",
298 Message: "the initial names have been accepted",
299 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
300 },
301 {
302 Type: NamesAccepted,
303 Status: ConditionTrue,
304 Reason: "NoConflicts",
305 Message: "no conflicts found",
306 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
307 },
308 },
309 conditionType: NamesAccepted,
310 expectedcrdCondition: []CustomResourceDefinitionCondition{
311 {
312 Type: Established,
313 Status: ConditionTrue,
314 Reason: "Accepted",
315 Message: "the initial names have been accepted",
316 LastTransitionTime: metav1.Date(2011, 1, 2, 0, 0, 0, 0, time.UTC),
317 },
318 },
319 },
320 {
321 name: "test remove CRDCondition when the conditionType not meets",
322 crdCondition: []CustomResourceDefinitionCondition{
323 {
324 Type: Established,
325 Status: ConditionTrue,
326 Reason: "Accepted",
327 Message: "the initial names have been accepted",
328 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
329 },
330 {
331 Type: NamesAccepted,
332 Status: ConditionTrue,
333 Reason: "NoConflicts",
334 Message: "no conflicts found",
335 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
336 },
337 },
338 conditionType: Terminating,
339 expectedcrdCondition: []CustomResourceDefinitionCondition{
340 {
341 Type: Established,
342 Status: ConditionTrue,
343 Reason: "Accepted",
344 Message: "the initial names have been accepted",
345 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
346 },
347 {
348 Type: NamesAccepted,
349 Status: ConditionTrue,
350 Reason: "NoConflicts",
351 Message: "no conflicts found",
352 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
353 },
354 },
355 },
356 }
357 for _, tc := range tests {
358 crd := generateCRDwithCondition(tc.crdCondition)
359 RemoveCRDCondition(crd, tc.conditionType)
360 if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
361 t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
362 }
363 for i := range tc.expectedcrdCondition {
364 if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
365 t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
366 }
367 }
368 }
369 }
370
371 func TestIsCRDConditionPresentAndEqual(t *testing.T) {
372 tests := []struct {
373 name string
374 crdCondition []CustomResourceDefinitionCondition
375 conditionType CustomResourceDefinitionConditionType
376 status ConditionStatus
377 expectresult bool
378 }{
379 {
380 name: "test CRDCondition is not Present",
381 crdCondition: []CustomResourceDefinitionCondition{
382 {
383 Type: Established,
384 Status: ConditionTrue,
385 Reason: "Accepted",
386 Message: "the initial names have been accepted",
387 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
388 },
389 {
390 Type: NamesAccepted,
391 Status: ConditionTrue,
392 Reason: "NoConflicts",
393 Message: "no conflicts found",
394 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
395 },
396 },
397 conditionType: Terminating,
398 status: ConditionTrue,
399 expectresult: false,
400 },
401 {
402 name: "test CRDCondition is Present but not Equal",
403 crdCondition: []CustomResourceDefinitionCondition{
404 {
405 Type: Established,
406 Status: ConditionTrue,
407 Reason: "Accepted",
408 Message: "the initial names have been accepted",
409 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
410 },
411 {
412 Type: NamesAccepted,
413 Status: ConditionTrue,
414 Reason: "NoConflicts",
415 Message: "no conflicts found",
416 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
417 },
418 },
419 conditionType: Established,
420 status: ConditionFalse,
421 expectresult: false,
422 },
423 {
424 name: "test CRDCondition is Present and Equal",
425 crdCondition: []CustomResourceDefinitionCondition{
426 {
427 Type: Established,
428 Status: ConditionTrue,
429 Reason: "Accepted",
430 Message: "the initial names have been accepted",
431 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
432 },
433 {
434 Type: NamesAccepted,
435 Status: ConditionTrue,
436 Reason: "NoConflicts",
437 Message: "no conflicts found",
438 LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
439 },
440 },
441 conditionType: NamesAccepted,
442 status: ConditionTrue,
443 expectresult: true,
444 },
445 }
446 for _, tc := range tests {
447 crd := generateCRDwithCondition(tc.crdCondition)
448 res := IsCRDConditionPresentAndEqual(crd, tc.conditionType, tc.status)
449 if res != tc.expectresult {
450 t.Errorf("%v expected %t, got %t", tc.name, tc.expectresult, res)
451 }
452 }
453 }
454
455 func generateCRDwithCondition(conditions []CustomResourceDefinitionCondition) *CustomResourceDefinition {
456 testCRDObjectMeta := metav1.ObjectMeta{
457 Name: "plural.group.com",
458 ResourceVersion: "12",
459 }
460 testCRDSpec := CustomResourceDefinitionSpec{
461 Group: "group.com",
462 Version: "version",
463 Scope: ResourceScope("Cluster"),
464 Names: CustomResourceDefinitionNames{
465 Plural: "plural",
466 Singular: "singular",
467 Kind: "kind",
468 ListKind: "listkind",
469 },
470 }
471 testCRDAcceptedNames := CustomResourceDefinitionNames{
472 Plural: "plural",
473 Singular: "singular",
474 Kind: "kind",
475 ListKind: "listkind",
476 }
477 return &CustomResourceDefinition{
478 ObjectMeta: testCRDObjectMeta,
479 Spec: testCRDSpec,
480 Status: CustomResourceDefinitionStatus{
481 AcceptedNames: testCRDAcceptedNames,
482 Conditions: conditions,
483 },
484 }
485 }
486
View as plain text