Skip to content

Commit f6f0183

Browse files
authored
feat: improve customizability of SSABasedGenericKubernetesResourceMatcher (#2757)
Signed-off-by: Mattis Bratland <[email protected]>
1 parent 82468be commit f6f0183

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcher.java

+23-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public boolean matches(R actual, R desired, Context<?> context) {
110110

111111
removeIrrelevantValues(desiredMap);
112112

113-
var matches = prunedActual.equals(desiredMap);
113+
var matches = matches(prunedActual, desiredMap, actual, desired, context);
114114
if (!matches && log.isDebugEnabled() && LoggingUtils.isNotSensitiveResource(desired)) {
115115
var diff = getDiff(prunedActual, desiredMap, objectMapper);
116116
log.debug(
@@ -125,6 +125,28 @@ public boolean matches(R actual, R desired, Context<?> context) {
125125
return matches;
126126
}
127127

128+
/**
129+
* Compares the desired and actual resources for equality.
130+
*
131+
* <p>This method can be overridden to implement custom matching logic. The {@code actualMap} is a
132+
* cleaned-up version of the actual resource with managed fields and irrelevant values removed.
133+
*
134+
* @param actualMap the actual resource represented as a map
135+
* @param desiredMap the desired resource represented as a map
136+
* @param actual the actual resource object
137+
* @param desired the desired resource object
138+
* @param context the current matching context
139+
* @return {@code true} if the resources are equal, otherwise {@code false}
140+
*/
141+
protected boolean matches(
142+
Map<String, Object> actualMap,
143+
Map<String, Object> desiredMap,
144+
R actual,
145+
R desired,
146+
Context<?> context) {
147+
return actualMap.equals(desiredMap);
148+
}
149+
128150
private String getDiff(
129151
Map<String, Object> prunedActualMap,
130152
Map<String, Object> desiredMap,

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcherTest.java

+31
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,37 @@ void testSanitizeState_daemonSetWithResources_withMismatch() {
236236
assertThat(matcher.matches(actualDaemonSet, desiredDaemonSet, mockedContext)).isFalse();
237237
}
238238

239+
@ParameterizedTest
240+
@ValueSource(booleans = {true, false})
241+
void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel(boolean readOnly) {
242+
var desiredConfigMap =
243+
loadResource("configmap.empty-owner-reference-desired.yaml", ConfigMap.class);
244+
desiredConfigMap.getData().put("key1", "another value");
245+
var actualConfigMap = loadResource("configmap.empty-owner-reference.yaml", ConfigMap.class);
246+
actualConfigMap.getMetadata().getLabels().put("readonly", Boolean.toString(readOnly));
247+
248+
var matcher = new ReadOnlyAwareMatcher<ConfigMap>();
249+
assertThat(matcher.matches(actualConfigMap, desiredConfigMap, mockedContext))
250+
.isEqualTo(readOnly);
251+
}
252+
253+
private static class ReadOnlyAwareMatcher<T extends HasMetadata>
254+
extends SSABasedGenericKubernetesResourceMatcher<T> {
255+
@Override
256+
protected boolean matches(
257+
Map<String, Object> actualMap,
258+
Map<String, Object> desiredMap,
259+
T actual,
260+
T desired,
261+
Context<?> context) {
262+
var readonly = actual.getMetadata().getLabels().get("readonly");
263+
if (readonly != null && readonly.equals("true")) {
264+
return true;
265+
}
266+
return actualMap.equals(desiredMap);
267+
}
268+
}
269+
239270
private static <R> R loadResource(String fileName, Class<R> clazz) {
240271
return ReconcilerUtils.loadYaml(
241272
clazz, SSABasedGenericKubernetesResourceMatcherTest.class, fileName);

0 commit comments

Comments
 (0)