diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java index 36935e08a0..98198bf39a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java @@ -1,11 +1,8 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Objects; -import java.util.Optional; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.HasMetadata; @@ -20,8 +17,10 @@ public class GenericKubernetesResourceMatcher { private static final String SPEC = "/spec"; + private static final String METADATA = "/metadata"; private static final String ADD = "add"; private static final String OP = "op"; + private static final List IGNORED_FIELDS = List.of("/apiVersion", "/kind", "/status"); public static final String METADATA_LABELS = "/metadata/labels"; public static final String METADATA_ANNOTATIONS = "/metadata/annotations"; @@ -184,87 +183,39 @@ public static Result match(R d "Equality should be false in case of ignore list provided"); } - if (considerMetadata) { - Optional> res = - matchMetadata(desired, actualResource, labelsAndAnnotationsEquality, context); - if (res.isPresent()) { - return res.orElseThrow(); - } - } - - final var matched = matchSpec(actualResource, desired, specEquality, context, ignoredPaths); - return Result.computed(matched, desired); - } - - private static boolean matchSpec(R actual, R desired, boolean equality, - Context context, - String[] ignoredPaths) { - final var kubernetesSerialization = context.getClient().getKubernetesSerialization(); var desiredNode = kubernetesSerialization.convertValue(desired, JsonNode.class); - var actualNode = kubernetesSerialization.convertValue(actual, JsonNode.class); + var actualNode = kubernetesSerialization.convertValue(actualResource, JsonNode.class); var wholeDiffJsonPatch = JsonDiff.asJson(desiredNode, actualNode); - final List ignoreList = - ignoredPaths != null && ignoredPaths.length > 0 ? Arrays.asList(ignoredPaths) - : Collections.emptyList(); - // reflection will be replaced by this: - // https://github.com/fabric8io/kubernetes-client/issues/3816 - var specDiffJsonPatch = getDiffsImpactingPathsWithPrefixes(wholeDiffJsonPatch, SPEC); - // In case of equality is set to true, no diffs are allowed, so we return early if diffs exist - // On contrary (if equality is false), "add" is allowed for cases when for some - // resources Kubernetes fills-in values into spec. - if (equality && !specDiffJsonPatch.isEmpty()) { - return false; - } - if (!equality && !ignoreList.isEmpty()) { - if (!allDiffsOnIgnoreList(specDiffJsonPatch, ignoreList)) { - return false; - } - } else { - if (!allDiffsAreAddOps(specDiffJsonPatch)) { - return false; + boolean matched = true; + for (int i = 0; i < wholeDiffJsonPatch.size() && matched; i++) { + var node = wholeDiffJsonPatch.get(i); + if (nodeIsChildOf(node, List.of(SPEC))) { + matched = match(specEquality, node, ignoreList); + } else if (nodeIsChildOf(node, List.of(METADATA))) { + // conditionally consider labels and annotations + if (considerMetadata + && nodeIsChildOf(node, List.of(METADATA_LABELS, METADATA_ANNOTATIONS))) { + matched = match(labelsAndAnnotationsEquality, node, Collections.emptyList()); + } + } else if (!nodeIsChildOf(node, IGNORED_FIELDS)) { + matched = match(true, node, ignoreList); } } - return true; + + return Result.computed(matched, desired); } - private static boolean allDiffsOnIgnoreList(List metadataJSonDiffs, - List ignoreList) { - if (metadataJSonDiffs.isEmpty()) { + private static boolean match(boolean equality, JsonNode diff, + final List ignoreList) { + if (equality) { return false; } - return metadataJSonDiffs.stream().allMatch(n -> nodeIsChildOf(n, ignoreList)); - } - - private static Optional> matchMetadata( - R desired, - R actualResource, - boolean labelsAndAnnotationsEquality, Context

context) { - - if (labelsAndAnnotationsEquality) { - final var desiredMetadata = desired.getMetadata(); - final var actualMetadata = actualResource.getMetadata(); - - final var matched = - Objects.equals(desiredMetadata.getAnnotations(), actualMetadata.getAnnotations()) && - Objects.equals(desiredMetadata.getLabels(), actualMetadata.getLabels()); - if (!matched) { - return Optional.of(Result.computed(false, desired)); - } - } else { - final var objectMapper = context.getClient().getKubernetesSerialization(); - var desiredNode = objectMapper.convertValue(desired, JsonNode.class); - var actualNode = objectMapper.convertValue(actualResource, JsonNode.class); - var wholeDiffJsonPatch = JsonDiff.asJson(desiredNode, actualNode); - var metadataJSonDiffs = getDiffsImpactingPathsWithPrefixes(wholeDiffJsonPatch, - METADATA_LABELS, - METADATA_ANNOTATIONS); - if (!allDiffsAreAddOps(metadataJSonDiffs)) { - return Optional.of(Result.computed(false, desired)); - } + if (!ignoreList.isEmpty()) { + return nodeIsChildOf(diff, ignoreList); } - return Optional.empty(); + return ADD.equals(diff.get(OP).asText()); } static boolean nodeIsChildOf(JsonNode n, List prefixes) { @@ -276,29 +227,6 @@ static String getPath(JsonNode n) { return n.get(PATH).asText(); } - static boolean allDiffsAreAddOps(List metadataJSonDiffs) { - if (metadataJSonDiffs.isEmpty()) { - return true; - } - return metadataJSonDiffs.stream().allMatch(n -> ADD.equals(n.get(OP).asText())); - } - - public static List getDiffsImpactingPathsWithPrefixes(JsonNode diffJsonPatch, - String... prefixes) { - if (prefixes != null && prefixes.length > 0) { - var res = new ArrayList(); - var prefixList = Arrays.asList(prefixes); - for (int i = 0; i < diffJsonPatch.size(); i++) { - var node = diffJsonPatch.get(i); - if (nodeIsChildOf(node, prefixList)) { - res.add(node); - } - } - return res; - } - return Collections.emptyList(); - } - @Deprecated(forRemoval = true) public static Result match( KubernetesDependentResource dependentResource, R actualResource, P primary, diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ClusterRoleBindingResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ClusterRoleBindingResourceUpdaterMatcher.java deleted file mode 100644 index f6f6d1ef54..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ClusterRoleBindingResourceUpdaterMatcher.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class ClusterRoleBindingResourceUpdaterMatcher - extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(ClusterRoleBinding actual, ClusterRoleBinding desired) { - actual.setRoleRef(desired.getRoleRef()); - actual.setSubjects(desired.getSubjects()); - } - - @Override - public boolean matches(ClusterRoleBinding actual, ClusterRoleBinding desired, - Context context) { - return Objects.equals(actual.getRoleRef(), desired.getRoleRef()) && - Objects.equals(actual.getSubjects(), desired.getSubjects()); - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ClusterRoleResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ClusterRoleResourceUpdaterMatcher.java deleted file mode 100644 index da7997c040..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ClusterRoleResourceUpdaterMatcher.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.rbac.ClusterRole; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class ClusterRoleResourceUpdaterMatcher - extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(ClusterRole actual, ClusterRole desired) { - actual.setAggregationRule(desired.getAggregationRule()); - actual.setRules(desired.getRules()); - } - - @Override - public boolean matches(ClusterRole actual, ClusterRole desired, Context context) { - return Objects.equals(actual.getRules(), desired.getRules()) && - Objects.equals(actual.getAggregationRule(), desired.getAggregationRule()); - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ConfigMapResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ConfigMapResourceUpdaterMatcher.java deleted file mode 100644 index 7f89d45ff5..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ConfigMapResourceUpdaterMatcher.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.ConfigMap; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class ConfigMapResourceUpdaterMatcher - extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(ConfigMap actual, ConfigMap desired) { - actual.setData(desired.getData()); - actual.setBinaryData((desired.getBinaryData())); - actual.setImmutable(desired.getImmutable()); - } - - @Override - public boolean matches(ConfigMap actual, ConfigMap desired, Context context) { - return Objects.equals(actual.getImmutable(), desired.getImmutable()) && - Objects.equals(actual.getData(), desired.getData()) && - Objects.equals(actual.getBinaryData(), desired.getBinaryData()); - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/EndpointSliceResourceUpdateMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/EndpointSliceResourceUpdateMatcher.java deleted file mode 100644 index dc83c86dbf..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/EndpointSliceResourceUpdateMatcher.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.discovery.v1.EndpointSlice; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class EndpointSliceResourceUpdateMatcher - extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(EndpointSlice actual, EndpointSlice desired) { - actual.setEndpoints(desired.getEndpoints()); - actual.setAddressType(desired.getAddressType()); - actual.setPorts(desired.getPorts()); - } - - @Override - public boolean matches(EndpointSlice actual, EndpointSlice desired, Context context) { - return Objects.equals(actual.getEndpoints(), desired.getEndpoints()) && - Objects.equals(actual.getAddressType(), desired.getAddressType()) && - Objects.equals(actual.getPorts(), desired.getPorts()); - } - -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/EndpointsResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/EndpointsResourceUpdaterMatcher.java deleted file mode 100644 index 3dcfabde28..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/EndpointsResourceUpdaterMatcher.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.Endpoints; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class EndpointsResourceUpdaterMatcher extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(Endpoints actual, Endpoints desired) { - actual.setSubsets(desired.getSubsets()); - } - - @Override - public boolean matches(Endpoints actual, Endpoints desired, Context context) { - return Objects.equals(actual.getSubsets(), desired.getSubsets()); - } - -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java index cd9fbe2b16..2a5bae03b9 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java @@ -2,13 +2,8 @@ import java.util.Map; -import io.fabric8.kubernetes.api.model.*; -import io.fabric8.kubernetes.api.model.discovery.v1.EndpointSlice; -import io.fabric8.kubernetes.api.model.rbac.ClusterRole; -import io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding; -import io.fabric8.kubernetes.api.model.rbac.Role; -import io.fabric8.kubernetes.api.model.rbac.RoleBinding; -import io.javaoperatorsdk.operator.ReconcilerUtils; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericKubernetesResourceMatcher; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.ResourceUpdaterMatcher; @@ -16,34 +11,31 @@ public class GenericResourceUpdaterMatcher implements ResourceUpdaterMatcher { + private static final String METADATA = "metadata"; private static final ResourceUpdaterMatcher INSTANCE = new GenericResourceUpdaterMatcher<>(); - @SuppressWarnings("rawtypes") - private static final Map processors = Map.of( - Secret.class, new SecretResourceUpdaterMatcher(), - ConfigMap.class, new ConfigMapResourceUpdaterMatcher(), - ServiceAccount.class, new ServiceAccountResourceUpdaterMatcher(), - Role.class, new RoleResourceUpdaterMatcher(), - ClusterRole.class, new ClusterRoleResourceUpdaterMatcher(), - RoleBinding.class, new RoleBindingResourceUpdaterMatcher(), - ClusterRoleBinding.class, new ClusterRoleBindingResourceUpdaterMatcher(), - Endpoints.class, new EndpointsResourceUpdaterMatcher(), - EndpointSlice.class, new EndpointSliceResourceUpdateMatcher()); - protected GenericResourceUpdaterMatcher() {} @SuppressWarnings("unchecked") public static ResourceUpdaterMatcher updaterMatcherFor( Class resourceType) { - final var processor = processors.get(resourceType); - return processor != null ? processor : (ResourceUpdaterMatcher) INSTANCE; + return (ResourceUpdaterMatcher) INSTANCE; } + @SuppressWarnings("unchecked") + @Override public R updateResource(R actual, R desired, Context context) { - var clonedActual = context.getControllerConfiguration().getConfigurationService() - .getResourceCloner().clone(actual); + KubernetesSerialization kubernetesSerialization = + context.getClient().getKubernetesSerialization(); + Map actualMap = kubernetesSerialization.convertValue(actual, Map.class); + Map desiredMap = kubernetesSerialization.convertValue(desired, Map.class); + // replace all top level fields from actual with desired, but merge metadata separately + var metadata = actualMap.remove(METADATA); + actualMap.replaceAll((k, v) -> desiredMap.get(k)); + actualMap.putAll(desiredMap); + actualMap.put(METADATA, metadata); + var clonedActual = (R) kubernetesSerialization.convertValue(actualMap, desired.getClass()); updateLabelsAndAnnotation(clonedActual, desired); - updateClonedActual(clonedActual, desired); return clonedActual; } @@ -53,15 +45,6 @@ public boolean matches(R actual, R desired, Context context) { false, false, context).matched(); } - protected void updateClonedActual(R actual, R desired) { - updateSpec(actual, desired); - } - - public static void updateSpec(K actual, K desired) { - var desiredSpec = ReconcilerUtils.getSpec(desired); - ReconcilerUtils.setSpec(actual, desiredSpec); - } - public static void updateLabelsAndAnnotation(K actual, K desired) { actual.getMetadata().getLabels().putAll(desired.getMetadata().getLabels()); actual.getMetadata().getAnnotations().putAll(desired.getMetadata().getAnnotations()); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/RoleBindingResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/RoleBindingResourceUpdaterMatcher.java deleted file mode 100644 index c6a87cdae3..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/RoleBindingResourceUpdaterMatcher.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.rbac.RoleBinding; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class RoleBindingResourceUpdaterMatcher - extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(RoleBinding actual, RoleBinding desired) { - actual.setRoleRef(desired.getRoleRef()); - actual.setSubjects(desired.getSubjects()); - } - - @Override - public boolean matches(RoleBinding actual, RoleBinding desired, - Context context) { - return Objects.equals(actual.getRoleRef(), desired.getRoleRef()) && - Objects.equals(actual.getSubjects(), desired.getSubjects()); - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/RoleResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/RoleResourceUpdaterMatcher.java deleted file mode 100644 index f02d946db8..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/RoleResourceUpdaterMatcher.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.rbac.Role; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class RoleResourceUpdaterMatcher extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(Role actual, Role desired) { - actual.setRules(desired.getRules()); - } - - @Override - public boolean matches(Role actual, Role desired, Context context) { - return Objects.equals(actual.getRules(), desired.getRules()); - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/SecretResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/SecretResourceUpdaterMatcher.java deleted file mode 100644 index 14e8696704..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/SecretResourceUpdaterMatcher.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.Secret; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class SecretResourceUpdaterMatcher extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(Secret actual, Secret desired) { - actual.setData(desired.getData()); - actual.setStringData(desired.getStringData()); - actual.setImmutable(desired.getImmutable()); - actual.setType(desired.getType()); - } - - @Override - public boolean matches(Secret actual, Secret desired, Context context) { - return Objects.equals(actual.getImmutable(), desired.getImmutable()) && - Objects.equals(actual.getType(), desired.getType()) && - Objects.equals(actual.getData(), desired.getData()) && - Objects.equals(actual.getStringData(), desired.getStringData()); - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ServiceAccountResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ServiceAccountResourceUpdaterMatcher.java deleted file mode 100644 index f3d625c778..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/ServiceAccountResourceUpdaterMatcher.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher; - -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.ServiceAccount; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public class ServiceAccountResourceUpdaterMatcher - extends GenericResourceUpdaterMatcher { - - @Override - protected void updateClonedActual(ServiceAccount actual, ServiceAccount desired) { - actual.setAutomountServiceAccountToken(desired.getAutomountServiceAccountToken()); - actual.setImagePullSecrets(desired.getImagePullSecrets()); - actual.setSecrets(desired.getSecrets()); - } - - @Override - public boolean matches(ServiceAccount actual, ServiceAccount desired, Context context) { - return Objects.equals(actual.getAutomountServiceAccountToken(), - desired.getAutomountServiceAccountToken()) && - Objects.equals(actual.getImagePullSecrets(), desired.getImagePullSecrets()) && - Objects.equals(actual.getSecrets(), desired.getSecrets()); - } -} diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java index 41bafe00e4..b1ff214f3b 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java @@ -10,6 +10,7 @@ import io.fabric8.kubernetes.api.model.ServiceAccountBuilder; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.apps.DeploymentStatusBuilder; import io.javaoperatorsdk.operator.MockKubernetesClient; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; @@ -79,6 +80,15 @@ void doesNotMatchChangedValues() { .isFalse(); } + @Test + void ignoreStatus() { + actual = createDeployment(); + actual.setStatus(new DeploymentStatusBuilder().withReadyReplicas(1).build()); + assertThat(matcher.match(actual, null, context).matched()) + .withFailMessage("Should ignore status in actual") + .isTrue(); + } + @Test void doesNotMatchChangedValuesWhenNoIgnoredPathsAreProvided() { actual = createDeployment(); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java index c1d9b4a5a5..44f3fb51ea 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java @@ -2,6 +2,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -33,7 +34,7 @@ static void setUp() { final var client = MockKubernetesClient.client(HasMetadata.class); when(configService.getKubernetesClient()).thenReturn(client); when(configService.getResourceCloner()).thenCallRealMethod(); - + when(context.getClient()).thenReturn(client); when(context.getControllerConfiguration()).thenReturn(controllerConfiguration); } @@ -99,6 +100,23 @@ void checkSecret() { assertThat(secret.getData()).containsOnlyKeys("foo"); } + @Test + void checkSeviceAccount() { + var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(ServiceAccount.class); + var desired = new ServiceAccountBuilder() + .withMetadata(new ObjectMetaBuilder().addToLabels("new", "label").build()) + .build(); + var actual = new ServiceAccountBuilder() + .withMetadata(new ObjectMetaBuilder().addToLabels("a", "label").build()) + .withImagePullSecrets(new LocalObjectReferenceBuilder().withName("secret").build()) + .build(); + + final var serviceAccount = processor.updateResource(actual, desired, context); + assertThat(serviceAccount.getMetadata().getLabels()) + .isEqualTo(Map.of("a", "label", "new", "label")); + assertThat(serviceAccount.getImagePullSecrets()).isNullOrEmpty(); + } + Deployment createDeployment() { return ReconcilerUtils.loadYaml( Deployment.class, GenericResourceUpdaterMatcherTest.class, "nginx-deployment.yaml");