From 5ef6808c85d08fd24501382354f6b6b341a0f9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= <csviri@gmail.com> Date: Thu, 7 Sep 2023 13:35:41 +0200 Subject: [PATCH] feat: configurable SSA per Dependent Resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros <csviri@gmail.com> --- .../kubernetes/BooleanWithUndefined.java | 19 +++++++++++++++++++ .../kubernetes/KubernetesDependent.java | 14 +++++++++++++- .../KubernetesDependentConverter.java | 4 +++- .../KubernetesDependentResource.java | 7 +++++-- .../KubernetesDependentResourceConfig.java | 10 +++++++++- 5 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/BooleanWithUndefined.java diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/BooleanWithUndefined.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/BooleanWithUndefined.java new file mode 100644 index 0000000000..fcf7553a4a --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/BooleanWithUndefined.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.operator.processing.dependent.kubernetes; + +/** + * A replacement for {@link Boolean}, which can't be used in annotations. + */ +public enum BooleanWithUndefined { + TRUE, FALSE, UNDEFINED; + + Boolean asBoolean() { + switch (this) { + case TRUE: + return Boolean.TRUE; + case FALSE: + return Boolean.FALSE; + default: + return null; + } + } +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java index c3f7be408a..eb4c9cf9b0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java @@ -25,7 +25,7 @@ * namespace is specified then the controller will monitor the namespaces configured for the * controller. * - * @return the list of namespaces this controller monitors + * @return the array of namespaces this controller monitors */ String[] namespaces() default {Constants.SAME_AS_CONTROLLER}; @@ -76,4 +76,16 @@ * Creates the resource only if did not exist before, this applies only if SSA is used. */ boolean createResourceOnlyIfNotExistingWithSSA() default KubernetesDependentResourceConfig.DEFAULT_CREATE_RESOURCE_ONLY_IF_NOT_EXISTING_WITH_SSA; + + /** + * Determines whether to use SSA (Server-Side Apply) for this dependent. If SSA is used, the + * dependent resource will only be created if it did not exist before. Default value is + * {@link BooleanWithUndefined#UNDEFINED}, which specifies that the behavior with respect to SSA + * is inherited from the global configuration. + * + * @return {@code true} if SSA is enabled, {@code false} if SSA is disabled, + * {@link BooleanWithUndefined#UNDEFINED} if the SSA behavior should be inherited from the + * global configuration + */ + BooleanWithUndefined useSSA() default BooleanWithUndefined.UNDEFINED; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java index 6ab07a9462..7a434aecf1 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java @@ -34,6 +34,7 @@ public KubernetesDependentResourceConfig<R> configFrom(KubernetesDependent confi OnDeleteFilter<? extends HasMetadata> onDeleteFilter = null; GenericFilter<? extends HasMetadata> genericFilter = null; ResourceDiscriminator<?, ?> resourceDiscriminator = null; + Boolean useSSA = null; if (configAnnotation != null) { if (!Arrays.equals(KubernetesDependent.DEFAULT_NAMESPACES, configAnnotation.namespaces())) { namespaces = Set.of(configAnnotation.namespaces()); @@ -58,10 +59,11 @@ public KubernetesDependentResourceConfig<R> configFrom(KubernetesDependent confi context); createResourceOnlyIfNotExistingWithSSA = configAnnotation.createResourceOnlyIfNotExistingWithSSA(); + useSSA = configAnnotation.useSSA().asBoolean(); } return new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS, createResourceOnlyIfNotExistingWithSSA, - resourceDiscriminator, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter); + resourceDiscriminator, useSSA, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java index 5fedd0899d..7fadcc6940 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java @@ -190,8 +190,10 @@ protected void addMetadata(boolean forMatch, R actualResource, final R target, P } private boolean useSSA(Context<P> context) { - return context.getControllerConfiguration().getConfigurationService() - .ssaBasedCreateUpdateMatchForDependentResources(); + Optional<Boolean> useSSAConfig = + configuration().flatMap(KubernetesDependentResourceConfig::useSSA); + return useSSAConfig.orElse(context.getControllerConfiguration().getConfigurationService() + .ssaBasedCreateUpdateMatchForDependentResources()); } @Override @@ -206,6 +208,7 @@ public void deleteTargetResource(P primary, R resource, String key, Context<P> c client.resource(resource).delete(); } + @SuppressWarnings("unused") protected Resource<R> prepare(R desired, P primary, String actionName) { log.debug("{} target resource with type: {}, with id: {}", actionName, diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java index 33f4f91d1f..836bfbfc08 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java @@ -1,5 +1,6 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; +import java.util.Optional; import java.util.Set; import io.javaoperatorsdk.operator.api.reconciler.Constants; @@ -20,6 +21,7 @@ public class KubernetesDependentResourceConfig<R> { private boolean namespacesWereConfigured = false; private boolean createResourceOnlyIfNotExistingWithSSA; private ResourceDiscriminator<R, ?> resourceDiscriminator; + private Boolean useSSA; private OnAddFilter<R> onAddFilter; @@ -36,6 +38,7 @@ public KubernetesDependentResourceConfig(Set<String> namespaces, boolean configuredNS, boolean createResourceOnlyIfNotExistingWithSSA, ResourceDiscriminator<R, ?> resourceDiscriminator, + Boolean useSSA, OnAddFilter<R> onAddFilter, OnUpdateFilter<R> onUpdateFilter, OnDeleteFilter<R> onDeleteFilter, GenericFilter<R> genericFilter) { @@ -48,12 +51,13 @@ public KubernetesDependentResourceConfig(Set<String> namespaces, this.onDeleteFilter = onDeleteFilter; this.genericFilter = genericFilter; this.resourceDiscriminator = resourceDiscriminator; + this.useSSA = useSSA; } public KubernetesDependentResourceConfig(Set<String> namespaces, String labelSelector) { this(namespaces, labelSelector, true, DEFAULT_CREATE_RESOURCE_ONLY_IF_NOT_EXISTING_WITH_SSA, null, null, null, - null, null); + null, null, null); } public KubernetesDependentResourceConfig<R> setLabelSelector(String labelSelector) { @@ -105,4 +109,8 @@ protected void setNamespaces(Set<String> namespaces) { this.namespaces = namespaces; } } + + public Optional<Boolean> useSSA() { + return Optional.ofNullable(useSSA); + } }