Skip to content

Commit

Permalink
feat: Workflow extracted to a separate annotation (#2274)
Browse files Browse the repository at this point in the history

Signed-off-by: Attila Mészáros <csviri@gmail.com>
  • Loading branch information
csviri committed Mar 11, 2024
1 parent a9b7bf7 commit e0a622f
Show file tree
Hide file tree
Showing 52 changed files with 318 additions and 313 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
import io.javaoperatorsdk.operator.api.reconciler.Workflow;
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;

import java.util.Map;
import java.util.Optional;

@ControllerConfiguration(dependents = {@Dependent(type = ConfigMapDependentResource.class)})
@Workflow(dependents = {@Dependent(type = ConfigMapDependentResource.class)})
@ControllerConfiguration
public class {{artifactClassId}}Reconciler implements Reconciler<{{artifactClassId}}CustomResource> {

public UpdateControl<{{artifactClassId}}CustomResource> reconcile({{artifactClassId}}CustomResource primary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.config.Utils.Configurator;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
import io.javaoperatorsdk.operator.api.reconciler.Constants;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.Workflow;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
Expand Down Expand Up @@ -97,6 +99,7 @@ public <R extends HasMetadata> ControllerConfiguration<R> getConfigurationFor(
protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconciler<P> reconciler) {
final var annotation = reconciler.getClass().getAnnotation(
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration.class);

if (annotation == null) {
throw new OperatorException(
"Missing mandatory @"
Expand Down Expand Up @@ -161,21 +164,26 @@ protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconcile
Utils.instantiate(annotation.itemStore(), ItemStore.class, context), dependentFieldManager,
this, informerListLimit);

List<DependentResourceSpec> specs = dependentResources(annotation, config);
config.setDependentResources(specs);

final var workflowAnnotation = reconciler.getClass().getAnnotation(
io.javaoperatorsdk.operator.api.reconciler.Workflow.class);
if (workflowAnnotation != null) {
List<DependentResourceSpec> specs = dependentResources(workflowAnnotation, config);
WorkflowSpec workflowSpec = new WorkflowSpec(specs);
config.setWorkflowSpec(workflowSpec);
}

return config;
}

@SuppressWarnings({"unchecked", "rawtypes"})
private static List<DependentResourceSpec> dependentResources(
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration annotation,
Workflow annotation,
ControllerConfiguration<?> parent) {
final var dependents =
valueOrDefault(annotation,
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::dependents,
new Dependent[] {});
if (dependents.length == 0) {
final var dependents = annotation.dependents();


if (dependents == null || dependents.length == 0) {
return Collections.emptyList();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package io.javaoperatorsdk.operator.api.config;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
import io.javaoperatorsdk.operator.api.reconciler.MaxReconciliationInterval;
import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter;
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
Expand Down Expand Up @@ -65,9 +63,8 @@ default RateLimiter getRateLimiter() {
return DEFAULT_RATE_LIMITER;
}

@SuppressWarnings("rawtypes")
default List<DependentResourceSpec> getDependentResources() {
return Collections.emptyList();
default Optional<WorkflowSpec> getWorkflowSpec() {
return Optional.empty();
}

default Optional<Duration> maxReconciliationInterval() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
Expand Down Expand Up @@ -38,6 +39,7 @@ public class ControllerConfigurationOverrider<R extends HasMetadata> {
private String name;
private String fieldManager;
private Long informerListLimit;
private WorkflowSpec workflowSpec;

private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
this.finalizer = original.getFinalizerName();
Expand All @@ -55,6 +57,7 @@ private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
this.fieldManager = original.fieldManager();
this.informerListLimit = original.getInformerListLimit().orElse(null);
this.itemStore = original.getItemStore().orElse(null);
this.workflowSpec = original.getWorkflowSpec().orElse(null);
}

public ControllerConfigurationOverrider<R> withFinalizer(String finalizer) {
Expand Down Expand Up @@ -175,7 +178,7 @@ public ControllerConfigurationOverrider<R> withInformerListLimit(
public ControllerConfigurationOverrider<R> replacingNamedDependentResourceConfig(String name,
Object dependentResourceConfig) {

final var specs = original.getDependentResources();
final var specs = original.getWorkflowSpec().orElseThrow().getDependentResourceSpecs();
final var spec = specs.stream()
.filter(drs -> drs.getName().equals(name)).findFirst()
.orElseThrow(
Expand All @@ -193,9 +196,9 @@ public ControllerConfiguration<R> build() {
name,
generationAware, original.getAssociatedReconcilerClassName(), retry, rateLimiter,
reconciliationMaxInterval, onAddFilter, onUpdateFilter, genericFilter,
original.getDependentResources(),
namespaces, finalizer, labelSelector, configurations, itemStore, fieldManager,
original.getConfigurationService(), informerListLimit);
original.getConfigurationService(), informerListLimit,
original.getWorkflowSpec().orElse(null));
}

public static <R extends HasMetadata> ControllerConfigurationOverrider<R> override(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationProvider;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
Expand All @@ -32,20 +33,19 @@ public class ResolvedControllerConfiguration<P extends HasMetadata>
private final ItemStore<P> itemStore;
private final ConfigurationService configurationService;
private final String fieldManager;

private List<DependentResourceSpec> dependentResources;
private WorkflowSpec workflowSpec;

public ResolvedControllerConfiguration(Class<P> resourceClass, ControllerConfiguration<P> other) {
this(resourceClass, other.getName(), other.isGenerationAware(),
other.getAssociatedReconcilerClassName(), other.getRetry(), other.getRateLimiter(),
other.maxReconciliationInterval().orElse(null),
other.onAddFilter().orElse(null), other.onUpdateFilter().orElse(null),
other.genericFilter().orElse(null),
other.getDependentResources(), other.getNamespaces(),
other.getNamespaces(),
other.getFinalizerName(), other.getLabelSelector(), Collections.emptyMap(),
other.getItemStore().orElse(null), other.fieldManager(),
other.getConfigurationService(),
other.getInformerListLimit().orElse(null));
other.getInformerListLimit().orElse(null), other.getWorkflowSpec().orElse(null));
}

public static Duration getMaxReconciliationInterval(long interval, TimeUnit timeUnit) {
Expand All @@ -70,16 +70,16 @@ public ResolvedControllerConfiguration(Class<P> resourceClass, String name,
RateLimiter rateLimiter, Duration maxReconciliationInterval,
OnAddFilter<? super P> onAddFilter, OnUpdateFilter<? super P> onUpdateFilter,
GenericFilter<? super P> genericFilter,
List<DependentResourceSpec> dependentResources,
Set<String> namespaces, String finalizer, String labelSelector,
Map<DependentResourceSpec, Object> configurations, ItemStore<P> itemStore,
String fieldManager,
ConfigurationService configurationService, Long informerListLimit) {
ConfigurationService configurationService, Long informerListLimit,
WorkflowSpec workflowSpec) {
this(resourceClass, name, generationAware, associatedReconcilerClassName, retry, rateLimiter,
maxReconciliationInterval, onAddFilter, onUpdateFilter, genericFilter,
namespaces, finalizer, labelSelector, configurations, itemStore, fieldManager,
configurationService, informerListLimit);
setDependentResources(dependentResources);
setWorkflowSpec(workflowSpec);
}

protected ResolvedControllerConfiguration(Class<P> resourceClass, String name,
Expand All @@ -105,6 +105,7 @@ protected ResolvedControllerConfiguration(Class<P> resourceClass, String name,
this.finalizer =
ControllerConfiguration.ensureValidFinalizerName(finalizer, getResourceTypeName());
this.fieldManager = fieldManager;
this.workflowSpec = workflowSpec;
}

protected ResolvedControllerConfiguration(Class<P> resourceClass, String name,
Expand Down Expand Up @@ -144,14 +145,14 @@ public RateLimiter getRateLimiter() {
return rateLimiter;
}


@Override
public List<DependentResourceSpec> getDependentResources() {
return dependentResources;
public Optional<WorkflowSpec> getWorkflowSpec() {
return Optional.ofNullable(workflowSpec);
}

protected void setDependentResources(List<DependentResourceSpec> dependentResources) {
this.dependentResources = dependentResources == null ? Collections.emptyList()
: Collections.unmodifiableList(dependentResources);
public void setWorkflowSpec(WorkflowSpec workflowSpec) {
this.workflowSpec = workflowSpec;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.javaoperatorsdk.operator.api.config.workflow;

import java.util.List;

import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;

public class WorkflowSpec {

@SuppressWarnings("rawtypes")
private final List<DependentResourceSpec> dependentResourceSpecs;

public WorkflowSpec(List<DependentResourceSpec> dependentResourceSpecs) {
this.dependentResourceSpecs = dependentResourceSpecs;
}

public List<DependentResourceSpec> getDependentResourceSpecs() {
return dependentResourceSpecs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.lang.annotation.Target;

import io.fabric8.kubernetes.client.informers.cache.ItemStore;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter;
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
import io.javaoperatorsdk.operator.processing.event.source.cache.BoundedItemStore;
Expand Down Expand Up @@ -93,15 +92,6 @@
MaxReconciliationInterval maxReconciliationInterval() default @MaxReconciliationInterval(
interval = MaxReconciliationInterval.DEFAULT_INTERVAL);


/**
* Optional list of {@link Dependent} configurations which associate a resource type to a
* {@link io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource} implementation
*
* @return the array of {@link Dependent} configurations
*/
Dependent[] dependents() default {};

/**
* Optional {@link Retry} implementation for the associated controller to use.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.javaoperatorsdk.operator.api.reconciler;

import java.lang.annotation.*;

import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Workflow {

Dependent[] dependents();

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package io.javaoperatorsdk.operator.processing.dependent.workflow;

import java.util.Optional;

import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;

public interface ManagedWorkflowFactory<C extends ControllerConfiguration<?>> {

@SuppressWarnings({"rawtypes", "unchecked"})
ManagedWorkflowFactory DEFAULT = (configuration) -> {
final var dependentResourceSpecs = configuration.getDependentResources();
if (dependentResourceSpecs == null || dependentResourceSpecs.isEmpty()) {
final Optional<WorkflowSpec> workflowSpec = configuration.getWorkflowSpec();
if (workflowSpec.isEmpty()) {
return (ManagedWorkflow) (client, configuration1) -> new DefaultWorkflow(null);
}
ManagedWorkflowSupport support = new ManagedWorkflowSupport();
return support.createWorkflow(dependentResourceSpecs);
return support.createWorkflow(workflowSpec.orElseThrow());
};

@SuppressWarnings("rawtypes")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.OperatorException;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;

@SuppressWarnings({"rawtypes", "unchecked"})
class ManagedWorkflowSupport {
Expand All @@ -38,10 +39,10 @@ public void checkForNameDuplication(List<DependentResourceSpec> dependentResourc
}
}


public <P extends HasMetadata> ManagedWorkflow<P> createWorkflow(
List<DependentResourceSpec> dependentResourceSpecs) {
return createAsDefault(dependentResourceSpecs);
WorkflowSpec workflowSpec) {

return createAsDefault(workflowSpec.getDependentResourceSpecs());
}

<P extends HasMetadata> DefaultManagedWorkflow<P> createAsDefault(
Expand Down
Loading

0 comments on commit e0a622f

Please sign in to comment.