7
7
import org .slf4j .Logger ;
8
8
import org .slf4j .LoggerFactory ;
9
9
10
+ import io .fabric8 .kubernetes .api .model .GenericKubernetesResource ;
10
11
import io .fabric8 .kubernetes .api .model .HasMetadata ;
11
12
import io .fabric8 .kubernetes .api .model .ManagedFieldsEntry ;
13
+ import io .fabric8 .kubernetes .api .model .apps .StatefulSet ;
12
14
import io .fabric8 .kubernetes .client .utils .KubernetesSerialization ;
13
15
import io .javaoperatorsdk .operator .OperatorException ;
14
16
import io .javaoperatorsdk .operator .api .reconciler .Context ;
@@ -74,6 +76,9 @@ public boolean matches(R actual, R desired, Context<?> context) {
74
76
var objectMapper = context .getClient ().getKubernetesSerialization ();
75
77
76
78
var actualMap = objectMapper .convertValue (actual , Map .class );
79
+
80
+ sanitizeState (actual , desired , actualMap );
81
+
77
82
var desiredMap = objectMapper .convertValue (desired , Map .class );
78
83
if (LoggingUtils .isNotSensitiveResource (desired )) {
79
84
log .trace ("Original actual: \n {} \n original desired: \n {} " , actual , desiredMap );
@@ -92,6 +97,33 @@ public boolean matches(R actual, R desired, Context<?> context) {
92
97
return prunedActual .equals (desiredMap );
93
98
}
94
99
100
+ /**
101
+ * Correct for known issue with SSA
102
+ */
103
+ @ SuppressWarnings ("unchecked" )
104
+ private void sanitizeState (R actual , R desired , Map <String , Object > actualMap ) {
105
+ if (desired instanceof StatefulSet ) {
106
+ StatefulSet desiredStatefulSet = (StatefulSet ) desired ;
107
+ StatefulSet actualStatefulSet = (StatefulSet ) actual ;
108
+ int claims = desiredStatefulSet .getSpec ().getVolumeClaimTemplates ().size ();
109
+ if (claims == actualStatefulSet .getSpec ().getVolumeClaimTemplates ().size ()) {
110
+ for (int i = 0 ; i < claims ; i ++) {
111
+ if (desiredStatefulSet .getSpec ().getVolumeClaimTemplates ().get (i ).getSpec ()
112
+ .getVolumeMode () == null ) {
113
+ Optional
114
+ .ofNullable (GenericKubernetesResource .get (actualMap , "spec" , "volumeClaimTemplates" ,
115
+ i , "spec" ))
116
+ .map (Map .class ::cast ).ifPresent (m -> m .remove ("volumeMode" ));
117
+ }
118
+ Optional
119
+ .ofNullable (
120
+ GenericKubernetesResource .get (actualMap , "spec" , "volumeClaimTemplates" , i ))
121
+ .map (Map .class ::cast ).ifPresent (m -> m .remove ("status" ));
122
+ }
123
+ }
124
+ }
125
+ }
126
+
95
127
@ SuppressWarnings ("unchecked" )
96
128
private static void removeIrrelevantValues (Map <String , Object > desiredMap ) {
97
129
var metadata = (Map <String , Object >) desiredMap .get (METADATA_KEY );
@@ -153,8 +185,7 @@ private static void fillResultsAndTraverseFurther(Map<String, Object> result,
153
185
var emptyMapValue = new HashMap <String , Object >();
154
186
result .put (keyInActual , emptyMapValue );
155
187
var actualMapValue = actualMap .getOrDefault (keyInActual , Collections .emptyMap ());
156
- log .debug ("key: {} actual map value: {} managedFieldValue: {}" , keyInActual ,
157
- actualMapValue , managedFieldValue );
188
+ log .debug ("key: {} actual map value: managedFieldValue: {}" , keyInActual , managedFieldValue );
158
189
159
190
keepOnlyManagedFields (emptyMapValue , (Map <String , Object >) actualMapValue ,
160
191
(Map <String , Object >) managedFields .get (key ), objectMapper );
@@ -282,29 +313,16 @@ private static java.util.Map.Entry<Integer, Map<String, Object>> selectListEntry
282
313
}
283
314
if (possibleTargets .isEmpty ()) {
284
315
throw new IllegalStateException (
285
- "Cannot find list element for key:" + key + ", in map: " + values );
316
+ "Cannot find list element for key:" + key + ", in map: "
317
+ + values .stream ().map (Map ::keySet ).collect (Collectors .toList ()));
286
318
}
287
319
if (possibleTargets .size () > 1 ) {
288
320
throw new IllegalStateException (
289
- "More targets found in list element for key:" + key + ", in map: " + values );
321
+ "More targets found in list element for key:" + key + ", in map: "
322
+ + values .stream ().map (Map ::keySet ).collect (Collectors .toList ()));
290
323
}
291
324
final var finalIndex = index ;
292
- return new Map .Entry <>() {
293
- @ Override
294
- public Integer getKey () {
295
- return finalIndex ;
296
- }
297
-
298
- @ Override
299
- public Map <String , Object > getValue () {
300
- return possibleTargets .get (0 );
301
- }
302
-
303
- @ Override
304
- public Map <String , Object > setValue (Map <String , Object > stringObjectMap ) {
305
- throw new IllegalStateException ("should not be called" );
306
- }
307
- };
325
+ return new AbstractMap .SimpleEntry <>(finalIndex , possibleTargets .get (0 ));
308
326
}
309
327
310
328
@@ -318,14 +336,14 @@ private Optional<ManagedFieldsEntry> checkIfFieldManagerExists(R actual, String
318
336
.collect (Collectors .toList ());
319
337
if (targetManagedFields .isEmpty ()) {
320
338
log .debug ("No field manager exists for resource {} with name: {} and operation Apply " ,
321
- actual , actual .getMetadata ().getName ());
339
+ actual . getKind () , actual .getMetadata ().getName ());
322
340
return Optional .empty ();
323
341
}
324
342
// this should not happen in theory
325
343
if (targetManagedFields .size () > 1 ) {
326
344
throw new OperatorException (
327
345
"More than one field manager exists with name: " + fieldManager + "in resource: " +
328
- actual + " with name: " + actual .getMetadata ().getName ());
346
+ actual . getKind () + " with name: " + actual .getMetadata ().getName ());
329
347
}
330
348
return Optional .of (targetManagedFields .get (0 ));
331
349
}
0 commit comments