Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,34 @@ samples [here](https://github.com/java-operator-sdk/java-operator-sdk/tree/main/
in [related integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/orderedmanageddependent/ConfigMapDependentResource2.java)
.

### Adding Common Metadata to All Managed Resources (Desired State Aspects)

Operators often need to mark every resource they manage in a uniform way, for example with a
`app.kubernetes.io/managed-by` label, so that these resources can easily be identified, selected or
garbage-collected later on. Instead of repeating that logic in every `desired()` implementation, a
`DesiredStateAspect` can be registered once, at the operator level, and is then applied to the
desired state of every Kubernetes dependent resource managed by the operator:

```java
Operator operator = new Operator(overrider -> overrider
.withDesiredStateAspects(List.of(
(desired, dependentResource, context) -> desired.getMetadata().getLabels()
.put("app.kubernetes.io/managed-by", "my-operator"))));
Comment on lines +543 to +546
```

Aspects are applied, in registration order, right after the desired state has been computed and
before the desired state is matched against the actual resource, created or updated. As a
consequence, the metadata added by an aspect is part of the desired state proper: if it is removed
from the actual resource, or if the aspect itself changes, the associated secondary resources are
updated accordingly on the next reconciliation.

Since the desired state is computed at most once per reconciliation and cached in the `Context`,
aspects are called at most once per dependent resource and reconciliation. They are only called for
dependent resources whose desired state is a `HasMetadata`, meaning that external (non-Kubernetes)
dependent resources are left untouched. Implementations are expected to modify the provided desired
state in place and need to be thread-safe as they can be called concurrently for different primary
resources.

## "Read-only" Dependent Resources vs. Event Source

See Integration test for a read-only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.javaoperatorsdk.operator.api.config;

import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
Expand All @@ -41,6 +42,7 @@
import io.javaoperatorsdk.operator.api.reconciler.Experimental;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceFactory;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredStateAspect;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig;
Expand Down Expand Up @@ -539,4 +541,18 @@ default InformerPool informerPool() {
pool.setConfigurationService(this);
return pool;
}

/**
* Retrieves the {@link DesiredStateAspect}s applied to the desired state of all the Kubernetes
* dependent resources managed by the operator. Aspects are applied in the order in which they are
* returned, right after the desired state has been computed, and are typically used to add common
* metadata (such as a label identifying the operator managing the resource) to all the resources
* the operator creates or updates.
*
* @return the list of aspects to apply to computed desired states, empty by default
* @since 5.6.0
*/
default List<DesiredStateAspect> desiredStateAspects() {
return List.of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package io.javaoperatorsdk.operator.api.config;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
Expand All @@ -31,6 +33,7 @@
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
import io.javaoperatorsdk.operator.api.reconciler.Experimental;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceFactory;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredStateAspect;
import io.javaoperatorsdk.operator.processing.event.source.informer.pool.InformerPool;

@SuppressWarnings({"unused", "UnusedReturnValue"})
Expand Down Expand Up @@ -59,6 +62,7 @@ public class ConfigurationServiceOverrider {
private Boolean useSSAToPatchPrimaryResource;
private Boolean cloneSecondaryResourcesWhenGettingFromCache;
private InformerPool informerPool;
private List<DesiredStateAspect> desiredStateAspects;

@SuppressWarnings("rawtypes")
private DependentResourceFactory dependentResourceFactory;
Expand Down Expand Up @@ -229,6 +233,38 @@ public ConfigurationServiceOverrider withInformerPool(InformerPool informerPool)
return this;
}

/**
* Replaces the {@link DesiredStateAspect}s applied to the desired state of all the Kubernetes
* dependent resources managed by the operator by the specified ones.
*
* @param desiredStateAspects the aspects to apply, in the order in which they should be applied
* @return this {@link ConfigurationServiceOverrider} for chained customization
* @since 5.6.0
*/
public ConfigurationServiceOverrider withDesiredStateAspects(
List<DesiredStateAspect> desiredStateAspects) {
this.desiredStateAspects = new ArrayList<>(desiredStateAspects);
return this;
}

/**
* Appends the specified {@link DesiredStateAspect}s to the already configured ones, which are the
* ones configured on the overridden {@link ConfigurationService} unless {@link
* #withDesiredStateAspects(List)} was called on this overrider first.
*
* @param desiredStateAspects the aspects to append, in the order in which they should be applied
* @return this {@link ConfigurationServiceOverrider} for chained customization
* @since 5.6.0
*/
public ConfigurationServiceOverrider addDesiredStateAspects(
DesiredStateAspect... desiredStateAspects) {
if (this.desiredStateAspects == null) {
this.desiredStateAspects = new ArrayList<>(original.desiredStateAspects());
}
this.desiredStateAspects.addAll(List.of(desiredStateAspects));
return this;
}

public ConfigurationService build() {
return new BaseConfigurationService(original.getVersion(), cloner, client) {
@Override
Expand Down Expand Up @@ -383,6 +419,12 @@ public synchronized InformerPool informerPool() {
informerPool.setConfigurationService(this);
return informerPool;
}

@Override
public List<DesiredStateAspect> desiredStateAspects() {
return overriddenValueOrDefault(
desiredStateAspects, ConfigurationService::desiredStateAspects);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.event.ResourceEventRecorder;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredStateAspect;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DefaultManagedWorkflowAndDependentResourceContext;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ManagedWorkflowAndDependentResourceContext;
import io.javaoperatorsdk.operator.processing.Controller;
Expand Down Expand Up @@ -258,6 +259,25 @@ public <R> R getOrComputeDesiredStateFor(
DependentResource<R, P> dependentResource, Function<P, R> desiredStateComputer) {
return (R)
desiredStates.computeIfAbsent(
dependentResource, ignored -> desiredStateComputer.apply(getPrimaryResource()));
dependentResource,
ignored -> {
final var desired = desiredStateComputer.apply(getPrimaryResource());
applyDesiredStateAspects(desired, dependentResource);
return desired;
});
}

/**
* Applies the globally configured {@link DesiredStateAspect}s, in configuration order, to the
* freshly computed desired state. Aspects only apply to Kubernetes resources, external dependent
* resources are therefore left untouched.
*/
private void applyDesiredStateAspects(Object desired, DependentResource<?, P> dependentResource) {
if (desired instanceof HasMetadata hasMetadata) {
controllerConfiguration
.getConfigurationService()
.desiredStateAspects()
.forEach(aspect -> aspect.apply(hasMetadata, dependentResource, this));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Java Operator SDK Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.javaoperatorsdk.operator.api.reconciler.dependent;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
import io.javaoperatorsdk.operator.api.reconciler.Context;

/**
* A cross-cutting hook applied to the desired state of every Kubernetes {@link DependentResource}
* managed by the operator, typically used to add common metadata (labels or annotations) marking
* the resources the operator manages.
*
* <p>Aspects are registered globally on the {@link ConfigurationService} and are applied, in
* registration order, right after the desired state has been computed and before it is matched
* against, created or updated. This means modifications performed by an aspect are taken into
* account when determining whether the actual resource matches its desired state, so that changing
* an aspect triggers an update of the associated secondary resources.
*
* <p>The desired state is computed at most once per reconciliation and cached in the {@link
* Context}, so aspects are also called at most once per dependent resource and reconciliation.
* Aspects are only applied to dependent resources whose desired state is a {@link HasMetadata},
* i.e. they are not called for external (non-Kubernetes) dependent resources.
*
* <p>Implementations are expected to mutate the provided desired state in place and must be
* thread-safe as they can be called concurrently for different primary resources.
Comment on lines +38 to +39
*
* @see ConfigurationService#desiredStateAspects()
*/
@FunctionalInterface
public interface DesiredStateAspect {

/**
* Applies this aspect to the specified, freshly computed desired state.
*
* @param desired the desired state to modify in place
* @param dependentResource the {@link DependentResource} the desired state was computed for
* @param context the {@link Context} of the current reconciliation, from which the primary
* resource can be retrieved using {@link Context#getPrimaryResource()}
*/
void apply(HasMetadata desired, DependentResource<?, ?> dependentResource, Context<?> context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ public R update(R actual, R desired, P primary, Context<P> context) {

@Override
public Result<R> match(R resource, P primary, Context<P> context) {
return bulkDependentResource.match(resource, desired, primary, context);
// retrieve the desired state via the context so that it is processed the same way as for
// non-bulk dependents, in particular so that configured DesiredStateAspects are applied
// before matching
return bulkDependentResource.match(resource, getOrComputeDesired(context), primary, context);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.javaoperatorsdk.operator.api.config;

import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
Expand All @@ -33,6 +34,7 @@
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceFactory;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredStateAspect;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
Expand All @@ -42,7 +44,7 @@
private static final Metrics METRICS = new Metrics() {};

private static final LeaderElectionConfiguration LEADER_ELECTION_CONFIGURATION =
new LeaderElectionConfiguration("foo", "fooNS");

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / Special integration tests (25)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / Special integration tests (21)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / Special integration tests (17)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / check_format_and_unit_tests

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/kotlin-operator)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/tomcat-operator)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/mysql-schema)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/webpage)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/leader-election)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/operations)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.34.5) / Integration tests (21, v1.34.5, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / httpclient-tests (jetty) / Integration tests (25, v1.35.2, jetty)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / httpclient-tests (vertx) / Integration tests (25, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.35.2) / Integration tests (25, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.35.2) / Integration tests (17, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / httpclient-tests (jdk) / Integration tests (25, v1.35.2, jdk)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.32.13) / Integration tests (17, v1.32.13, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.32.13) / Integration tests (25, v1.32.13, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.33.9) / Integration tests (25, v1.33.9, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.34.5) / Integration tests (25, v1.34.5, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.34.5) / Integration tests (17, v1.34.5, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.32.13) / Integration tests (21, v1.32.13, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.35.2) / Integration tests (21, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.33.9) / Integration tests (21, v1.33.9, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 47 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.33.9) / Integration tests (17, v1.33.9, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

private static final Cloner CLONER =
new Cloner() {
Expand Down Expand Up @@ -94,7 +96,7 @@
.withConcurrentReconciliationThreads(25)
.withMetrics(new Metrics() {})
.withLeaderElectionConfiguration(
new LeaderElectionConfiguration("newLease", "newLeaseNS"))

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / Special integration tests (25)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / Special integration tests (21)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / Special integration tests (17)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / check_format_and_unit_tests

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/kotlin-operator)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/tomcat-operator)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/mysql-schema)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/webpage)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/leader-election)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / sample_operators_tests (sample-operators/operations)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.34.5) / Integration tests (21, v1.34.5, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / httpclient-tests (jetty) / Integration tests (25, v1.35.2, jetty)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / httpclient-tests (vertx) / Integration tests (25, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.35.2) / Integration tests (25, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.35.2) / Integration tests (17, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / httpclient-tests (jdk) / Integration tests (25, v1.35.2, jdk)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.32.13) / Integration tests (17, v1.32.13, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.32.13) / Integration tests (25, v1.32.13, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.33.9) / Integration tests (25, v1.33.9, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (25, v1.34.5) / Integration tests (25, v1.34.5, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.34.5) / Integration tests (17, v1.34.5, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.32.13) / Integration tests (21, v1.32.13, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.35.2) / Integration tests (21, v1.35.2, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (21, v1.33.9) / Integration tests (21, v1.33.9, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal

Check warning on line 99 in operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java

View workflow job for this annotation

GitHub Actions / build / integration_tests (17, v1.33.9) / Integration tests (17, v1.33.9, vertx)

LeaderElectionConfiguration(java.lang.String,java.lang.String) in io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration has been deprecated and marked for removal
.withInformerStoppedHandler((informer, ex) -> {})
.withReconciliationTerminationTimeout(Duration.ofSeconds(30))
.build();
Expand Down Expand Up @@ -187,4 +189,36 @@
.clusterScopedEventNamespace())
.isEqualTo("operator-ns");
}

@Test
void desiredStateAspectsAreEmptyByDefaultAndCanBeOverridden() {
assertThat(config.desiredStateAspects()).isEmpty();

final DesiredStateAspect first = (desired, dependentResource, context) -> {};
final DesiredStateAspect second = (desired, dependentResource, context) -> {};

assertThat(
new ConfigurationServiceOverrider(config)
.withDesiredStateAspects(List.of(first, second))
.build()
.desiredStateAspects())
.containsExactly(first, second);
}

@Test
void desiredStateAspectsCanBeAppendedToAlreadyConfiguredOnes() {
final DesiredStateAspect first = (desired, dependentResource, context) -> {};
final DesiredStateAspect second = (desired, dependentResource, context) -> {};
final DesiredStateAspect third = (desired, dependentResource, context) -> {};

final var configWithAspect =
new ConfigurationServiceOverrider(config).withDesiredStateAspects(List.of(first)).build();

assertThat(
new ConfigurationServiceOverrider(configWithAspect)
.addDesiredStateAspects(second, third)
.build()
.desiredStateAspects())
.containsExactly(first, second, third);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.javaoperatorsdk.operator.processing.dependent;

import java.util.List;
import java.util.Optional;
import java.util.Set;

Expand All @@ -23,8 +24,12 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.DefaultContext;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredStateAspect;
import io.javaoperatorsdk.operator.processing.Controller;
import io.javaoperatorsdk.operator.sample.simple.TestCustomResource;

import static org.junit.jupiter.api.Assertions.*;
Expand All @@ -37,7 +42,18 @@ class AbstractDependentResourceTest {
private static final DefaultContext<TestCustomResource> CONTEXT = createContext(PRIMARY);

private static DefaultContext<TestCustomResource> createContext(TestCustomResource primary) {
return new DefaultContext<>(mock(), mock(), primary, false, false);
return createContext(primary, List.of());
}

private static DefaultContext<TestCustomResource> createContext(
TestCustomResource primary, List<DesiredStateAspect> aspects) {
final ConfigurationService configurationService = mock();
when(configurationService.desiredStateAspects()).thenReturn(aspects);
final ControllerConfiguration<TestCustomResource> controllerConfiguration = mock();
when(controllerConfiguration.getConfigurationService()).thenReturn(configurationService);
final Controller<TestCustomResource> controller = mock();
when(controller.getConfiguration()).thenReturn(controllerConfiguration);
return new DefaultContext<>(mock(), controller, primary, false, false);
}

@Test
Expand Down Expand Up @@ -101,6 +117,35 @@ void checkThatDesiredIsOnlyCalledOnce() {
assertEquals(1, testDependentResource.desiredCallCount);
}

@Test
void appliesConfiguredDesiredStateAspectsInOrderAndOnlyOnce() {
final var testDependentResource = new DesiredCallCountCheckingDR();
final var primary = new TestCustomResource();
final var spec = primary.getSpec();
spec.setConfigMapName("foo");
spec.setKey("key");
spec.setValue("value");
final var context =
createContext(
primary,
List.of(
(desired, dependentResource, ctx) -> {
assertSame(testDependentResource, dependentResource);
assertSame(primary, ctx.getPrimaryResource());
desired.getMetadata().getLabels().put("aspect", "first");
},
(desired, dependentResource, ctx) ->
desired.getMetadata().getLabels().put("aspect", "second")));
Comment on lines +132 to +138

final var created = testDependentResource.reconcile(primary, context).getSingleResource();
assertEquals("second", created.orElseThrow().getMetadata().getLabels().get("aspect"));

// desired state is cached, aspects should therefore not be applied again
created.orElseThrow().getMetadata().getLabels().remove("aspect");
testDependentResource.reconcile(primary, context);
assertNull(created.orElseThrow().getMetadata().getLabels().get("aspect"));
}

private ConfigMap configMap() {
ConfigMap configMap = new ConfigMap();
configMap.setMetadata(
Expand Down
Loading
Loading