From 79cd6cd0a262c91a1b6cbd43fa2191a9ee6bb943 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Thu, 3 Feb 2022 09:55:05 +0100 Subject: [PATCH 1/7] feat: add desired and matches methods on DependentResource This removes the need for Builder and Updater interfaces. --- .../api/config/DependentResource.java | 43 +++++++++++++++++++ .../api/reconciler/dependent/Builder.java | 9 ---- .../DependentResourceController.java | 40 +++++++---------- .../api/reconciler/dependent/Updater.java | 10 ----- .../dependent/DependentResourceManager.java | 24 ++++------- .../runtime/AnnotationConfiguration.java | 3 +- .../sample/MySQLSchemaReconciler.java | 14 +++--- .../sample/SchemaDependentResource.java | 7 ++- .../sample/DeploymentDependentResource.java | 20 ++++----- .../sample/ServiceDependentResource.java | 26 +++++------ 10 files changed, 100 insertions(+), 96 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Builder.java delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java index f4d5df89fb..30798a8aa5 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java @@ -1,6 +1,7 @@ package io.javaoperatorsdk.operator.api.config; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.processing.event.source.EventSource; @@ -12,4 +13,46 @@ default EventSource initEventSource(EventSourceContext

context) { default Class resourceType() { return (Class) Utils.getFirstTypeArgumentFromInterface(getClass()); } + + /** + * todo: return Optional instead? + * + * Computes the desired state of the dependent based on the state provided by the specified + * primary resource. + * + * The default implementation returns {@code null} which corresponds to the case where the + * associated dependent should never be created by the associated reconciler or that the global + * state of the cluster doesn't allow for the resource to be created at this point. + * + * @param primary the primary resource associated with the reconciliation process + * @param context the {@link Context} associated with the reconciliation process + * @return an instance of the dependent resource matching the desired state specified by the + * primary resource or {@code null} if the dependent shouldn't be created at this point + * (or ever) + */ + default R desired(P primary, Context context) { + return null; + } + + /** + * Checks whether the actual resource as fetched from the cluster matches the desired state + * expressed by the specified primary resource. + * + * The default implementation always return {@code true}, which corresponds to the behavior where + * the dependent never needs to be updated after it's been created. + * + * Note that failure to properly implement this method will lead to infinite loops. In particular, + * for typical Kubernetes resource implementations, simply calling + * {@code desired(primary, context).equals(actual)} is not enough because metadata will usually be + * different. + * + * @param actual the current state of the resource as fetched from the cluster + * @param primary the primary resource associated with the reconciliation request + * @param context the {@link Context} associated with the reconciliation request + * @return {@code true} if the actual state of the resource matches the desired state expressed by + * the specified primary resource, {@code false} otherwise + */ + default boolean match(R actual, P primary, Context context) { + return true; + } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Builder.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Builder.java deleted file mode 100644 index 4dfaf91e64..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Builder.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -@FunctionalInterface -public interface Builder { - R buildFor(P primary, Context context); -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java index 21cd16a32f..e4ffa9d9c5 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java @@ -8,11 +8,8 @@ import io.javaoperatorsdk.operator.processing.event.source.EventSource; public class DependentResourceController> - implements DependentResource, Builder, Updater, Persister, - Cleaner { + implements DependentResource, Persister, Cleaner { - private final Builder builder; - private final Updater updater; private final Cleaner cleaner; private final Persister persister; private final DependentResource delegate; @@ -21,13 +18,26 @@ public class DependentResourceController delegate, C configuration) { this.delegate = delegate; - builder = (delegate instanceof Builder) ? (Builder) delegate : null; - updater = (delegate instanceof Updater) ? (Updater) delegate : null; cleaner = (delegate instanceof Cleaner) ? (Cleaner) delegate : null; persister = initPersister(delegate); this.configuration = configuration; } + @Override + public Class resourceType() { + return delegate.resourceType(); + } + + @Override + public boolean match(R actual, P primary, Context context) { + return delegate.match(actual, primary, context); + } + + @Override + public R desired(P primary, Context context) { + return delegate.desired(primary, context); + } + @SuppressWarnings("unchecked") protected Persister initPersister(DependentResource delegate) { if (delegate instanceof Persister) { @@ -42,16 +52,6 @@ public String descriptionFor(R resource) { return resource.toString(); } - @Override - public R buildFor(P primary, Context context) { - return builder.buildFor(primary, context); - } - - @Override - public R update(R fetched, P primary, Context context) { - return updater.update(fetched, primary, context); - } - @Override public void delete(R fetched, P primary, Context context) { cleaner.delete(fetched, primary, context); @@ -66,14 +66,6 @@ public EventSource initEventSource(EventSourceContext

context) { return delegate.initEventSource(context); } - public boolean creatable() { - return builder != null; - } - - public boolean updatable() { - return updater != null; - } - public boolean deletable() { return cleaner != null; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java deleted file mode 100644 index c92f3c5ced..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -@FunctionalInterface -public interface Updater { - - R update(R fetched, P primary, Context context); -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index 911805b396..8795bcced0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -67,21 +67,15 @@ public void injectInto(EventSourceContext context) { public UpdateControl reconcile(R resource, Context context) { initContextIfNeeded(resource, context); - dependents.stream() - .filter(dependent -> dependent.creatable() || dependent.updatable()) - .forEach(dependent -> { - var dependentResource = dependent.getFor(resource, context); - if (dependent.creatable() && dependentResource == null) { - // we need to create the dependent - dependentResource = dependent.buildFor(resource, context); - createOrReplaceDependent(resource, context, dependent, dependentResource, "Creating"); - } else if (dependent.updatable()) { - dependentResource = dependent.update(dependentResource, resource, context); - createOrReplaceDependent(resource, context, dependent, dependentResource, "Updating"); - } else { - logOperationInfo(resource, dependent, dependentResource, "Ignoring"); - } - }); + dependents.stream().forEach(dependent -> { + var actual = dependent.getFor(resource, context); + if (actual == null || !dependent.match(actual, resource, context)) { + final var desired = dependent.desired(resource, context); + if (desired != null) { + createOrReplaceDependent(resource, context, dependent, desired, "Reconciling"); + } + } + }); return UpdateControl.noUpdate(); } diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java index 5d10762f35..2b5880cfbc 100644 --- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java +++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java @@ -159,7 +159,8 @@ public List getDependentResources() { if (HasMetadata.class.isAssignableFrom(resourceType)) { final var kubeDependent = dependentType.getAnnotation(KubernetesDependent.class); final var namespaces = - valueOrDefault(kubeDependent, KubernetesDependent::namespaces, new String[] {}); + valueOrDefault(kubeDependent, KubernetesDependent::namespaces, + this.getNamespaces().toArray(new String[0])); final var labelSelector = valueOrDefault(kubeDependent, KubernetesDependent::labelSelector, null); final var owned = valueOrDefault(kubeDependent, KubernetesDependent::owned, diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java index ecc2aa9be7..8d46b4b3f8 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java @@ -20,7 +20,6 @@ import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.RetryInfo; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Builder; import io.javaoperatorsdk.operator.sample.MySQLSchemaReconciler.SecretDependentResource; import io.javaoperatorsdk.operator.sample.schema.Schema; @@ -51,11 +50,14 @@ public MySQLSchemaReconciler(MySQLDbConfig mysqlDbConfig) { this.mysqlDbConfig = mysqlDbConfig; } - public static class SecretDependentResource - implements DependentResource, Builder { + public static class SecretDependentResource implements DependentResource { + + private static String encode(String value) { + return Base64.getEncoder().encodeToString(value.getBytes()); + } @Override - public Secret buildFor(MySQLSchema schema, Context context) { + public Secret desired(MySQLSchema schema, Context context) { return new SecretBuilder() .withNewMetadata() .withName(context.getMandatory(MYSQL_SECRET_NAME, String.class)) @@ -67,10 +69,6 @@ public Secret buildFor(MySQLSchema schema, Context context) { context.getMandatory(MYSQL_SECRET_PASSWORD, String.class))) .build(); } - - private static String encode(String value) { - return Base64.getEncoder().encodeToString(value.getBytes()); - } } @Override diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java index de4b0ece58..48c7ac62ab 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java @@ -7,7 +7,6 @@ import io.javaoperatorsdk.operator.api.config.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Builder; import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; @@ -18,8 +17,8 @@ import static java.lang.String.format; public class SchemaDependentResource - implements DependentResource, Builder, - Cleaner, Persister { + implements DependentResource, Cleaner, + Persister { private static final int POLL_PERIOD = 500; private MySQLDbConfig dbConfig; @@ -33,7 +32,7 @@ public EventSource initEventSource(EventSourceContext context) { } @Override - public Schema buildFor(MySQLSchema primary, Context context) { + public Schema desired(MySQLSchema primary, Context context) { try (Connection connection = getConnection()) { final var schema = SchemaService.createSchemaAndRelatedUser( connection, diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java index 245011a1cf..f385698a13 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java @@ -6,16 +6,13 @@ import io.javaoperatorsdk.operator.api.config.DependentResource; import io.javaoperatorsdk.operator.api.config.KubernetesDependent; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Builder; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; @KubernetesDependent(labelSelector = "app.kubernetes.io/managed-by=tomcat-operator") public class DeploymentDependentResource - implements DependentResource, Builder, - Updater { + implements DependentResource { @Override - public Deployment buildFor(Tomcat tomcat, Context context) { + public Deployment desired(Tomcat tomcat, Context context) { Deployment deployment = TomcatReconciler.loadYaml(Deployment.class, "deployment.yaml"); final ObjectMeta tomcatMetadata = tomcat.getMetadata(); final String tomcatName = tomcatMetadata.getName(); @@ -35,7 +32,7 @@ public Deployment buildFor(Tomcat tomcat, Context context) { // make sure label selector matches label (which has to be matched by service selector too) .editMetadata().addToLabels("app", tomcatName).endMetadata() .editSpec() - .editFirstContainer().withImage("tomcat:" + tomcat.getSpec().getVersion()).endContainer() + .editFirstContainer().withImage(tomcatImage(tomcat)).endContainer() .endSpec() .endTemplate() .endSpec() @@ -43,10 +40,13 @@ public Deployment buildFor(Tomcat tomcat, Context context) { return deployment; } + private String tomcatImage(Tomcat tomcat) { + return "tomcat:" + tomcat.getSpec().getVersion(); + } + @Override - public Deployment update(Deployment fetched, Tomcat tomcat, Context context) { - return new DeploymentBuilder(fetched).editSpec().editTemplate().editSpec().editFirstContainer() - .withImage("tomcat:" + tomcat.getSpec().getVersion()) - .endContainer().endSpec().endTemplate().endSpec().build(); + public boolean match(Deployment fetched, Tomcat tomcat, Context context) { + return fetched.getSpec().getTemplate().getSpec().getContainers().stream() + .findFirst().map(c -> tomcatImage(tomcat).equals(c.getImage())).orElse(false); } } diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java index b90bd0e6e2..3554c33ef9 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java @@ -5,24 +5,20 @@ import io.fabric8.kubernetes.api.model.ServiceBuilder; import io.javaoperatorsdk.operator.api.config.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Builder; -public class ServiceDependentResource - implements DependentResource, Builder { +public class ServiceDependentResource implements DependentResource { @Override - public Service buildFor(Tomcat tomcat, Context context) { + public Service desired(Tomcat tomcat, Context context) { final ObjectMeta tomcatMetadata = tomcat.getMetadata(); - final Service service = - new ServiceBuilder(TomcatReconciler.loadYaml(Service.class, "service.yaml")) - .editMetadata() - .withName(tomcatMetadata.getName()) - .withNamespace(tomcatMetadata.getNamespace()) - .endMetadata() - .editSpec() - .addToSelector("app", tomcatMetadata.getName()) - .endSpec() - .build(); - return service; + return new ServiceBuilder(TomcatReconciler.loadYaml(Service.class, "service.yaml")) + .editMetadata() + .withName(tomcatMetadata.getName()) + .withNamespace(tomcatMetadata.getNamespace()) + .endMetadata() + .editSpec() + .addToSelector("app", tomcatMetadata.getName()) + .endSpec() + .build(); } } From 1c8aaf872babcd8a139d026a3429ccf87b5d26b7 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 4 Feb 2022 09:28:55 +0100 Subject: [PATCH 2/7] refactor: move classes to more coherent locations --- .../operator/api/config/ControllerConfiguration.java | 1 + .../api/config/DefaultControllerConfiguration.java | 1 + .../operator/api/config/Dependent.java | 8 -------- .../operator/api/config/dependent/Dependent.java | 10 ++++++++++ .../DependentResourceConfiguration.java | 3 ++- .../config/{ => dependent}/KubernetesDependent.java | 2 +- .../KubernetesDependentResourceConfiguration.java | 7 +++---- .../config}/informer/InformerConfiguration.java | 3 ++- .../api/reconciler/ControllerConfiguration.java | 4 ++-- .../dependent}/DependentResource.java | 5 +++-- .../DependentResourceControllerFactory.java | 5 ++++- .../dependent/DependentResourceController.java | 8 +++++--- .../dependent/DependentResourceManager.java | 6 +++--- .../KubernetesDependentResourceController.java | 8 +++++--- .../event/source/informer/InformerEventSource.java | 1 + .../config/runtime/AnnotationConfiguration.java | 12 ++++++------ .../InformerEventSourceTestCustomReconciler.java | 4 ++-- .../operator/sample/MySQLSchemaReconciler.java | 4 ++-- .../operator/sample/SchemaDependentResource.java | 2 +- .../operator/sample/DeploymentDependentResource.java | 4 ++-- .../operator/sample/ServiceDependentResource.java | 2 +- .../operator/sample/TomcatDependentResource.java | 2 +- .../operator/sample/TomcatReconciler.java | 2 +- .../operator/sample/WebappReconciler.java | 2 +- 24 files changed, 60 insertions(+), 46 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Dependent.java create mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/Dependent.java rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/{ => dependent}/DependentResourceConfiguration.java (63%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/{ => dependent}/KubernetesDependent.java (95%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/{reconciler => config}/dependent/KubernetesDependentResourceConfiguration.java (90%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{processing/event/source => api/config}/informer/InformerConfiguration.java (97%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/{config => reconciler/dependent}/DependentResource.java (95%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/DependentResourceController.java (86%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/KubernetesDependentResourceController.java (88%) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java index 717e339514..e8008715ff 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java @@ -7,6 +7,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.ReconcilerUtils; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Constants; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceControllerFactory; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java index 41bacbbbce..188311cfdb 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java @@ -7,6 +7,7 @@ import java.util.Set; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; public class DefaultControllerConfiguration diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Dependent.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Dependent.java deleted file mode 100644 index ed013fafb0..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Dependent.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.javaoperatorsdk.operator.api.config; - -public @interface Dependent { - - Class resourceType(); - - Class type(); -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/Dependent.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/Dependent.java new file mode 100644 index 0000000000..017f4363a6 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/Dependent.java @@ -0,0 +1,10 @@ +package io.javaoperatorsdk.operator.api.config.dependent; + +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; + +public @interface Dependent { + + Class resourceType(); + + Class type(); +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfiguration.java similarity index 63% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResourceConfiguration.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfiguration.java index 15911e0418..c0f428c12d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfiguration.java @@ -1,6 +1,7 @@ -package io.javaoperatorsdk.operator.api.config; +package io.javaoperatorsdk.operator.api.config.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; public interface DependentResourceConfiguration { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/KubernetesDependent.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/KubernetesDependent.java similarity index 95% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/KubernetesDependent.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/KubernetesDependent.java index 5b9fbd38f3..e7d2ad3158 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/KubernetesDependent.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/KubernetesDependent.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.config; +package io.javaoperatorsdk.operator.api.config.dependent; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesDependentResourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/KubernetesDependentResourceConfiguration.java similarity index 90% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesDependentResourceConfiguration.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/KubernetesDependentResourceConfiguration.java index 23d37881b4..6872322e4f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesDependentResourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/KubernetesDependentResourceConfiguration.java @@ -1,14 +1,13 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.api.config.dependent; import java.util.Set; import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.ConfigurationService; -import io.javaoperatorsdk.operator.api.config.DependentResource; -import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; -import io.javaoperatorsdk.operator.processing.event.source.informer.InformerConfiguration; public interface KubernetesDependentResourceConfiguration extends InformerConfiguration, DependentResourceConfiguration { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java similarity index 97% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerConfiguration.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java index 087e206f8b..c4d747a990 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.processing.event.source.informer; +package io.javaoperatorsdk.operator.api.config.informer; import java.util.Collections; import java.util.Objects; @@ -12,6 +12,7 @@ import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; +import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; public interface InformerConfiguration extends ResourceConfiguration { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java index 4db09c9cc8..85eed38025 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java @@ -6,8 +6,8 @@ import java.lang.annotation.Target; import java.util.concurrent.TimeUnit; -import io.javaoperatorsdk.operator.api.config.Dependent; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceController; +import io.javaoperatorsdk.operator.api.config.dependent.Dependent; +import io.javaoperatorsdk.operator.processing.dependent.DependentResourceController; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; @Retention(RetentionPolicy.RUNTIME) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java similarity index 95% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java index 30798a8aa5..037e3dce5f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java @@ -1,6 +1,7 @@ -package io.javaoperatorsdk.operator.api.config; +package io.javaoperatorsdk.operator.api.reconciler.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.processing.event.source.EventSource; @@ -8,7 +9,7 @@ public interface DependentResource { default EventSource initEventSource(EventSourceContext

context) { throw new IllegalStateException("Must be implemented if not automatically provided by the SDK"); - }; + } default Class resourceType() { return (Class) Utils.getFirstTypeArgumentFromInterface(getClass()); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java index dd11a7a706..e52daed1ba 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java @@ -3,7 +3,10 @@ import java.lang.reflect.InvocationTargetException; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependentResourceConfiguration; +import io.javaoperatorsdk.operator.processing.dependent.DependentResourceController; +import io.javaoperatorsdk.operator.processing.dependent.KubernetesDependentResourceController; public interface DependentResourceControllerFactory

{ diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java similarity index 86% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java index e4ffa9d9c5..ac9e367380 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java @@ -1,10 +1,12 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.DependentResource; -import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; public class DependentResourceController> diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index 8795bcced0..f15fa2d45b 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -8,7 +8,8 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependentResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ContextInitializer; import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; @@ -18,8 +19,7 @@ import io.javaoperatorsdk.operator.api.reconciler.Ignore; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceController; -import io.javaoperatorsdk.operator.api.reconciler.dependent.KubernetesDependentResourceController; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.Controller; import io.javaoperatorsdk.operator.processing.event.source.EventSource; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesDependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java similarity index 88% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesDependentResourceController.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java index 172e9cb0d9..7a9a595cc9 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesDependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java @@ -1,14 +1,16 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.KubernetesClient; -import io.javaoperatorsdk.operator.api.config.DependentResource; +import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; -import io.javaoperatorsdk.operator.processing.event.source.informer.InformerConfiguration; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; public class KubernetesDependentResourceController diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java index fa9e516585..3def733bd8 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.informers.ResourceEventHandler; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.processing.event.Event; import io.javaoperatorsdk.operator.processing.event.EventHandler; diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java index 2b5880cfbc..19e31e932b 100644 --- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java +++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java @@ -11,16 +11,16 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ConfigurationService; -import io.javaoperatorsdk.operator.api.config.Dependent; -import io.javaoperatorsdk.operator.api.config.DependentResource; -import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration; -import io.javaoperatorsdk.operator.api.config.KubernetesDependent; +import io.javaoperatorsdk.operator.api.config.dependent.Dependent; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependent; +import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.dependent.KubernetesDependentResourceConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters; -import io.javaoperatorsdk.operator.processing.event.source.informer.InformerConfiguration; @SuppressWarnings("rawtypes") public class AnnotationConfiguration diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java index 2a04b85d19..33128a6b8c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java @@ -8,12 +8,12 @@ import org.slf4j.LoggerFactory; import io.fabric8.kubernetes.api.model.ConfigMap; -import io.javaoperatorsdk.operator.api.config.Dependent; -import io.javaoperatorsdk.operator.api.config.DependentResource; +import io.javaoperatorsdk.operator.api.config.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java index 8d46b4b3f8..3d4d7772ab 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java @@ -9,8 +9,7 @@ import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.SecretBuilder; -import io.javaoperatorsdk.operator.api.config.Dependent; -import io.javaoperatorsdk.operator.api.config.DependentResource; +import io.javaoperatorsdk.operator.api.config.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ContextInitializer; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; @@ -20,6 +19,7 @@ import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.RetryInfo; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.sample.MySQLSchemaReconciler.SecretDependentResource; import io.javaoperatorsdk.operator.sample.schema.Schema; diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java index 48c7ac62ab..6ca9721c05 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java @@ -4,10 +4,10 @@ import java.sql.DriverManager; import java.sql.SQLException; -import io.javaoperatorsdk.operator.api.config.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.polling.PerResourcePollingEventSource; diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java index f385698a13..f544399365 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java @@ -3,9 +3,9 @@ import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; -import io.javaoperatorsdk.operator.api.config.DependentResource; -import io.javaoperatorsdk.operator.api.config.KubernetesDependent; +import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependent; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; @KubernetesDependent(labelSelector = "app.kubernetes.io/managed-by=tomcat-operator") public class DeploymentDependentResource diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java index 3554c33ef9..e93bb6886a 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java @@ -3,8 +3,8 @@ import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServiceBuilder; -import io.javaoperatorsdk.operator.api.config.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; public class ServiceDependentResource implements DependentResource { diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatDependentResource.java index 9dd49466ab..abb4e62358 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatDependentResource.java @@ -3,8 +3,8 @@ import java.util.Set; import java.util.stream.Collectors; -import io.javaoperatorsdk.operator.api.config.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; import io.javaoperatorsdk.operator.processing.event.source.EventSourceContextAware; diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java index 32f7927f44..d2d2a6c96c 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java @@ -11,7 +11,7 @@ import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentStatus; import io.fabric8.kubernetes.client.utils.Serialization; -import io.javaoperatorsdk.operator.api.config.Dependent; +import io.javaoperatorsdk.operator.api.config.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java index 9e1f6f677f..8f7b682d62 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java @@ -17,6 +17,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.dsl.ExecListener; import io.fabric8.kubernetes.client.dsl.ExecWatch; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; @@ -28,7 +29,6 @@ import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; -import io.javaoperatorsdk.operator.processing.event.source.informer.InformerConfiguration; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; @ControllerConfiguration From 2d885f1ed0d9598af95f8e6750d39297f32bbaa5 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 4 Feb 2022 09:31:33 +0100 Subject: [PATCH 3/7] refactor: remove DependentResourceControllerFactory --- .../api/config/ControllerConfiguration.java | 5 ---- .../DependentResourceControllerFactory.java | 29 ------------------- .../dependent/DependentResourceManager.java | 28 ++++++++++++++---- 3 files changed, 23 insertions(+), 39 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java index e8008715ff..c077a7876d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java @@ -9,7 +9,6 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Constants; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceControllerFactory; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters; @@ -55,10 +54,6 @@ default List getDependentResources() { return Collections.emptyList(); } - default DependentResourceControllerFactory dependentFactory() { - return new DependentResourceControllerFactory<>() {}; - } - default Optional reconciliationMaxInterval() { return Optional.of(Duration.ofHours(10L)); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java deleted file mode 100644 index e52daed1ba..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceControllerFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; - -import java.lang.reflect.InvocationTargetException; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; -import io.javaoperatorsdk.operator.api.config.dependent.KubernetesDependentResourceConfiguration; -import io.javaoperatorsdk.operator.processing.dependent.DependentResourceController; -import io.javaoperatorsdk.operator.processing.dependent.KubernetesDependentResourceController; - -public interface DependentResourceControllerFactory

{ - - default , R, C extends DependentResourceConfiguration> T from( - C config) { - try { - final var dependentResource = config.getDependentResourceClass().getConstructor() - .newInstance(); - if (config instanceof KubernetesDependentResourceConfiguration) { - return (T) new KubernetesDependentResourceController(dependentResource, - (KubernetesDependentResourceConfiguration) config); - } else { - return (T) new DependentResourceController(dependentResource, config); - } - } catch (NoSuchMethodException | InvocationTargetException | InstantiationException - | IllegalAccessException e) { - throw new IllegalArgumentException(e); - } - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index f15fa2d45b..3002258ae2 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -1,5 +1,6 @@ package io.javaoperatorsdk.operator.processing.dependent; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; @@ -47,7 +48,7 @@ public List prepareEventSources(EventSourceContext context) { List sources = new ArrayList<>(configured.size() + 5); configured.forEach(dependent -> { - final var dependentResourceController = configuration.dependentFactory().from(dependent); + final var dependentResourceController = from(dependent); dependents.add(dependentResourceController); sources.add(dependentResourceController.initEventSource(context)); }); @@ -67,12 +68,12 @@ public void injectInto(EventSourceContext context) { public UpdateControl reconcile(R resource, Context context) { initContextIfNeeded(resource, context); - dependents.stream().forEach(dependent -> { + dependents.forEach(dependent -> { var actual = dependent.getFor(resource, context); if (actual == null || !dependent.match(actual, resource, context)) { final var desired = dependent.desired(resource, context); if (desired != null) { - createOrReplaceDependent(resource, context, dependent, desired, "Reconciling"); + createOrReplaceDependent(resource, context, dependent, desired); } } }); @@ -104,14 +105,14 @@ public DeleteControl cleanup(R resource, Context context) { private void createOrReplaceDependent(R primaryResource, Context context, DependentResourceController dependentController, - Object dependentResource, String operationDescription) { + Object dependentResource) { // add owner reference if needed if (dependentResource instanceof HasMetadata && ((KubernetesDependentResourceController) dependentController).owned()) { ((HasMetadata) dependentResource).addOwnerReference(primaryResource); } - logOperationInfo(primaryResource, dependentController, dependentResource, operationDescription); + logOperationInfo(primaryResource, dependentController, dependentResource, "Reconciling"); // commit the changes // todo: add metrics timing for dependent resource @@ -134,4 +135,21 @@ private void initContextIfNeeded(R resource, Context context) { initializer.initContext(resource, context); } } + + private DependentResourceController from(DependentResourceConfiguration config) { + try { + final var dependentResource = + (DependentResource) config.getDependentResourceClass().getConstructor() + .newInstance(); + if (config instanceof KubernetesDependentResourceConfiguration) { + return new KubernetesDependentResourceController(dependentResource, + (KubernetesDependentResourceConfiguration) config); + } else { + return new DependentResourceController(dependentResource, config); + } + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } } From 94f546a89a05ee966eff1ac7900a0cbfc47aa1c8 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 4 Feb 2022 09:45:13 +0100 Subject: [PATCH 4/7] refactor: remove Cleaner interface --- .../api/reconciler/dependent/Cleaner.java | 9 -------- .../dependent/DependentResource.java | 3 +++ .../DependentResourceController.java | 22 ++++++------------- .../dependent/DependentResourceManager.java | 4 +--- .../sample/SchemaDependentResource.java | 4 +--- 5 files changed, 12 insertions(+), 30 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java deleted file mode 100644 index a6a3d691be..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.Context; - -public interface Cleaner { - - void delete(R fetched, P primary, Context context); -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java index 037e3dce5f..e85189593a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java @@ -11,10 +11,13 @@ default EventSource initEventSource(EventSourceContext

context) { throw new IllegalStateException("Must be implemented if not automatically provided by the SDK"); } + @SuppressWarnings("unchecked") default Class resourceType() { return (Class) Utils.getFirstTypeArgumentFromInterface(getClass()); } + default void delete(R fetched, P primary, Context context) {} + /** * todo: return Optional instead? * diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java index ac9e367380..cfadf1a127 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java @@ -4,23 +4,19 @@ import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; public class DependentResourceController> - implements DependentResource, Persister, Cleaner { + implements DependentResource, Persister { - private final Cleaner cleaner; private final Persister persister; private final DependentResource delegate; private final C configuration; - - @SuppressWarnings("unchecked") + public DependentResourceController(DependentResource delegate, C configuration) { this.delegate = delegate; - cleaner = (delegate instanceof Cleaner) ? (Cleaner) delegate : null; persister = initPersister(delegate); this.configuration = configuration; } @@ -40,6 +36,11 @@ public R desired(P primary, Context context) { return delegate.desired(primary, context); } + @Override + public void delete(R fetched, P primary, Context context) { + delegate.delete(fetched, primary, context); + } + @SuppressWarnings("unchecked") protected Persister initPersister(DependentResource delegate) { if (delegate instanceof Persister) { @@ -54,11 +55,6 @@ public String descriptionFor(R resource) { return resource.toString(); } - @Override - public void delete(R fetched, P primary, Context context) { - cleaner.delete(fetched, primary, context); - } - public Class getResourceType() { return delegate.resourceType(); } @@ -68,10 +64,6 @@ public EventSource initEventSource(EventSourceContext

context) { return delegate.initEventSource(context); } - public boolean deletable() { - return cleaner != null; - } - @Override public void createOrReplace(R dependentResource, Context context) { persister.createOrReplace(dependentResource, context); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index 3002258ae2..f9ec87df2f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -85,9 +85,7 @@ public UpdateControl reconcile(R resource, Context context) { public DeleteControl cleanup(R resource, Context context) { initContextIfNeeded(resource, context); - dependents.stream() - .filter(DependentResourceController::deletable) - .forEach(dependent -> { + dependents.forEach(dependent -> { var dependentResource = dependent.getFor(resource, context); if (dependentResource != null) { dependent.delete(dependentResource, resource, context); diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java index 6ca9721c05..8079975240 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java @@ -6,7 +6,6 @@ import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; @@ -17,8 +16,7 @@ import static java.lang.String.format; public class SchemaDependentResource - implements DependentResource, Cleaner, - Persister { + implements DependentResource, Persister { private static final int POLL_PERIOD = 500; private MySQLDbConfig dbConfig; From 91c46469b0a13b0ab4634675f1c0b61915692f8d Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 4 Feb 2022 10:14:38 +0100 Subject: [PATCH 5/7] refactor: put the reconciling logic in DependentResourceController --- .../DependentResourceController.java | 56 ++++++++++++- .../dependent/DependentResourceManager.java | 78 +++---------------- ...KubernetesDependentResourceController.java | 10 +++ 3 files changed, 76 insertions(+), 68 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java index cfadf1a127..0be868e6db 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java @@ -1,20 +1,28 @@ package io.javaoperatorsdk.operator.processing.dependent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; public class DependentResourceController> - implements DependentResource, Persister { + implements DependentResource, Persister, Reconciler

{ + + private static final Logger log = LoggerFactory.getLogger(DependentResourceController.class); private final Persister persister; private final DependentResource delegate; private final C configuration; - + public DependentResourceController(DependentResource delegate, C configuration) { this.delegate = delegate; persister = initPersister(delegate); @@ -77,4 +85,48 @@ public R getFor(P primary, Context context) { public C getConfiguration() { return configuration; } + + @Override + public UpdateControl

reconcile(P resource, Context context) { + var actual = getFor(resource, context); + if (actual == null || !match(actual, resource, context)) { + final var desired = desired(resource, context); + if (desired != null) { + createOrReplaceDependent(resource, desired, context); + } + } + return UpdateControl.noUpdate(); + } + + @Override + public DeleteControl cleanup(P primary, Context context) { + var dependent = getFor(primary, context); + if (dependent != null) { + delete(dependent, primary, context); + logOperationInfo(primary, dependent, "Deleting"); + } else { + log.info("Ignoring already deleted {} for '{}' {}", + getResourceType().getName(), + primary.getMetadata().getName(), + primary.getKind()); + } + return Reconciler.super.cleanup(primary, context); + } + + protected void createOrReplaceDependent(P primary, R dependent, Context context) { + logOperationInfo(primary, dependent, "Reconciling"); + + // commit the changes + // todo: add metrics timing for dependent resource + createOrReplace(dependent, context); + } + + private void logOperationInfo(P resource, R dependentResource, String operationDescription) { + if (log.isInfoEnabled()) { + log.info("{} {} for '{}' {}", operationDescription, + descriptionFor(dependentResource), + resource.getMetadata().getName(), + resource.getKind()); + } + } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index f9ec87df2f..8ab04d7d09 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -4,9 +4,6 @@ import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfiguration; @@ -26,23 +23,20 @@ @SuppressWarnings({"rawtypes", "unchecked"}) @Ignore -public class DependentResourceManager implements EventSourceInitializer, - EventSourceContextInjector, Reconciler { - - private static final Logger log = LoggerFactory.getLogger(DependentResourceManager.class); - - private final Reconciler reconciler; - private final ControllerConfiguration configuration; +public class DependentResourceManager

implements EventSourceInitializer

, + EventSourceContextInjector, Reconciler

{ + private final Reconciler

reconciler; + private final ControllerConfiguration

configuration; private List dependents; - public DependentResourceManager(Controller controller) { + public DependentResourceManager(Controller

controller) { this.reconciler = controller.getReconciler(); this.configuration = controller.getConfiguration(); } @Override - public List prepareEventSources(EventSourceContext context) { + public List prepareEventSources(EventSourceContext

context) { final List configured = configuration.getDependentResources(); dependents = new ArrayList<>(configured.size()); @@ -65,71 +59,23 @@ public void injectInto(EventSourceContext context) { } @Override - public UpdateControl reconcile(R resource, Context context) { + public UpdateControl

reconcile(P resource, Context context) { initContextIfNeeded(resource, context); - - dependents.forEach(dependent -> { - var actual = dependent.getFor(resource, context); - if (actual == null || !dependent.match(actual, resource, context)) { - final var desired = dependent.desired(resource, context); - if (desired != null) { - createOrReplaceDependent(resource, context, dependent, desired); - } - } - }); - + dependents.forEach(dependent -> dependent.reconcile(resource, context)); return UpdateControl.noUpdate(); } @Override - public DeleteControl cleanup(R resource, Context context) { + public DeleteControl cleanup(P resource, Context context) { initContextIfNeeded(resource, context); - - dependents.forEach(dependent -> { - var dependentResource = dependent.getFor(resource, context); - if (dependentResource != null) { - dependent.delete(dependentResource, resource, context); - logOperationInfo(resource, dependent, dependentResource, "Deleting"); - } else { - log.info("Ignoring already deleted {} for '{}' {}", - dependent.getResourceType().getName(), - resource.getMetadata().getName(), - configuration.getResourceTypeName()); - } - }); - + dependents.forEach(dependent -> dependent.cleanup(resource, context)); return Reconciler.super.cleanup(resource, context); } - private void createOrReplaceDependent(R primaryResource, - Context context, DependentResourceController dependentController, - Object dependentResource) { - // add owner reference if needed - if (dependentResource instanceof HasMetadata - && ((KubernetesDependentResourceController) dependentController).owned()) { - ((HasMetadata) dependentResource).addOwnerReference(primaryResource); - } - - logOperationInfo(primaryResource, dependentController, dependentResource, "Reconciling"); - - // commit the changes - // todo: add metrics timing for dependent resource - dependentController.createOrReplace(dependentResource, context); - } - - private void logOperationInfo(R resource, DependentResourceController dependent, - Object dependentResource, String operationDescription) { - if (log.isInfoEnabled()) { - log.info("{} {} for '{}' {}", operationDescription, - dependent.descriptionFor(dependentResource), - resource.getMetadata().getName(), - configuration.getResourceTypeName()); - } - } - private void initContextIfNeeded(R resource, Context context) { + private void initContextIfNeeded(P resource, Context context) { if (reconciler instanceof ContextInitializer) { - final var initializer = (ContextInitializer) reconciler; + final var initializer = (ContextInitializer

) reconciler; initializer.initContext(resource, context); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java index 7a9a595cc9..d2a402b5d4 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java @@ -21,6 +21,7 @@ public class KubernetesDependentResourceController informer; + @SuppressWarnings("unchecked") public KubernetesDependentResourceController(DependentResource delegate, KubernetesDependentResourceConfiguration configuration) { super(delegate, configuration); @@ -43,6 +44,7 @@ public KubernetesDependentResourceController(DependentResource delegate, configuration.getDependentResourceClass()); } + @SuppressWarnings("unchecked") @Override protected Persister initPersister(DependentResource delegate) { return (delegate instanceof Persister) ? (Persister) delegate : this; @@ -75,4 +77,12 @@ public R getFor(P primary, Context context) { public boolean owned() { return getConfiguration().isOwned(); } + + @Override + protected void createOrReplaceDependent(P primary, R dependent, Context context) { + if (owned()) { + dependent.addOwnerReference(primary); + } + super.createOrReplaceDependent(primary, dependent, context); + } } From 6271998c29d8e6bfe7fa50d9060014e2650e88bd Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 4 Feb 2022 10:20:51 +0100 Subject: [PATCH 6/7] refactor: return DependentResource.desired now returns Optional --- .../api/reconciler/dependent/DependentResource.java | 12 ++++++------ .../dependent/DependentResourceController.java | 8 ++++---- .../operator/sample/MySQLSchemaReconciler.java | 7 ++++--- .../operator/sample/SchemaDependentResource.java | 5 +++-- .../operator/sample/DeploymentDependentResource.java | 6 ++++-- .../operator/sample/ServiceDependentResource.java | 8 +++++--- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java index e85189593a..df144ade1f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java @@ -1,5 +1,7 @@ package io.javaoperatorsdk.operator.api.reconciler.dependent; +import java.util.Optional; + import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.reconciler.Context; @@ -19,23 +21,21 @@ default Class resourceType() { default void delete(R fetched, P primary, Context context) {} /** - * todo: return Optional instead? - * * Computes the desired state of the dependent based on the state provided by the specified * primary resource. * - * The default implementation returns {@code null} which corresponds to the case where the + * The default implementation returns {@code empty} which corresponds to the case where the * associated dependent should never be created by the associated reconciler or that the global * state of the cluster doesn't allow for the resource to be created at this point. * * @param primary the primary resource associated with the reconciliation process * @param context the {@link Context} associated with the reconciliation process * @return an instance of the dependent resource matching the desired state specified by the - * primary resource or {@code null} if the dependent shouldn't be created at this point + * primary resource or {@code empty} if the dependent shouldn't be created at this point * (or ever) */ - default R desired(P primary, Context context) { - return null; + default Optional desired(P primary, Context context) { + return Optional.empty(); } /** diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java index 0be868e6db..af79ce471b 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java @@ -1,5 +1,7 @@ package io.javaoperatorsdk.operator.processing.dependent; +import java.util.Optional; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +42,7 @@ public boolean match(R actual, P primary, Context context) { } @Override - public R desired(P primary, Context context) { + public Optional desired(P primary, Context context) { return delegate.desired(primary, context); } @@ -91,9 +93,7 @@ public UpdateControl

reconcile(P resource, Context context) { var actual = getFor(resource, context); if (actual == null || !match(actual, resource, context)) { final var desired = desired(resource, context); - if (desired != null) { - createOrReplaceDependent(resource, desired, context); - } + desired.ifPresent(d -> createOrReplaceDependent(resource, d, context)); } return UpdateControl.noUpdate(); } diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java index 3d4d7772ab..ff4fcad131 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java @@ -57,8 +57,8 @@ private static String encode(String value) { } @Override - public Secret desired(MySQLSchema schema, Context context) { - return new SecretBuilder() + public Optional desired(MySQLSchema schema, Context context) { + return Optional.of(new SecretBuilder() .withNewMetadata() .withName(context.getMandatory(MYSQL_SECRET_NAME, String.class)) .withNamespace(schema.getMetadata().getNamespace()) @@ -67,10 +67,11 @@ public Secret desired(MySQLSchema schema, Context context) { context.getMandatory(MYSQL_SECRET_USERNAME, String.class))) .addToData("MYSQL_PASSWORD", encode( context.getMandatory(MYSQL_SECRET_PASSWORD, String.class))) - .build(); + .build()); } } + @SuppressWarnings("rawtypes") @Override public void injectInto(EventSourceContext context) { context.put(MYSQL_DB_CONFIG, mysqlDbConfig); diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java index 8079975240..8ba9612029 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaDependentResource.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import java.util.Optional; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; @@ -30,7 +31,7 @@ public EventSource initEventSource(EventSourceContext context) { } @Override - public Schema desired(MySQLSchema primary, Context context) { + public Optional desired(MySQLSchema primary, Context context) { try (Connection connection = getConnection()) { final var schema = SchemaService.createSchemaAndRelatedUser( connection, @@ -41,7 +42,7 @@ public Schema desired(MySQLSchema primary, Context context) { // put the newly built schema in the context to let the reconciler know we just built it context.put(MySQLSchemaReconciler.BUILT_SCHEMA, schema); - return schema; + return Optional.of(schema); } catch (SQLException e) { MySQLSchemaReconciler.log.error("Error while creating Schema", e); throw new IllegalStateException(e); diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java index f544399365..58200df988 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java @@ -1,5 +1,7 @@ package io.javaoperatorsdk.operator.sample; +import java.util.Optional; + import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; @@ -12,7 +14,7 @@ public class DeploymentDependentResource implements DependentResource { @Override - public Deployment desired(Tomcat tomcat, Context context) { + public Optional desired(Tomcat tomcat, Context context) { Deployment deployment = TomcatReconciler.loadYaml(Deployment.class, "deployment.yaml"); final ObjectMeta tomcatMetadata = tomcat.getMetadata(); final String tomcatName = tomcatMetadata.getName(); @@ -37,7 +39,7 @@ public Deployment desired(Tomcat tomcat, Context context) { .endTemplate() .endSpec() .build(); - return deployment; + return Optional.of(deployment); } private String tomcatImage(Tomcat tomcat) { diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java index e93bb6886a..52d043203b 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java @@ -1,5 +1,7 @@ package io.javaoperatorsdk.operator.sample; +import java.util.Optional; + import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServiceBuilder; @@ -9,9 +11,9 @@ public class ServiceDependentResource implements DependentResource { @Override - public Service desired(Tomcat tomcat, Context context) { + public Optional desired(Tomcat tomcat, Context context) { final ObjectMeta tomcatMetadata = tomcat.getMetadata(); - return new ServiceBuilder(TomcatReconciler.loadYaml(Service.class, "service.yaml")) + return Optional.of(new ServiceBuilder(TomcatReconciler.loadYaml(Service.class, "service.yaml")) .editMetadata() .withName(tomcatMetadata.getName()) .withNamespace(tomcatMetadata.getNamespace()) @@ -19,6 +21,6 @@ public Service desired(Tomcat tomcat, Context context) { .editSpec() .addToSelector("app", tomcatMetadata.getName()) .endSpec() - .build(); + .build()); } } From 83efe798ea6d2bdc20cdc51eb60b8c1a8e5f5dd3 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 4 Feb 2022 10:27:16 +0100 Subject: [PATCH 7/7] chore: add @Ignore to mark internal Reconciler implementations --- .../processing/dependent/DependentResourceController.java | 2 ++ .../dependent/KubernetesDependentResourceController.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java index af79ce471b..d0004111af 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceController.java @@ -10,12 +10,14 @@ import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.Ignore; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.EventSource; +@Ignore public class DependentResourceController> implements DependentResource, Persister, Reconciler

{ diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java index d2a402b5d4..63d533193b 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/KubernetesDependentResourceController.java @@ -6,6 +6,7 @@ import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.Ignore; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Persister; import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; @@ -13,6 +14,7 @@ import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; +@Ignore public class KubernetesDependentResourceController extends DependentResourceController> {