diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java index 43c61319ac..7c987262c9 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java @@ -3,8 +3,10 @@ import java.lang.annotation.Annotation; import java.time.Duration; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Function; @@ -19,7 +21,7 @@ import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.AnnotationDependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; @@ -112,19 +114,17 @@ public ResourceEventFilter

getEventFilter() { Class>[] filterTypes = (Class>[]) valueOrDefault(annotation, ControllerConfiguration::eventFilters, new Object[] {}); - if (filterTypes.length > 0) { - for (var filterType : filterTypes) { - try { - ResourceEventFilter

filter = filterType.getConstructor().newInstance(); - - if (answer == null) { - answer = filter; - } else { - answer = answer.and(filter); - } - } catch (Exception e) { - throw new IllegalArgumentException(e); + for (var filterType : filterTypes) { + try { + ResourceEventFilter

filter = filterType.getConstructor().newInstance(); + + if (answer == null) { + answer = filter; + } else { + answer = answer.and(filter); } + } catch (Exception e) { + throw new IllegalArgumentException(e); } } return answer != null ? answer : ResourceEventFilters.passthrough(); @@ -168,18 +168,42 @@ private void configureFromAnnotatedReconciler(Object instance) { } } + private final Map converters = new HashMap<>(); + @SuppressWarnings("unchecked") - private void configureFromCustomAnnotation(Object instance) { - if (instance instanceof AnnotationDependentResourceConfigurator) { - AnnotationDependentResourceConfigurator configurator = - (AnnotationDependentResourceConfigurator) instance; - final Class configurationClass = - (Class) Utils.getFirstTypeArgumentFromInterface( - instance.getClass(), AnnotationDependentResourceConfigurator.class); - final var configAnnotation = instance.getClass().getAnnotation(configurationClass); - // always called even if the annotation is null so that implementations can provide default - // values - final var config = configurator.configFrom(configAnnotation, this); + private void configureFromCustomAnnotation(DependentResource instance) { + if (instance instanceof DependentResourceConfigurator) { + final var configurator = (DependentResourceConfigurator) instance; + + // find Configured-annotated class if it exists + final Class drClass = instance.getClass(); + Class currentClass = drClass; + Configured configured = null; + while (!Object.class.equals(currentClass)) { + configured = currentClass.getAnnotation(Configured.class); + if (configured != null) { + break; + } + currentClass = currentClass.getSuperclass(); + } + + if (configured == null) { + return; + } + + // find the associated configuration annotation + final var configAnnotation = drClass.getAnnotation(configured.by()); + // and associated converter + var converter = converters.get(drClass); + if (converter == null) { + converter = Utils.instantiate(configured.converter(), + ConfigurationConverter.class, + Utils.contextFor(this, drClass, Configured.class)); + converters.put(drClass, converter); + } + // always call the converter even if the annotation is not present so that default values can + // be provided + final var config = converter.configFrom(configAnnotation, this, drClass); configurator.configureWith(config); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationConverter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationConverter.java new file mode 100644 index 0000000000..68073f36fe --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationConverter.java @@ -0,0 +1,11 @@ +package io.javaoperatorsdk.operator.api.config; + +import java.lang.annotation.Annotation; + +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; + +public interface ConfigurationConverter> { + + C configFrom(A configAnnotation, ControllerConfiguration parentConfiguration, + Class originatingClass); +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Configured.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Configured.java new file mode 100644 index 0000000000..a8ea56edce --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Configured.java @@ -0,0 +1,16 @@ +package io.javaoperatorsdk.operator.api.config; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Configured { + + Class by(); + + Class with(); + + @SuppressWarnings("rawtypes") + Class converter(); +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/AnnotationDependentResourceConfigurator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/AnnotationDependentResourceConfigurator.java deleted file mode 100644 index d65249b753..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/AnnotationDependentResourceConfigurator.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent.managed; - -import java.lang.annotation.Annotation; - -import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; - -public interface AnnotationDependentResourceConfigurator - extends DependentResourceConfigurator { - - C configFrom(A annotation, ControllerConfiguration parentConfiguration); -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java new file mode 100644 index 0000000000..2c84deb610 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java @@ -0,0 +1,62 @@ +package io.javaoperatorsdk.operator.processing.dependent.kubernetes; + +import java.util.Arrays; +import java.util.Set; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.config.ConfigurationConverter; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.Utils; +import io.javaoperatorsdk.operator.api.reconciler.Constants; +import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator; +import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; + +public class KubernetesDependentConverter implements + ConfigurationConverter, KubernetesDependentResource> { + + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public KubernetesDependentResourceConfig configFrom(KubernetesDependent configAnnotation, + ControllerConfiguration parentConfiguration, + Class> originatingClass) { + var namespaces = parentConfiguration.getNamespaces(); + var configuredNS = false; + String labelSelector = null; + OnAddFilter onAddFilter = null; + OnUpdateFilter onUpdateFilter = null; + OnDeleteFilter onDeleteFilter = null; + GenericFilter genericFilter = null; + ResourceDiscriminator resourceDiscriminator = null; + if (configAnnotation != null) { + if (!Arrays.equals(KubernetesDependent.DEFAULT_NAMESPACES, configAnnotation.namespaces())) { + namespaces = Set.of(configAnnotation.namespaces()); + configuredNS = true; + } + + final var fromAnnotation = configAnnotation.labelSelector(); + labelSelector = Constants.NO_VALUE_SET.equals(fromAnnotation) ? null : fromAnnotation; + + final var context = + Utils.contextFor(parentConfiguration, originatingClass, + configAnnotation.annotationType()); + onAddFilter = Utils.instantiate(configAnnotation.onAddFilter(), OnAddFilter.class, context); + onUpdateFilter = + Utils.instantiate(configAnnotation.onUpdateFilter(), OnUpdateFilter.class, context); + onDeleteFilter = + Utils.instantiate(configAnnotation.onDeleteFilter(), OnDeleteFilter.class, context); + genericFilter = + Utils.instantiate(configAnnotation.genericFilter(), GenericFilter.class, context); + + resourceDiscriminator = + Utils.instantiate(configAnnotation.resourceDiscriminator(), ResourceDiscriminator.class, + context); + } + + return new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS, + resourceDiscriminator, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter); + } +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java index b9d26a0c14..f48e91d4f5 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java @@ -1,6 +1,5 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; -import java.util.Arrays; import java.util.HashMap; import java.util.Optional; import java.util.Set; @@ -12,35 +11,30 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.dsl.Resource; import io.javaoperatorsdk.operator.OperatorException; -import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.config.Utils; +import io.javaoperatorsdk.operator.api.config.Configured; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Constants; 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.ResourceDiscriminator; import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.AnnotationDependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware; import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource; import io.javaoperatorsdk.operator.processing.dependent.Matcher; import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; -import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; @Ignore -@SuppressWarnings("rawtypes") +@Configured(by = KubernetesDependent.class, with = KubernetesDependentResourceConfig.class, + converter = KubernetesDependentConverter.class) public abstract class KubernetesDependentResource extends AbstractEventSourceHolderDependentResource> implements KubernetesClientAware, - AnnotationDependentResourceConfigurator> { + DependentResourceConfigurator> { private static final Logger log = LoggerFactory.getLogger(KubernetesDependentResource.class); @@ -250,46 +244,6 @@ private void cleanupAfterEventFiltering(ResourceID resourceID) { .cleanupOnCreateOrUpdateEventFiltering(resourceID); } - @Override - @SuppressWarnings("unchecked") - public KubernetesDependentResourceConfig configFrom(KubernetesDependent kubeDependent, - ControllerConfiguration parentConfiguration) { - var namespaces = parentConfiguration.getNamespaces(); - var configuredNS = false; - String labelSelector = null; - OnAddFilter onAddFilter = null; - OnUpdateFilter onUpdateFilter = null; - OnDeleteFilter onDeleteFilter = null; - GenericFilter genericFilter = null; - ResourceDiscriminator resourceDiscriminator = null; - if (kubeDependent != null) { - if (!Arrays.equals(KubernetesDependent.DEFAULT_NAMESPACES, kubeDependent.namespaces())) { - namespaces = Set.of(kubeDependent.namespaces()); - configuredNS = true; - } - - final var fromAnnotation = kubeDependent.labelSelector(); - labelSelector = Constants.NO_VALUE_SET.equals(fromAnnotation) ? null : fromAnnotation; - - final var context = - Utils.contextFor(parentConfiguration, getClass(), kubeDependent.annotationType()); - onAddFilter = Utils.instantiate(kubeDependent.onAddFilter(), OnAddFilter.class, context); - onUpdateFilter = - Utils.instantiate(kubeDependent.onUpdateFilter(), OnUpdateFilter.class, context); - onDeleteFilter = - Utils.instantiate(kubeDependent.onDeleteFilter(), OnDeleteFilter.class, context); - genericFilter = - Utils.instantiate(kubeDependent.genericFilter(), GenericFilter.class, context); - - resourceDiscriminator = - Utils.instantiate(kubeDependent.resourceDiscriminator(), ResourceDiscriminator.class, - context); - } - - return new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS, - resourceDiscriminator, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter); - } - @Override public Optional> configuration() { return Optional.ofNullable(kubernetesDependentResourceConfig); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/UtilsTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/UtilsTest.java index 11200f55d9..ec1223377c 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/UtilsTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/UtilsTest.java @@ -9,10 +9,8 @@ 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.managed.AnnotationDependentResourceConfigurator; import io.javaoperatorsdk.operator.processing.dependent.EmptyTestDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; import static org.assertj.core.api.Assertions.assertThat; @@ -96,10 +94,6 @@ void getsFirstTypeArgumentFromInterface() { assertThatIllegalArgumentException().isThrownBy( () -> Utils.getFirstTypeArgumentFromInterface(TestKubernetesDependentResource.class, DependentResource.class)); - - assertThat(Utils.getTypeArgumentFromInterfaceByIndex(TestKubernetesDependentResource.class, - AnnotationDependentResourceConfigurator.class, 1)) - .isEqualTo(KubernetesDependentResourceConfig.class); } @Test diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java index daf1964d13..8ebabb101b 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java @@ -16,6 +16,8 @@ import io.fabric8.kubernetes.api.model.ConfigMap; import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.api.config.AnnotationConfigurable; +import io.javaoperatorsdk.operator.api.config.ConfigurationConverter; +import io.javaoperatorsdk.operator.api.config.Configured; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; @@ -24,6 +26,8 @@ import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; @@ -183,6 +187,19 @@ void controllerConfigurationOnSuperClassShouldWork() { assertNotNull(config.getName()); } + @Test + @SuppressWarnings("rawtypes") + void configuringFromCustomAnnotationsShouldWork() { + var config = new AnnotationControllerConfiguration<>(new CustomAnnotationReconciler()); + final var dependents = config.getDependentResources(); + final var dep1 = ((DependentResourceConfigurator) dependents.get(0).getDependentResource()); + assertEquals(CustomAnnotatedDep.PROVIDED_VALUE, + ((CustomConfig) dep1.configuration().orElseThrow()).getValue()); + final var dep2 = ((DependentResourceConfigurator) dependents.get(1).getDependentResource()); + assertEquals(CustomConfigConverter.CONVERTER_PROVIDED_DEFAULT, + ((CustomConfig) dep2.configuration().orElseThrow()).getValue()); + } + @ControllerConfiguration( maxReconciliationInterval = @MaxReconciliationInterval(interval = 50, timeUnit = TimeUnit.SECONDS)) @@ -353,4 +370,84 @@ public UpdateControl reconcile(ConfigMap resource, Context return null; } } + + @ControllerConfiguration(dependents = { + @Dependent(type = CustomAnnotatedDep.class), + @Dependent(type = ChildCustomAnnotatedDep.class) + }) + private static class CustomAnnotationReconciler implements Reconciler { + + @Override + public UpdateControl reconcile(ConfigMap resource, Context context) + throws Exception { + return null; + } + } + + @CustomAnnotation(value = CustomAnnotatedDep.PROVIDED_VALUE) + @Configured(by = CustomAnnotation.class, with = CustomConfig.class, + converter = CustomConfigConverter.class) + private static class CustomAnnotatedDep implements DependentResource, + DependentResourceConfigurator { + + public static final int PROVIDED_VALUE = 42; + private CustomConfig config; + + @Override + public ReconcileResult reconcile(ConfigMap primary, Context context) { + return null; + } + + @Override + public Class resourceType() { + return ConfigMap.class; + } + + @Override + public void configureWith(CustomConfig config) { + this.config = config; + } + + @Override + public Optional configuration() { + return Optional.ofNullable(config); + } + } + + private static class ChildCustomAnnotatedDep extends CustomAnnotatedDep { + + } + + @Retention(RetentionPolicy.RUNTIME) + private @interface CustomAnnotation { + int value(); + } + + private static class CustomConfig { + private final int value; + + private CustomConfig(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private static class CustomConfigConverter + implements ConfigurationConverter { + static final int CONVERTER_PROVIDED_DEFAULT = 7; + + @Override + public CustomConfig configFrom(CustomAnnotation configAnnotation, + io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration, + Class originatingClass) { + if (configAnnotation == null) { + return new CustomConfig(CONVERTER_PROVIDED_DEFAULT); + } else { + return new CustomConfig(configAnnotation.value()); + } + } + } } diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java index 8fb8855e41..8cf0854952 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java @@ -12,14 +12,17 @@ import org.slf4j.LoggerFactory; import io.fabric8.kubernetes.api.model.Secret; +import io.javaoperatorsdk.operator.api.config.ConfigurationConverter; +import io.javaoperatorsdk.operator.api.config.Configured; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.AnnotationDependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.external.PerResourcePollingDependentResource; import io.javaoperatorsdk.operator.sample.MySQLDbConfig; import io.javaoperatorsdk.operator.sample.MySQLSchema; +import io.javaoperatorsdk.operator.sample.dependent.SchemaDependentResource.ResourcePollerConfigConverter; import io.javaoperatorsdk.operator.sample.schema.Schema; import io.javaoperatorsdk.operator.sample.schema.SchemaService; @@ -30,9 +33,11 @@ @SchemaConfig(pollPeriod = 700, host = "127.0.0.1", port = SchemaDependentResource.LOCAL_PORT, user = "root", password = "password") // NOSONAR: password is only used locally, example only +@Configured(by = SchemaConfig.class, with = ResourcePollerConfig.class, + converter = ResourcePollerConfigConverter.class) public class SchemaDependentResource extends PerResourcePollingDependentResource - implements AnnotationDependentResourceConfigurator, + implements DependentResourceConfigurator, Creator, Deleter { public static final String NAME = "schema"; @@ -56,18 +61,6 @@ public void configureWith(ResourcePollerConfig config) { setPollingPeriod(config.getPollPeriod()); } - @Override - public ResourcePollerConfig configFrom(SchemaConfig annotation, - ControllerConfiguration parentConfiguration) { - if (annotation != null) { - return new ResourcePollerConfig(annotation.pollPeriod(), - new MySQLDbConfig(annotation.host(), "" + annotation.port(), - annotation.user(), annotation.password())); - } - return new ResourcePollerConfig(SchemaConfig.DEFAULT_POLL_PERIOD, - MySQLDbConfig.loadFromEnvironmentVars()); - } - @Override public Schema desired(MySQLSchema primary, Context context) { return new Schema(primary.getMetadata().getName(), primary.getSpec().getEncoding()); @@ -120,4 +113,21 @@ public Set fetchResources(MySQLSchema primaryResource) { throw new RuntimeException("Error while trying read Schema", e); } } + + static class ResourcePollerConfigConverter implements + ConfigurationConverter { + + @Override + public ResourcePollerConfig configFrom(SchemaConfig configAnnotation, + ControllerConfiguration parentConfiguration, + Class originatingClass) { + if (configAnnotation != null) { + return new ResourcePollerConfig(configAnnotation.pollPeriod(), + new MySQLDbConfig(configAnnotation.host(), "" + configAnnotation.port(), + configAnnotation.user(), configAnnotation.password())); + } + return new ResourcePollerConfig(SchemaConfig.DEFAULT_POLL_PERIOD, + MySQLDbConfig.loadFromEnvironmentVars()); + } + } }