@@ -41,6 +41,10 @@ public class SSABasedGenericKubernetesResourceMatcher<R extends HasMetadata> {
41
41
public static final String APPLY_OPERATION = "Apply" ;
42
42
public static final String DOT_KEY = "." ;
43
43
44
+ private static final List <String > IGNORED_METADATA =
45
+ Arrays .asList ("creationTimestamp" , "deletionTimestamp" ,
46
+ "generation" , "selfLink" , "uid" );
47
+
44
48
@ SuppressWarnings ("unchecked" )
45
49
public static <L extends HasMetadata > SSABasedGenericKubernetesResourceMatcher <L > getInstance () {
46
50
return INSTANCE ;
@@ -58,11 +62,10 @@ public static <L extends HasMetadata> SSABasedGenericKubernetesResourceMatcher<L
58
62
private static final Logger log =
59
63
LoggerFactory .getLogger (SSABasedGenericKubernetesResourceMatcher .class );
60
64
61
-
62
65
@ SuppressWarnings ("unchecked" )
63
66
public boolean matches (R actual , R desired , Context <?> context ) {
64
- var optionalManagedFieldsEntry =
65
- checkIfFieldManagerExists ( actual , context .getControllerConfiguration ().fieldManager ());
67
+ var optionalManagedFieldsEntry = checkIfFieldManagerExists ( actual ,
68
+ context .getControllerConfiguration ().fieldManager ());
66
69
// If no field is managed by our controller, that means the controller hasn't touched the
67
70
// resource yet and the resource probably doesn't match the desired state. Not matching here
68
71
// means that the resource will need to be updated and since this will be done using SSA, the
@@ -86,7 +89,8 @@ public boolean matches(R actual, R desired, Context<?> context) {
86
89
87
90
var prunedActual = new HashMap <String , Object >(actualMap .size ());
88
91
keepOnlyManagedFields (prunedActual , actualMap ,
89
- managedFieldsEntry .getFieldsV1 ().getAdditionalProperties (), objectMapper );
92
+ managedFieldsEntry .getFieldsV1 ().getAdditionalProperties (),
93
+ objectMapper );
90
94
91
95
removeIrrelevantValues (desiredMap );
92
96
@@ -110,9 +114,8 @@ private void sanitizeState(R actual, R desired, Map<String, Object> actualMap) {
110
114
for (int i = 0 ; i < claims ; i ++) {
111
115
if (desiredStatefulSet .getSpec ().getVolumeClaimTemplates ().get (i ).getSpec ()
112
116
.getVolumeMode () == null ) {
113
- Optional
114
- .ofNullable (GenericKubernetesResource .get (actualMap , "spec" , "volumeClaimTemplates" ,
115
- i , "spec" ))
117
+ Optional .ofNullable (
118
+ GenericKubernetesResource .get (actualMap , "spec" , "volumeClaimTemplates" , i , "spec" ))
116
119
.map (Map .class ::cast ).ifPresent (m -> m .remove ("volumeMode" ));
117
120
}
118
121
if (desiredStatefulSet .getSpec ().getVolumeClaimTemplates ().get (i ).getStatus () == null ) {
@@ -131,6 +134,7 @@ private static void removeIrrelevantValues(Map<String, Object> desiredMap) {
131
134
var metadata = (Map <String , Object >) desiredMap .get (METADATA_KEY );
132
135
metadata .remove (NAME_KEY );
133
136
metadata .remove (NAMESPACE_KEY );
137
+ IGNORED_METADATA .forEach (metadata ::remove );
134
138
if (metadata .isEmpty ()) {
135
139
desiredMap .remove (METADATA_KEY );
136
140
}
@@ -163,7 +167,8 @@ private static void keepOnlyManagedFields(Map<String, Object> result,
163
167
} else {
164
168
// basically if we should traverse further
165
169
fillResultsAndTraverseFurther (result , actualMap , managedFields , objectMapper , key ,
166
- keyInActual , managedFieldValue );
170
+ keyInActual ,
171
+ managedFieldValue );
167
172
}
168
173
} else {
169
174
// this should handle the case when the value is complex in the actual map (not just a
@@ -181,8 +186,9 @@ private static void keepOnlyManagedFields(Map<String, Object> result,
181
186
182
187
@ SuppressWarnings ("unchecked" )
183
188
private static void fillResultsAndTraverseFurther (Map <String , Object > result ,
184
- Map <String , Object > actualMap , Map <String , Object > managedFields ,
185
- KubernetesSerialization objectMapper , String key , String keyInActual ,
189
+ Map <String , Object > actualMap ,
190
+ Map <String , Object > managedFields , KubernetesSerialization objectMapper , String key ,
191
+ String keyInActual ,
186
192
Object managedFieldValue ) {
187
193
var emptyMapValue = new HashMap <String , Object >();
188
194
result .put (keyInActual , emptyMapValue );
@@ -223,8 +229,9 @@ private static void handleListKeyEntrySet(Map<String, Object> result,
223
229
if (DOT_KEY .equals (listEntry .getKey ())) {
224
230
continue ;
225
231
}
226
- var actualListEntry = selectListEntryBasedOnKey (keyWithoutPrefix (listEntry .getKey ()),
227
- actualValueList , objectMapper );
232
+ var actualListEntry =
233
+ selectListEntryBasedOnKey (keyWithoutPrefix (listEntry .getKey ()), actualValueList ,
234
+ objectMapper );
228
235
targetValuesByIndex .put (actualListEntry .getKey (), actualListEntry .getValue ());
229
236
managedEntryByIndex .put (actualListEntry .getKey (), (Map <String , Object >) listEntry .getValue ());
230
237
}
@@ -301,8 +308,7 @@ private static boolean isKeyPrefixedSkippingDotKey(Set<Map.Entry<String, Object>
301
308
@ SuppressWarnings ("unchecked" )
302
309
private static java .util .Map .Entry <Integer , Map <String , Object >> selectListEntryBasedOnKey (
303
310
String key ,
304
- List <Map <String , Object >> values ,
305
- KubernetesSerialization objectMapper ) {
311
+ List <Map <String , Object >> values , KubernetesSerialization objectMapper ) {
306
312
Map <String , Object > ids = objectMapper .unmarshal (key , Map .class );
307
313
List <Map <String , Object >> possibleTargets = new ArrayList <>(1 );
308
314
int index = -1 ;
@@ -314,9 +320,8 @@ private static java.util.Map.Entry<Integer, Map<String, Object>> selectListEntry
314
320
}
315
321
}
316
322
if (possibleTargets .isEmpty ()) {
317
- throw new IllegalStateException (
318
- "Cannot find list element for key:" + key + ", in map: "
319
- + values .stream ().map (Map ::keySet ).collect (Collectors .toList ()));
323
+ throw new IllegalStateException ("Cannot find list element for key:" + key + ", in map: "
324
+ + values .stream ().map (Map ::keySet ).collect (Collectors .toList ()));
320
325
}
321
326
if (possibleTargets .size () > 1 ) {
322
327
throw new IllegalStateException (
@@ -327,7 +332,6 @@ private static java.util.Map.Entry<Integer, Map<String, Object>> selectListEntry
327
332
return new AbstractMap .SimpleEntry <>(finalIndex , possibleTargets .get (0 ));
328
333
}
329
334
330
-
331
335
private Optional <ManagedFieldsEntry > checkIfFieldManagerExists (R actual , String fieldManager ) {
332
336
var targetManagedFields = actual .getMetadata ().getManagedFields ().stream ()
333
337
// Only the apply operations are interesting for us since those were created properly be SSA
@@ -338,14 +342,14 @@ private Optional<ManagedFieldsEntry> checkIfFieldManagerExists(R actual, String
338
342
.collect (Collectors .toList ());
339
343
if (targetManagedFields .isEmpty ()) {
340
344
log .debug ("No field manager exists for resource {} with name: {} and operation Apply " ,
341
- actual .getKind (), actual .getMetadata ().getName ());
345
+ actual .getKind (),
346
+ actual .getMetadata ().getName ());
342
347
return Optional .empty ();
343
348
}
344
349
// this should not happen in theory
345
350
if (targetManagedFields .size () > 1 ) {
346
- throw new OperatorException (
347
- "More than one field manager exists with name: " + fieldManager + "in resource: " +
348
- actual .getKind () + " with name: " + actual .getMetadata ().getName ());
351
+ throw new OperatorException ("More than one field manager exists with name: " + fieldManager
352
+ + "in resource: " + actual .getKind () + " with name: " + actual .getMetadata ().getName ());
349
353
}
350
354
return Optional .of (targetManagedFields .get (0 ));
351
355
}
0 commit comments