1
1
package io .javaoperatorsdk .operator .processing .dependent .kubernetes ;
2
2
3
- import java .util .HashMap ;
4
3
import java .util .List ;
5
4
import java .util .Map ;
6
5
11
10
12
11
import io .fabric8 .kubernetes .api .model .ConfigMap ;
13
12
import io .fabric8 .kubernetes .api .model .HasMetadata ;
13
+ import io .fabric8 .kubernetes .api .model .Secret ;
14
14
import io .fabric8 .kubernetes .api .model .apps .DaemonSet ;
15
15
import io .fabric8 .kubernetes .api .model .apps .Deployment ;
16
16
import io .fabric8 .kubernetes .api .model .apps .ReplicaSet ;
17
17
import io .fabric8 .kubernetes .api .model .apps .StatefulSet ;
18
18
import io .javaoperatorsdk .operator .MockKubernetesClient ;
19
+ import io .javaoperatorsdk .operator .OperatorException ;
19
20
import io .javaoperatorsdk .operator .ReconcilerUtils ;
20
21
import io .javaoperatorsdk .operator .api .config .ConfigurationService ;
21
22
import io .javaoperatorsdk .operator .api .config .ControllerConfiguration ;
22
23
import io .javaoperatorsdk .operator .api .reconciler .Context ;
23
24
24
25
import static org .assertj .core .api .Assertions .assertThat ;
26
+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
25
27
import static org .mockito .ArgumentMatchers .any ;
26
28
import static org .mockito .Mockito .mock ;
27
29
import static org .mockito .Mockito .when ;
@@ -47,6 +49,54 @@ void setup() {
47
49
when (mockedContext .getControllerConfiguration ()).thenReturn (controllerConfiguration );
48
50
}
49
51
52
+ @ Test
53
+ void noMatchWhenNoMatchingController () {
54
+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
55
+ var actual =
56
+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
57
+ actual
58
+ .getMetadata ()
59
+ .getManagedFields ()
60
+ .removeIf (managedFieldsEntry -> managedFieldsEntry .getManager ().equals ("controller" ));
61
+
62
+ assertThat (matcher .matches (actual , desired , mockedContext )).isFalse ();
63
+ }
64
+
65
+ @ Test
66
+ void exceptionWhenDuplicateController () {
67
+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
68
+ var actual =
69
+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
70
+ actual .getMetadata ().getManagedFields ().stream ()
71
+ .filter (managedFieldsEntry -> managedFieldsEntry .getManager ().equals ("controller" ))
72
+ .findFirst ()
73
+ .ifPresent (
74
+ managedFieldsEntry -> actual .getMetadata ().getManagedFields ().add (managedFieldsEntry ));
75
+
76
+ assertThatThrownBy (() -> matcher .matches (actual , desired , mockedContext ))
77
+ .isInstanceOf (OperatorException .class )
78
+ .hasMessage (
79
+ "More than one field manager exists with name: controller in resource: Deployment with"
80
+ + " name: test" );
81
+ }
82
+
83
+ @ Test
84
+ void matchWithSensitiveResource () {
85
+ var desired = loadResource ("secret-desired.yaml" , Secret .class );
86
+ var actual = loadResource ("secret.yaml" , Secret .class );
87
+
88
+ assertThat (matcher .matches (actual , desired , mockedContext )).isTrue ();
89
+ }
90
+
91
+ @ Test
92
+ void noMatchWithSensitiveResource () {
93
+ var desired = loadResource ("secret-desired.yaml" , Secret .class );
94
+ var actual = loadResource ("secret.yaml" , Secret .class );
95
+ actual .getData ().put ("key1" , "dmFsMg==" );
96
+
97
+ assertThat (matcher .matches (actual , desired , mockedContext )).isFalse ();
98
+ }
99
+
50
100
@ Test
51
101
void checksIfAddsNotAddedByController () {
52
102
var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
@@ -56,7 +106,40 @@ void checksIfAddsNotAddedByController() {
56
106
assertThat (matcher .matches (actual , desired , mockedContext )).isTrue ();
57
107
}
58
108
59
- // In the example the owner reference in a list is referenced by "k:", while all the fields are
109
+ @ Test
110
+ void throwExceptionWhenManagedListEntryNotFound () {
111
+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
112
+ var actual =
113
+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
114
+ final var container = actual .getSpec ().getTemplate ().getSpec ().getContainers ().get (0 );
115
+ container .setName ("foobar" );
116
+
117
+ assertThatThrownBy (() -> matcher .matches (actual , desired , mockedContext ))
118
+ .isInstanceOf (IllegalStateException .class )
119
+ .hasMessage (
120
+ "Cannot find list element for key: {\" name\" :\" nginx\" } in map: [[image,"
121
+ + " imagePullPolicy, name, ports, resources, terminationMessagePath,"
122
+ + " terminationMessagePolicy]]" );
123
+ }
124
+
125
+ @ Test
126
+ void throwExceptionWhenDuplicateManagedListEntryFound () {
127
+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
128
+ var actual =
129
+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
130
+ final var container = actual .getSpec ().getTemplate ().getSpec ().getContainers ().get (0 );
131
+ actual .getSpec ().getTemplate ().getSpec ().getContainers ().add (container );
132
+
133
+ assertThatThrownBy (() -> matcher .matches (actual , desired , mockedContext ))
134
+ .isInstanceOf (IllegalStateException .class )
135
+ .hasMessage (
136
+ "More targets found in list element for key: {\" name\" :\" nginx\" } in map: [[image,"
137
+ + " imagePullPolicy, name, ports, resources, terminationMessagePath,"
138
+ + " terminationMessagePolicy], [image, imagePullPolicy, name, ports, resources,"
139
+ + " terminationMessagePath, terminationMessagePolicy]]" );
140
+ }
141
+
142
+ // in the example the owner reference in a list is referenced by "k:", while all the fields are
60
143
// managed but not listed
61
144
@ Test
62
145
void emptyListElementMatchesAllFields () {
@@ -117,6 +200,14 @@ void addedLabelInDesiredMakesMatchFail() {
117
200
assertThat (matcher .matches (actualConfigMap , desiredConfigMap , mockedContext )).isFalse ();
118
201
}
119
202
203
+ @ Test
204
+ void withFinalizer () {
205
+ var desired = loadResource ("secret-with-finalizer-desired.yaml" , Secret .class );
206
+ var actual = loadResource ("secret-with-finalizer.yaml" , Secret .class );
207
+
208
+ assertThat (matcher .matches (actual , desired , mockedContext )).isTrue ();
209
+ }
210
+
120
211
@ ParameterizedTest
121
212
@ ValueSource (
122
213
strings = {
@@ -163,6 +254,23 @@ void testSanitizeState_statefulSetWithResources_withMismatch() {
163
254
assertThat (matcher .matches (actualStatefulSet , desiredStatefulSet , mockedContext )).isFalse ();
164
255
}
165
256
257
+ @ Test
258
+ void testSanitizeState_statefulSet_withResourceTypeMismatch () {
259
+ var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
260
+ var actualStatefulSet = loadResource ("sample-sts-resources.yaml" , StatefulSet .class );
261
+
262
+ assertThat (matcher .matches (actualStatefulSet , desiredReplicaSet , mockedContext )).isFalse ();
263
+ }
264
+
265
+ @ Test
266
+ void testSanitizeState_deployment_withResourceTypeMismatch () {
267
+ var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
268
+ var actualDeployment =
269
+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
270
+
271
+ assertThat (matcher .matches (actualDeployment , desiredReplicaSet , mockedContext )).isFalse ();
272
+ }
273
+
166
274
@ Test
167
275
void testSanitizeState_replicaSetWithResources () {
168
276
var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
@@ -180,6 +288,14 @@ void testSanitizeState_replicaSetWithResources_withMismatch() {
180
288
assertThat (matcher .matches (actualReplicaSet , desiredReplicaSet , mockedContext )).isFalse ();
181
289
}
182
290
291
+ @ Test
292
+ void testSanitizeState_replicaSet_withResourceTypeMismatch () {
293
+ var desiredDaemonSet = loadResource ("sample-ds-resources-desired.yaml" , DaemonSet .class );
294
+ var actualReplicaSet = loadResource ("sample-rs-resources.yaml" , ReplicaSet .class );
295
+
296
+ assertThat (matcher .matches (actualReplicaSet , desiredDaemonSet , mockedContext )).isFalse ();
297
+ }
298
+
183
299
@ Test
184
300
void testSanitizeState_daemonSetWithResources () {
185
301
var desiredDaemonSet = loadResource ("sample-ds-resources-desired.yaml" , DaemonSet .class );
@@ -196,6 +312,14 @@ void testSanitizeState_daemonSetWithResources_withMismatch() {
196
312
assertThat (matcher .matches (actualDaemonSet , desiredDaemonSet , mockedContext )).isFalse ();
197
313
}
198
314
315
+ @ Test
316
+ void testSanitizeState_daemonSet_withResourceTypeMismatch () {
317
+ var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
318
+ var actualDaemonSet = loadResource ("sample-ds-resources.yaml" , DaemonSet .class );
319
+
320
+ assertThat (matcher .matches (actualDaemonSet , desiredReplicaSet , mockedContext )).isFalse ();
321
+ }
322
+
199
323
@ ParameterizedTest
200
324
@ ValueSource (booleans = {true , false })
201
325
void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel (boolean readOnly ) {
@@ -222,16 +346,22 @@ void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel(boolean readOnly
222
346
}
223
347
224
348
@ Test
225
- @ SuppressWarnings ("unchecked" )
226
- void testSortMapWithNestedMap () {
227
- var nestedMap = new HashMap <String , Object >();
228
- nestedMap .put ("z" , 26 );
229
- nestedMap .put ("y" , 25 );
349
+ void keepOnlyManagedFields_withInvalidManagedFieldsKey () {
350
+ assertThatThrownBy (
351
+ () ->
352
+ SSABasedGenericKubernetesResourceMatcher .keepOnlyManagedFields (
353
+ Map .of (),
354
+ Map .of (),
355
+ Map .of ("invalid" , 1 ),
356
+ mockedContext .getClient ().getKubernetesSerialization ())) //
357
+ .isInstanceOf (IllegalStateException .class ) //
358
+ .hasMessage ("Key: invalid has no prefix: f:" );
359
+ }
230
360
231
- var unsortedMap = new HashMap < String , Object >();
232
- unsortedMap . put ( "b" , nestedMap );
233
- unsortedMap . put ( "a" , 1 );
234
- unsortedMap . put ( "c" , 2 );
361
+ @ Test
362
+ @ SuppressWarnings ( "unchecked" )
363
+ void testSortMap () {
364
+ final var unsortedMap = Map . of ( "b" , Map . of ( "z" , 26 , "y" , 25 ), "a" , List . of ( "w" , "v" ), "c" , 2 );
235
365
236
366
var sortedMap = SSABasedGenericKubernetesResourceMatcher .sortMap (unsortedMap );
237
367
assertThat (sortedMap .keySet ()).containsExactly ("a" , "b" , "c" );
@@ -242,18 +372,11 @@ void testSortMapWithNestedMap() {
242
372
243
373
@ Test
244
374
@ SuppressWarnings ("unchecked" )
245
- void sortListItemsTest () {
246
- var nestedMap1 = new HashMap <String , Object >();
247
- nestedMap1 .put ("z" , 26 );
248
- nestedMap1 .put ("y" , 25 );
249
-
250
- var nestedMap2 = new HashMap <String , Object >();
251
- nestedMap2 .put ("b" , 26 );
252
- nestedMap2 .put ("c" , 25 );
253
- nestedMap2 .put ("a" , 24 );
254
-
255
- var unsortedListItems = List .<Object >of (1 , nestedMap1 , nestedMap2 );
256
- var sortedListItems = SSABasedGenericKubernetesResourceMatcher .sortListItems (unsortedListItems );
375
+ void testSortListItems () {
376
+ final var unsortedList =
377
+ List .of (1 , Map .of ("z" , 26 , "y" , 25 ), Map .of ("b" , 26 , "c" , 25 , "a" , 24 ), List .of ("w" , "v" ));
378
+
379
+ var sortedListItems = SSABasedGenericKubernetesResourceMatcher .sortListItems (unsortedList );
257
380
assertThat (sortedListItems ).element (0 ).isEqualTo (1 );
258
381
259
382
var sortedNestedMap1 = (Map <String , Object >) sortedListItems .get (1 );
@@ -265,7 +388,7 @@ void sortListItemsTest() {
265
388
266
389
private static <R > R loadResource (String fileName , Class <R > clazz ) {
267
390
return ReconcilerUtils .loadYaml (
268
- clazz , SSABasedGenericKubernetesResourceMatcherTest .class , fileName );
391
+ clazz , SSABasedGenericKubernetesResourceMatcherTest .class , fileName );
269
392
}
270
393
271
394
private static class ConfigMapDR extends KubernetesDependentResource <ConfigMap , ConfigMap > {
0 commit comments