Skip to content

Commit fd49f40

Browse files
authored
feat: use SSA matcher flag for child resources (#150)
Signed-off-by: Attila Mészáros <[email protected]>
1 parent c4955b0 commit fd49f40

File tree

8 files changed

+72
-13
lines changed

8 files changed

+72
-13
lines changed

docs/reference.md

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ It has several attributes:
4040
(Same as `reconcilePrecondition` in Java Operator SDK)
4141
- **`readyPostCondition`** - condition to check if the resource is considered to be ready. If a resource is ready all the resources, which depend on it
4242
can proceed in reconciliation.
43+
- **`matcher`** - Match resources with Java Operator SDK Server Side Apply based matcher (default `SSA`). Matching resources
44+
is makes the reconciliation much more efficient, since controller updates the resource only if truly changed. However,
45+
it is not possible to match resources because of some characteristics of Kubernetes API (default values, value conversions, etc)
46+
so you can always opt out the matching (use value `NONE`), and update the resource on every reconciliation.
4347

4448
#### Built-in conditions
4549

src/main/java/io/javaoperatorsdk/operator/glue/customresource/glue/DependentResourceSpec.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public class DependentResourceSpec {
2121

2222
private String resourceTemplate;
2323

24+
private Matcher matcher = Matcher.SSA;
25+
2426
private List<String> dependsOn = new ArrayList<>();
2527

2628
@PreserveUnknownFields
@@ -92,6 +94,14 @@ public void setClusterScoped(boolean clusterScoped) {
9294
this.clusterScoped = clusterScoped;
9395
}
9496

97+
public Matcher getMatcher() {
98+
return matcher;
99+
}
100+
101+
public void setMatcher(Matcher matcher) {
102+
this.matcher = matcher;
103+
}
104+
95105
@Override
96106
public boolean equals(Object o) {
97107
if (this == o)
@@ -101,15 +111,15 @@ public boolean equals(Object o) {
101111
DependentResourceSpec that = (DependentResourceSpec) o;
102112
return clusterScoped == that.clusterScoped && Objects.equals(name, that.name)
103113
&& Objects.equals(resource, that.resource)
104-
&& Objects.equals(resourceTemplate, that.resourceTemplate)
114+
&& Objects.equals(resourceTemplate, that.resourceTemplate) && matcher == that.matcher
105115
&& Objects.equals(dependsOn, that.dependsOn)
106116
&& Objects.equals(readyPostCondition, that.readyPostCondition)
107117
&& Objects.equals(condition, that.condition);
108118
}
109119

110120
@Override
111121
public int hashCode() {
112-
return Objects.hash(name, clusterScoped, resource, resourceTemplate, dependsOn,
122+
return Objects.hash(name, clusterScoped, resource, resourceTemplate, matcher, dependsOn,
113123
readyPostCondition, condition);
114124
}
115125
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.javaoperatorsdk.operator.glue.customresource.glue;
2+
3+
public enum Matcher {
4+
NONE, SSA
5+
}

src/main/java/io/javaoperatorsdk/operator/glue/dependent/GCGenericDependentResource.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33
import io.fabric8.kubernetes.api.model.GenericKubernetesResource;
44
import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected;
55
import io.javaoperatorsdk.operator.glue.customresource.glue.Glue;
6+
import io.javaoperatorsdk.operator.glue.customresource.glue.Matcher;
67
import io.javaoperatorsdk.operator.glue.templating.GenericTemplateHandler;
78

89
public class GCGenericDependentResource extends GenericDependentResource
910
implements GarbageCollected<Glue> {
1011

1112
public GCGenericDependentResource(GenericTemplateHandler genericTemplateHandler,
1213
GenericKubernetesResource desired, String name,
13-
boolean clusterScoped) {
14-
super(genericTemplateHandler, desired, name, clusterScoped);
14+
boolean clusterScoped, Matcher matcher) {
15+
super(genericTemplateHandler, desired, name, clusterScoped, matcher);
1516
}
1617

1718
public GCGenericDependentResource(GenericTemplateHandler genericTemplateHandler,
18-
String desiredTemplate, String name, boolean clusterScoped) {
19-
super(genericTemplateHandler, desiredTemplate, name, clusterScoped);
19+
String desiredTemplate, String name, boolean clusterScoped, Matcher matcher) {
20+
super(genericTemplateHandler, desiredTemplate, name, clusterScoped, matcher);
2021
}
2122
}

src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericDependentResource.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
77
import io.javaoperatorsdk.operator.glue.Utils;
88
import io.javaoperatorsdk.operator.glue.customresource.glue.Glue;
9+
import io.javaoperatorsdk.operator.glue.customresource.glue.Matcher;
910
import io.javaoperatorsdk.operator.glue.reconciler.glue.GlueReconciler;
1011
import io.javaoperatorsdk.operator.glue.templating.GenericTemplateHandler;
1112
import io.javaoperatorsdk.operator.processing.GroupVersionKind;
@@ -23,28 +24,31 @@ public class GenericDependentResource
2324
private final String desiredTemplate;
2425
private final String name;
2526
private final boolean clusterScoped;
27+
private final Matcher matcher;
2628

2729
// optimize share between instances
2830
private final GenericTemplateHandler genericTemplateHandler;
2931

3032
public GenericDependentResource(GenericTemplateHandler genericTemplateHandler,
3133
GenericKubernetesResource desired, String name,
32-
boolean clusterScoped) {
34+
boolean clusterScoped, Matcher matcher) {
3335
super(new GroupVersionKind(desired.getApiVersion(), desired.getKind()));
3436
this.desired = desired;
37+
this.matcher = matcher;
3538
this.desiredTemplate = null;
3639
this.name = name;
3740
this.clusterScoped = clusterScoped;
3841
this.genericTemplateHandler = genericTemplateHandler;
3942
}
4043

4144
public GenericDependentResource(GenericTemplateHandler genericTemplateHandler,
42-
String desiredTemplate, String name, boolean clusterScoped) {
45+
String desiredTemplate, String name, boolean clusterScoped, Matcher matcher) {
4346
super(new GroupVersionKind(Utils.getApiVersionFromTemplate(desiredTemplate),
4447
Utils.getKindFromTemplate(desiredTemplate)));
4548
this.genericTemplateHandler = genericTemplateHandler;
4649
this.name = name;
4750
this.desiredTemplate = desiredTemplate;
51+
this.matcher = matcher;
4852
this.desired = null;
4953
this.clusterScoped = clusterScoped;
5054
}
@@ -75,6 +79,10 @@ public Result<GenericKubernetesResource> match(GenericKubernetesResource actualR
7579
&& actualResource.getApiVersion().equals("apps/v1")) {
7680
return super.match(actualResource, primary, context);
7781
}
78-
return Result.nonComputed(false);
82+
if (Matcher.SSA.equals(matcher)) {
83+
return super.match(actualResource, primary, context);
84+
} else {
85+
return Result.nonComputed(false);
86+
}
7987
}
8088
}

src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,17 @@ private GenericDependentResource createDependentResource(DependentResourceSpec s
211211
return spec.getResourceTemplate() != null
212212
? new GCGenericDependentResource(genericTemplateHandler, spec.getResourceTemplate(),
213213
spec.getName(),
214-
spec.isClusterScoped())
214+
spec.isClusterScoped(), spec.getMatcher())
215215
: new GCGenericDependentResource(genericTemplateHandler, spec.getResource(),
216216
spec.getName(),
217-
spec.isClusterScoped());
217+
spec.isClusterScoped(), spec.getMatcher());
218218
} else {
219219
return spec.getResourceTemplate() != null
220220
? new GenericDependentResource(genericTemplateHandler,
221-
spec.getResourceTemplate(), spec.getName(), spec.isClusterScoped())
221+
spec.getResourceTemplate(), spec.getName(), spec.isClusterScoped(),
222+
spec.getMatcher())
222223
: new GenericDependentResource(genericTemplateHandler,
223-
spec.getResource(), spec.getName(), spec.isClusterScoped());
224+
spec.getResource(), spec.getName(), spec.isClusterScoped(), spec.getMatcher());
224225
}
225226
}
226227

src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler;
2323
import io.quarkus.test.junit.QuarkusTest;
2424

25+
import static io.javaoperatorsdk.operator.glue.TestUtils.INITIAL_RECONCILE_WAIT_TIMEOUT;
2526
import static org.assertj.core.api.Assertions.assertThat;
2627
import static org.awaitility.Awaitility.await;
2728

@@ -354,6 +355,19 @@ void pathRelatedResourceStatus(String glueFileName) {
354355
});
355356
}
356357

358+
@Test
359+
void customizeMatcher() {
360+
var glue = createGlue("/glue/SimpleNotUseSSA.yaml");
361+
362+
await().pollDelay(INITIAL_RECONCILE_WAIT_TIMEOUT).untilAsserted(() -> {
363+
assertThat(get(ConfigMap.class, "simple-glue-no-ssa-configmap")).isNotNull();
364+
});
365+
delete(glue);
366+
await().pollDelay(INITIAL_RECONCILE_WAIT_TIMEOUT).untilAsserted(() -> {
367+
assertThat(get(ConfigMap.class, "simple-glue-no-ssa-configmap")).isNull();
368+
});
369+
}
370+
357371
private List<Glue> testWorkflowList(int num) {
358372
List<Glue> res = new ArrayList<>();
359373
IntStream.range(0, num).forEach(index -> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Invalid GLUE, presents resources with non-unique name
2+
apiVersion: io.javaoperatorsdk.operator.glue/v1beta1
3+
kind: Glue
4+
metadata:
5+
name: simple-glue-no-ssa
6+
spec:
7+
childResources:
8+
- name: configMap
9+
matcher: NONE
10+
resource:
11+
apiVersion: v1
12+
kind: ConfigMap
13+
metadata:
14+
name: simple-glue-no-ssa-configmap
15+
data:
16+
key: "value1"

0 commit comments

Comments
 (0)