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,35 @@ 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
+ if (desiredStatefulSet .getSpec ().getVolumeClaimTemplates ().get (i ).getStatus () == null ) {
119
+ Optional
120
+ .ofNullable (
121
+ GenericKubernetesResource .get (actualMap , "spec" , "volumeClaimTemplates" , i ))
122
+ .map (Map .class ::cast ).ifPresent (m -> m .remove ("status" ));
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+
95
129
@ SuppressWarnings ("unchecked" )
96
130
private static void removeIrrelevantValues (Map <String , Object > desiredMap ) {
97
131
var metadata = (Map <String , Object >) desiredMap .get (METADATA_KEY );
@@ -153,8 +187,7 @@ private static void fillResultsAndTraverseFurther(Map<String, Object> result,
153
187
var emptyMapValue = new HashMap <String , Object >();
154
188
result .put (keyInActual , emptyMapValue );
155
189
var actualMapValue = actualMap .getOrDefault (keyInActual , Collections .emptyMap ());
156
- log .debug ("key: {} actual map value: {} managedFieldValue: {}" , keyInActual ,
157
- actualMapValue , managedFieldValue );
190
+ log .debug ("key: {} actual map value: managedFieldValue: {}" , keyInActual , managedFieldValue );
158
191
159
192
keepOnlyManagedFields (emptyMapValue , (Map <String , Object >) actualMapValue ,
160
193
(Map <String , Object >) managedFields .get (key ), objectMapper );
@@ -282,29 +315,16 @@ private static java.util.Map.Entry<Integer, Map<String, Object>> selectListEntry
282
315
}
283
316
if (possibleTargets .isEmpty ()) {
284
317
throw new IllegalStateException (
285
- "Cannot find list element for key:" + key + ", in map: " + values );
318
+ "Cannot find list element for key:" + key + ", in map: "
319
+ + values .stream ().map (Map ::keySet ).collect (Collectors .toList ()));
286
320
}
287
321
if (possibleTargets .size () > 1 ) {
288
322
throw new IllegalStateException (
289
- "More targets found in list element for key:" + key + ", in map: " + values );
323
+ "More targets found in list element for key:" + key + ", in map: "
324
+ + values .stream ().map (Map ::keySet ).collect (Collectors .toList ()));
290
325
}
291
326
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
- };
327
+ return new AbstractMap .SimpleEntry <>(finalIndex , possibleTargets .get (0 ));
308
328
}
309
329
310
330
@@ -318,14 +338,14 @@ private Optional<ManagedFieldsEntry> checkIfFieldManagerExists(R actual, String
318
338
.collect (Collectors .toList ());
319
339
if (targetManagedFields .isEmpty ()) {
320
340
log .debug ("No field manager exists for resource {} with name: {} and operation Apply " ,
321
- actual , actual .getMetadata ().getName ());
341
+ actual . getKind () , actual .getMetadata ().getName ());
322
342
return Optional .empty ();
323
343
}
324
344
// this should not happen in theory
325
345
if (targetManagedFields .size () > 1 ) {
326
346
throw new OperatorException (
327
347
"More than one field manager exists with name: " + fieldManager + "in resource: " +
328
- actual + " with name: " + actual .getMetadata ().getName ());
348
+ actual . getKind () + " with name: " + actual .getMetadata ().getName ());
329
349
}
330
350
return Optional .of (targetManagedFields .get (0 ));
331
351
}
0 commit comments