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 configFrom(KubernetesDependent confi OnDeleteFilter onDeleteFilter = null; GenericFilter 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 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

context) { - return context.getControllerConfiguration().getConfigurationService() - .ssaBasedCreateUpdateMatchForDependentResources(); + Optional 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

c client.resource(resource).delete(); } + @SuppressWarnings("unused") protected Resource 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 { private boolean namespacesWereConfigured = false; private boolean createResourceOnlyIfNotExistingWithSSA; private ResourceDiscriminator resourceDiscriminator; + private Boolean useSSA; private OnAddFilter onAddFilter; @@ -36,6 +38,7 @@ public KubernetesDependentResourceConfig(Set namespaces, boolean configuredNS, boolean createResourceOnlyIfNotExistingWithSSA, ResourceDiscriminator resourceDiscriminator, + Boolean useSSA, OnAddFilter onAddFilter, OnUpdateFilter onUpdateFilter, OnDeleteFilter onDeleteFilter, GenericFilter genericFilter) { @@ -48,12 +51,13 @@ public KubernetesDependentResourceConfig(Set namespaces, this.onDeleteFilter = onDeleteFilter; this.genericFilter = genericFilter; this.resourceDiscriminator = resourceDiscriminator; + this.useSSA = useSSA; } public KubernetesDependentResourceConfig(Set 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 setLabelSelector(String labelSelector) { @@ -105,4 +109,8 @@ protected void setNamespaces(Set namespaces) { this.namespaces = namespaces; } } + + public Optional useSSA() { + return Optional.ofNullable(useSSA); + } }