11package io .javaoperatorsdk .operator .processing .dependent .kubernetes ;
22
3- import java .util .HashMap ;
43import java .util .List ;
54import java .util .Map ;
65
1110
1211import io .fabric8 .kubernetes .api .model .ConfigMap ;
1312import io .fabric8 .kubernetes .api .model .HasMetadata ;
13+ import io .fabric8 .kubernetes .api .model .Secret ;
1414import io .fabric8 .kubernetes .api .model .apps .DaemonSet ;
1515import io .fabric8 .kubernetes .api .model .apps .Deployment ;
1616import io .fabric8 .kubernetes .api .model .apps .ReplicaSet ;
1717import io .fabric8 .kubernetes .api .model .apps .StatefulSet ;
1818import io .javaoperatorsdk .operator .MockKubernetesClient ;
19+ import io .javaoperatorsdk .operator .OperatorException ;
1920import io .javaoperatorsdk .operator .ReconcilerUtils ;
2021import io .javaoperatorsdk .operator .api .config .ConfigurationService ;
2122import io .javaoperatorsdk .operator .api .config .ControllerConfiguration ;
2223import io .javaoperatorsdk .operator .api .reconciler .Context ;
2324
2425import static org .assertj .core .api .Assertions .assertThat ;
26+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2527import static org .mockito .Mockito .mock ;
2628import static org .mockito .Mockito .when ;
2729
@@ -45,6 +47,54 @@ void setup() {
4547 when (mockedContext .getControllerConfiguration ()).thenReturn (controllerConfiguration );
4648 }
4749
50+ @ Test
51+ void noMatchWhenNoMatchingController () {
52+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
53+ var actual =
54+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
55+ actual
56+ .getMetadata ()
57+ .getManagedFields ()
58+ .removeIf (managedFieldsEntry -> managedFieldsEntry .getManager ().equals ("controller" ));
59+
60+ assertThat (matcher .matches (actual , desired , mockedContext )).isFalse ();
61+ }
62+
63+ @ Test
64+ void exceptionWhenDuplicateController () {
65+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
66+ var actual =
67+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
68+ actual .getMetadata ().getManagedFields ().stream ()
69+ .filter (managedFieldsEntry -> managedFieldsEntry .getManager ().equals ("controller" ))
70+ .findFirst ()
71+ .ifPresent (
72+ managedFieldsEntry -> actual .getMetadata ().getManagedFields ().add (managedFieldsEntry ));
73+
74+ assertThatThrownBy (() -> matcher .matches (actual , desired , mockedContext ))
75+ .isInstanceOf (OperatorException .class )
76+ .hasMessage (
77+ "More than one field manager exists with name: controller in resource: Deployment with"
78+ + " name: test" );
79+ }
80+
81+ @ Test
82+ void matchWithSensitiveResource () {
83+ var desired = loadResource ("secret-desired.yaml" , Secret .class );
84+ var actual = loadResource ("secret.yaml" , Secret .class );
85+
86+ assertThat (matcher .matches (actual , desired , mockedContext )).isTrue ();
87+ }
88+
89+ @ Test
90+ void noMatchWithSensitiveResource () {
91+ var desired = loadResource ("secret-desired.yaml" , Secret .class );
92+ var actual = loadResource ("secret.yaml" , Secret .class );
93+ actual .getData ().put ("key1" , "dmFsMg==" );
94+
95+ assertThat (matcher .matches (actual , desired , mockedContext )).isFalse ();
96+ }
97+
4898 @ Test
4999 void checksIfAddsNotAddedByController () {
50100 var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
@@ -54,7 +104,40 @@ void checksIfAddsNotAddedByController() {
54104 assertThat (matcher .matches (actual , desired , mockedContext )).isTrue ();
55105 }
56106
57- // In the example the owner reference in a list is referenced by "k:", while all the fields are
107+ @ Test
108+ void throwExceptionWhenManagedListEntryNotFound () {
109+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
110+ var actual =
111+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
112+ final var container = actual .getSpec ().getTemplate ().getSpec ().getContainers ().get (0 );
113+ container .setName ("foobar" );
114+
115+ assertThatThrownBy (() -> matcher .matches (actual , desired , mockedContext ))
116+ .isInstanceOf (IllegalStateException .class )
117+ .hasMessage (
118+ "Cannot find list element for key: {\" name\" :\" nginx\" } in map: [[image,"
119+ + " imagePullPolicy, name, ports, resources, terminationMessagePath,"
120+ + " terminationMessagePolicy]]" );
121+ }
122+
123+ @ Test
124+ void throwExceptionWhenDuplicateManagedListEntryFound () {
125+ var desired = loadResource ("nginx-deployment.yaml" , Deployment .class );
126+ var actual =
127+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
128+ final var container = actual .getSpec ().getTemplate ().getSpec ().getContainers ().get (0 );
129+ actual .getSpec ().getTemplate ().getSpec ().getContainers ().add (container );
130+
131+ assertThatThrownBy (() -> matcher .matches (actual , desired , mockedContext ))
132+ .isInstanceOf (IllegalStateException .class )
133+ .hasMessage (
134+ "More targets found in list element for key: {\" name\" :\" nginx\" } in map: [[image,"
135+ + " imagePullPolicy, name, ports, resources, terminationMessagePath,"
136+ + " terminationMessagePolicy], [image, imagePullPolicy, name, ports, resources,"
137+ + " terminationMessagePath, terminationMessagePolicy]]" );
138+ }
139+
140+ // in the example the owner reference in a list is referenced by "k:", while all the fields are
58141 // managed but not listed
59142 @ Test
60143 void emptyListElementMatchesAllFields () {
@@ -115,6 +198,14 @@ void addedLabelInDesiredMakesMatchFail() {
115198 assertThat (matcher .matches (actualConfigMap , desiredConfigMap , mockedContext )).isFalse ();
116199 }
117200
201+ @ Test
202+ void withFinalizer () {
203+ var desired = loadResource ("secret-with-finalizer-desired.yaml" , Secret .class );
204+ var actual = loadResource ("secret-with-finalizer.yaml" , Secret .class );
205+
206+ assertThat (matcher .matches (actual , desired , mockedContext )).isTrue ();
207+ }
208+
118209 @ ParameterizedTest
119210 @ ValueSource (
120211 strings = {
@@ -161,6 +252,23 @@ void testSanitizeState_statefulSetWithResources_withMismatch() {
161252 assertThat (matcher .matches (actualStatefulSet , desiredStatefulSet , mockedContext )).isFalse ();
162253 }
163254
255+ @ Test
256+ void testSanitizeState_statefulSet_withResourceTypeMismatch () {
257+ var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
258+ var actualStatefulSet = loadResource ("sample-sts-resources.yaml" , StatefulSet .class );
259+
260+ assertThat (matcher .matches (actualStatefulSet , desiredReplicaSet , mockedContext )).isFalse ();
261+ }
262+
263+ @ Test
264+ void testSanitizeState_deployment_withResourceTypeMismatch () {
265+ var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
266+ var actualDeployment =
267+ loadResource ("deployment-with-managed-fields-additional-controller.yaml" , Deployment .class );
268+
269+ assertThat (matcher .matches (actualDeployment , desiredReplicaSet , mockedContext )).isFalse ();
270+ }
271+
164272 @ Test
165273 void testSanitizeState_replicaSetWithResources () {
166274 var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
@@ -178,6 +286,14 @@ void testSanitizeState_replicaSetWithResources_withMismatch() {
178286 assertThat (matcher .matches (actualReplicaSet , desiredReplicaSet , mockedContext )).isFalse ();
179287 }
180288
289+ @ Test
290+ void testSanitizeState_replicaSet_withResourceTypeMismatch () {
291+ var desiredDaemonSet = loadResource ("sample-ds-resources-desired.yaml" , DaemonSet .class );
292+ var actualReplicaSet = loadResource ("sample-rs-resources.yaml" , ReplicaSet .class );
293+
294+ assertThat (matcher .matches (actualReplicaSet , desiredDaemonSet , mockedContext )).isFalse ();
295+ }
296+
181297 @ Test
182298 void testSanitizeState_daemonSetWithResources () {
183299 var desiredDaemonSet = loadResource ("sample-ds-resources-desired.yaml" , DaemonSet .class );
@@ -194,6 +310,14 @@ void testSanitizeState_daemonSetWithResources_withMismatch() {
194310 assertThat (matcher .matches (actualDaemonSet , desiredDaemonSet , mockedContext )).isFalse ();
195311 }
196312
313+ @ Test
314+ void testSanitizeState_daemonSet_withResourceTypeMismatch () {
315+ var desiredReplicaSet = loadResource ("sample-rs-resources-desired.yaml" , ReplicaSet .class );
316+ var actualDaemonSet = loadResource ("sample-ds-resources.yaml" , DaemonSet .class );
317+
318+ assertThat (matcher .matches (actualDaemonSet , desiredReplicaSet , mockedContext )).isFalse ();
319+ }
320+
197321 @ ParameterizedTest
198322 @ ValueSource (booleans = {true , false })
199323 void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel (boolean readOnly ) {
@@ -209,16 +333,22 @@ void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel(boolean readOnly
209333 }
210334
211335 @ Test
212- @ SuppressWarnings ("unchecked" )
213- void testSortMapWithNestedMap () {
214- var nestedMap = new HashMap <String , Object >();
215- nestedMap .put ("z" , 26 );
216- nestedMap .put ("y" , 25 );
336+ void keepOnlyManagedFields_withInvalidManagedFieldsKey () {
337+ assertThatThrownBy (
338+ () ->
339+ SSABasedGenericKubernetesResourceMatcher .keepOnlyManagedFields (
340+ Map .of (),
341+ Map .of (),
342+ Map .of ("invalid" , 1 ),
343+ mockedContext .getClient ().getKubernetesSerialization ())) //
344+ .isInstanceOf (IllegalStateException .class ) //
345+ .hasMessage ("Key: invalid has no prefix: f:" );
346+ }
217347
218- var unsortedMap = new HashMap < String , Object >();
219- unsortedMap . put ( "b" , nestedMap );
220- unsortedMap . put ( "a" , 1 );
221- unsortedMap . put ( "c" , 2 );
348+ @ Test
349+ @ SuppressWarnings ( "unchecked" )
350+ void testSortMap () {
351+ final var unsortedMap = Map . of ( "b" , Map . of ( "z" , 26 , "y" , 25 ), "a" , List . of ( "w" , "v" ), "c" , 2 );
222352
223353 var sortedMap = SSABasedGenericKubernetesResourceMatcher .sortMap (unsortedMap );
224354 assertThat (sortedMap .keySet ()).containsExactly ("a" , "b" , "c" );
@@ -229,18 +359,11 @@ void testSortMapWithNestedMap() {
229359
230360 @ Test
231361 @ SuppressWarnings ("unchecked" )
232- void sortListItemsTest () {
233- var nestedMap1 = new HashMap <String , Object >();
234- nestedMap1 .put ("z" , 26 );
235- nestedMap1 .put ("y" , 25 );
236-
237- var nestedMap2 = new HashMap <String , Object >();
238- nestedMap2 .put ("b" , 26 );
239- nestedMap2 .put ("c" , 25 );
240- nestedMap2 .put ("a" , 24 );
241-
242- var unsortedListItems = List .<Object >of (1 , nestedMap1 , nestedMap2 );
243- var sortedListItems = SSABasedGenericKubernetesResourceMatcher .sortListItems (unsortedListItems );
362+ void testSortListItems () {
363+ final var unsortedList =
364+ List .of (1 , Map .of ("z" , 26 , "y" , 25 ), Map .of ("b" , 26 , "c" , 25 , "a" , 24 ), List .of ("w" , "v" ));
365+
366+ var sortedListItems = SSABasedGenericKubernetesResourceMatcher .sortListItems (unsortedList );
244367 assertThat (sortedListItems ).element (0 ).isEqualTo (1 );
245368
246369 var sortedNestedMap1 = (Map <String , Object >) sortedListItems .get (1 );
@@ -252,7 +375,7 @@ void sortListItemsTest() {
252375
253376 private static <R > R loadResource (String fileName , Class <R > clazz ) {
254377 return ReconcilerUtils .loadYaml (
255- clazz , SSABasedGenericKubernetesResourceMatcherTest .class , fileName );
378+ clazz , SSABasedGenericKubernetesResourceMatcherTest .class , fileName );
256379 }
257380
258381 private static class ReadOnlyAwareMatcher <T extends HasMetadata >
0 commit comments