Skip to content

Commit b156052

Browse files
authored
feat: use processors for matching as well since usually both are related (#1911)
1 parent 50f3b43 commit b156052

12 files changed

+130
-39
lines changed

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

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@
22

33
import java.util.Objects;
44

5-
import io.fabric8.kubernetes.api.model.ConfigMap;
65
import io.fabric8.kubernetes.api.model.HasMetadata;
7-
import io.fabric8.kubernetes.api.model.Secret;
8-
import io.fabric8.zjsonpatch.JsonDiff;
9-
import io.javaoperatorsdk.operator.ReconcilerUtils;
10-
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
116
import io.javaoperatorsdk.operator.api.reconciler.Context;
127
import io.javaoperatorsdk.operator.processing.dependent.Matcher;
8+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors.GenericResourceUpdatePreProcessor;
139

1410
public class GenericKubernetesResourceMatcher<R extends HasMetadata, P extends HasMetadata>
1511
implements Matcher<R, P> {
@@ -22,7 +18,7 @@ private GenericKubernetesResourceMatcher(KubernetesDependentResource<R, P> depen
2218

2319
@SuppressWarnings({"unchecked", "rawtypes"})
2420
static <R extends HasMetadata, P extends HasMetadata> Matcher<R, P> matcherFor(
25-
Class<R> resourceType, KubernetesDependentResource<R, P> dependentResource) {
21+
KubernetesDependentResource<R, P> dependentResource) {
2622
return new GenericKubernetesResourceMatcher(dependentResource);
2723
}
2824

@@ -61,6 +57,7 @@ public static <R extends HasMetadata> Result<R> match(R desired, R actualResourc
6157
* @return results of matching
6258
* @param <R> resource
6359
*/
60+
@SuppressWarnings("unchecked")
6461
public static <R extends HasMetadata> Result<R> match(R desired, R actualResource,
6562
boolean considerMetadata, boolean equality) {
6663
if (considerMetadata) {
@@ -74,36 +71,10 @@ public static <R extends HasMetadata> Result<R> match(R desired, R actualResourc
7471
}
7572
}
7673

77-
if (desired instanceof ConfigMap) {
78-
return Result.computed(
79-
ResourceComparators.compareConfigMapData((ConfigMap) desired, (ConfigMap) actualResource),
80-
desired);
81-
} else if (desired instanceof Secret) {
82-
return Result.computed(
83-
ResourceComparators.compareSecretData((Secret) desired, (Secret) actualResource),
84-
desired);
85-
} else {
86-
final var objectMapper = ConfigurationServiceProvider.instance().getObjectMapper();
87-
88-
// reflection will be replaced by this:
89-
// https://github.com/fabric8io/kubernetes-client/issues/3816
90-
var desiredSpecNode = objectMapper.valueToTree(ReconcilerUtils.getSpec(desired));
91-
var actualSpecNode = objectMapper.valueToTree(ReconcilerUtils.getSpec(actualResource));
92-
var diffJsonPatch = JsonDiff.asJson(desiredSpecNode, actualSpecNode);
93-
// In case of equality is set to true, no diffs are allowed, so we return early if diffs exist
94-
// On contrary (if equality is false), "add" is allowed for cases when for some
95-
// resources Kubernetes fills-in values into spec.
96-
if (equality && diffJsonPatch.size() > 0) {
97-
return Result.computed(false, desired);
98-
}
99-
for (int i = 0; i < diffJsonPatch.size(); i++) {
100-
String operation = diffJsonPatch.get(i).get("op").asText();
101-
if (!operation.equals("add")) {
102-
return Result.computed(false, desired);
103-
}
104-
}
105-
return Result.computed(true, desired);
106-
}
74+
final ResourceUpdatePreProcessor<R> processor =
75+
GenericResourceUpdatePreProcessor.processorFor((Class<R>) desired.getClass());
76+
final var matched = processor.matches(actualResource, desired, equality);
77+
return Result.computed(matched, desired);
10778
}
10879

10980
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public abstract class KubernetesDependentResource<R extends HasMetadata, P exten
5050
public KubernetesDependentResource(Class<R> resourceType) {
5151
super(resourceType);
5252
matcher = this instanceof Matcher ? (Matcher<R, P>) this
53-
: GenericKubernetesResourceMatcher.matcherFor(resourceType, this);
53+
: GenericKubernetesResourceMatcher.matcherFor(this);
5454

5555
processor = this instanceof ResourceUpdatePreProcessor
5656
? (ResourceUpdatePreProcessor<R>) this

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66
public interface ResourceUpdatePreProcessor<R extends HasMetadata> {
77

88
R replaceSpecOnActual(R actual, R desired, Context<?> context);
9+
10+
boolean matches(R actual, R desired, boolean equality);
911
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding;
46

57
public class ClusterRoleBindingResourceUpdatePreProcessor
@@ -10,4 +12,10 @@ protected void updateClonedActual(ClusterRoleBinding actual, ClusterRoleBinding
1012
actual.setRoleRef(desired.getRoleRef());
1113
actual.setSubjects(desired.getSubjects());
1214
}
15+
16+
@Override
17+
public boolean matches(ClusterRoleBinding actual, ClusterRoleBinding desired, boolean equality) {
18+
return Objects.equals(actual.getRoleRef(), desired.getRoleRef()) &&
19+
Objects.equals(actual.getSubjects(), desired.getSubjects());
20+
}
1321
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.rbac.ClusterRole;
46

57
public class ClusterRoleResourceUpdatePreProcessor
@@ -10,4 +12,10 @@ protected void updateClonedActual(ClusterRole actual, ClusterRole desired) {
1012
actual.setAggregationRule(desired.getAggregationRule());
1113
actual.setRules(desired.getRules());
1214
}
15+
16+
@Override
17+
public boolean matches(ClusterRole actual, ClusterRole desired, boolean equality) {
18+
return Objects.equals(actual.getRules(), desired.getRules()) &&
19+
Objects.equals(actual.getAggregationRule(), desired.getAggregationRule());
20+
}
1321
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.ConfigMap;
46

57
public class ConfigMapResourceUpdatePreProcessor
@@ -11,4 +13,11 @@ protected void updateClonedActual(ConfigMap actual, ConfigMap desired) {
1113
actual.setBinaryData((desired.getBinaryData()));
1214
actual.setImmutable(desired.getImmutable());
1315
}
16+
17+
@Override
18+
public boolean matches(ConfigMap actual, ConfigMap desired, boolean equality) {
19+
return Objects.equals(actual.getImmutable(), desired.getImmutable()) &&
20+
Objects.equals(actual.getData(), desired.getData()) &&
21+
Objects.equals(actual.getBinaryData(), desired.getBinaryData());
22+
}
1423
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.fabric8.kubernetes.api.model.rbac.ClusterRole;
1212
import io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding;
1313
import io.fabric8.kubernetes.api.model.rbac.RoleBinding;
14+
import io.fabric8.zjsonpatch.JsonDiff;
1415
import io.javaoperatorsdk.operator.ReconcilerUtils;
1516
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
1617
import io.javaoperatorsdk.operator.api.reconciler.Context;
@@ -50,4 +51,29 @@ protected void updateClonedActual(R actual, R desired) {
5051
var desiredSpec = ReconcilerUtils.getSpec(desired);
5152
ReconcilerUtils.setSpec(actual, desiredSpec);
5253
}
54+
55+
@Override
56+
public boolean matches(R actual, R desired, boolean equality) {
57+
final var objectMapper = ConfigurationServiceProvider.instance().getObjectMapper();
58+
59+
// reflection will be replaced by this:
60+
// https://github.com/fabric8io/kubernetes-client/issues/3816
61+
var desiredSpecNode = objectMapper.valueToTree(ReconcilerUtils.getSpec(desired));
62+
var actualSpecNode = objectMapper.valueToTree(ReconcilerUtils.getSpec(actual));
63+
var diffJsonPatch = JsonDiff.asJson(desiredSpecNode, actualSpecNode);
64+
// In case of equality is set to true, no diffs are allowed, so we return early if diffs exist
65+
// On contrary (if equality is false), "add" is allowed for cases when for some
66+
// resources Kubernetes fills-in values into spec.
67+
final var diffNumber = diffJsonPatch.size();
68+
if (equality && diffNumber > 0) {
69+
return false;
70+
}
71+
for (int i = 0; i < diffNumber; i++) {
72+
String operation = diffJsonPatch.get(i).get("op").asText();
73+
if (!operation.equals("add")) {
74+
return false;
75+
}
76+
}
77+
return true;
78+
}
5379
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.rbac.RoleBinding;
46

57
public class RoleBindingResourceUpdatePreProcessor
@@ -10,4 +12,10 @@ protected void updateClonedActual(RoleBinding actual, RoleBinding desired) {
1012
actual.setRoleRef(desired.getRoleRef());
1113
actual.setSubjects(desired.getSubjects());
1214
}
15+
16+
@Override
17+
public boolean matches(RoleBinding actual, RoleBinding desired, boolean equality) {
18+
return Objects.equals(actual.getRoleRef(), desired.getRoleRef()) &&
19+
Objects.equals(actual.getSubjects(), desired.getSubjects());
20+
}
1321
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.rbac.Role;
46

57
public class RoleResourceUpdatePreProcessor extends GenericResourceUpdatePreProcessor<Role> {
@@ -8,4 +10,9 @@ public class RoleResourceUpdatePreProcessor extends GenericResourceUpdatePreProc
810
protected void updateClonedActual(Role actual, Role desired) {
911
actual.setRules(desired.getRules());
1012
}
13+
14+
@Override
15+
public boolean matches(Role actual, Role desired, boolean equality) {
16+
return Objects.equals(actual.getRules(), desired.getRules());
17+
}
1118
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.Secret;
46

57
public class SecretResourceUpdatePreProcessor extends GenericResourceUpdatePreProcessor<Secret> {
@@ -11,4 +13,12 @@ protected void updateClonedActual(Secret actual, Secret desired) {
1113
actual.setImmutable(desired.getImmutable());
1214
actual.setType(desired.getType());
1315
}
16+
17+
@Override
18+
public boolean matches(Secret actual, Secret desired, boolean equality) {
19+
return Objects.equals(actual.getImmutable(), desired.getImmutable()) &&
20+
Objects.equals(actual.getType(), desired.getType()) &&
21+
Objects.equals(actual.getData(), desired.getData()) &&
22+
Objects.equals(actual.getStringData(), desired.getStringData());
23+
}
1424
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent.kubernetes.processors;
22

3+
import java.util.Objects;
4+
35
import io.fabric8.kubernetes.api.model.ServiceAccount;
46

57
public class ServiceAccountResourceUpdateProcessor
@@ -11,4 +13,12 @@ protected void updateClonedActual(ServiceAccount actual, ServiceAccount desired)
1113
actual.setImagePullSecrets(desired.getImagePullSecrets());
1214
actual.setSecrets(desired.getSecrets());
1315
}
16+
17+
@Override
18+
public boolean matches(ServiceAccount actual, ServiceAccount desired, boolean equality) {
19+
return Objects.equals(actual.getAutomountServiceAccountToken(),
20+
desired.getAutomountServiceAccountToken()) &&
21+
Objects.equals(actual.getImagePullSecrets(), desired.getImagePullSecrets()) &&
22+
Objects.equals(actual.getSecrets(), desired.getSecrets());
23+
}
1424
}

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import org.junit.jupiter.api.Test;
77

88
import io.fabric8.kubernetes.api.model.HasMetadata;
9+
import io.fabric8.kubernetes.api.model.ServiceAccount;
10+
import io.fabric8.kubernetes.api.model.ServiceAccountBuilder;
911
import io.fabric8.kubernetes.api.model.apps.Deployment;
1012
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
1113
import io.javaoperatorsdk.operator.ReconcilerUtils;
@@ -32,8 +34,7 @@ void checksIfDesiredValuesAreTheSame() {
3234
var actual = createDeployment();
3335
final var desired = createDeployment();
3436
final var dependentResource = new TestDependentResource(desired);
35-
final var matcher =
36-
GenericKubernetesResourceMatcher.matcherFor(Deployment.class, dependentResource);
37+
final var matcher = GenericKubernetesResourceMatcher.matcherFor(dependentResource);
3738
assertThat(matcher.match(actual, null, context).matched()).isTrue();
3839
assertThat(matcher.match(actual, null, context).computedDesired().isPresent()).isTrue();
3940
assertThat(matcher.match(actual, null, context).computedDesired().get()).isEqualTo(desired);
@@ -75,6 +76,19 @@ void checksIfDesiredValuesAreTheSame() {
7576
.isFalse();
7677
}
7778

79+
@Test
80+
void checkServiceAccount() {
81+
final var serviceAccountDR = new ServiceAccountDR();
82+
83+
final var desired = serviceAccountDR.desired(null, context);
84+
var actual = new ServiceAccountBuilder(desired)
85+
.addNewImagePullSecret("imagePullSecret3")
86+
.build();
87+
88+
final var matcher = GenericKubernetesResourceMatcher.matcherFor(serviceAccountDR);
89+
assertThat(matcher.match(actual, null, context).matched()).isFalse();
90+
}
91+
7892
Deployment createDeployment() {
7993
return ReconcilerUtils.loadYaml(
8094
Deployment.class, GenericKubernetesResourceMatcherTest.class, "nginx-deployment.yaml");
@@ -88,6 +102,24 @@ HasMetadata createPrimary(String caseName) {
88102
.build();
89103
}
90104

105+
private static class ServiceAccountDR
106+
extends KubernetesDependentResource<ServiceAccount, HasMetadata> {
107+
108+
public ServiceAccountDR() {
109+
super(ServiceAccount.class);
110+
}
111+
112+
@Override
113+
protected ServiceAccount desired(HasMetadata primary, Context<HasMetadata> context) {
114+
return new ServiceAccountBuilder()
115+
.withNewMetadata().withName("foo").endMetadata()
116+
.withAutomountServiceAccountToken()
117+
.addNewImagePullSecret("imagePullSecret1")
118+
.addNewImagePullSecret("imagePullSecret2")
119+
.build();
120+
}
121+
}
122+
91123
private class TestDependentResource extends KubernetesDependentResource<Deployment, HasMetadata> {
92124

93125
private final Deployment desired;

0 commit comments

Comments
 (0)