Skip to content

refactor: move getResourceClassResolver to BaseConfigurationService #2451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class BaseConfigurationService extends AbstractConfigurationService {

private static final String LOGGER_NAME = "Default ConfigurationService implementation";
private static final Logger logger = LoggerFactory.getLogger(LOGGER_NAME);
private static final ResourceClassResolver DEFAULT_RESOLVER = new DefaultResourceClassResolver();

public BaseConfigurationService(Version version) {
this(version, null);
Expand All @@ -56,6 +57,89 @@ public BaseConfigurationService() {
this(Utils.VERSION);
}

@SuppressWarnings({"unchecked", "rawtypes"})
private static List<DependentResourceSpec> dependentResources(
Workflow annotation,
ControllerConfiguration<?> controllerConfiguration) {
final var dependents = annotation.dependents();


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

final var specsMap = new LinkedHashMap<String, DependentResourceSpec>(dependents.length);
for (Dependent dependent : dependents) {
final Class<? extends DependentResource> dependentType = dependent.type();

final var dependentName = getName(dependent.name(), dependentType);
var spec = specsMap.get(dependentName);
if (spec != null) {
throw new IllegalArgumentException(
"A DependentResource named '" + dependentName + "' already exists: " + spec);
}

final var name = controllerConfiguration.getName();

var eventSourceName = dependent.useEventSourceWithName();
eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName;
final var context = Utils.contextFor(name, dependentType, null);
spec = new DependentResourceSpec(dependentType, dependentName,
Set.of(dependent.dependsOn()),
Utils.instantiate(dependent.readyPostcondition(), Condition.class, context),
Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context),
Utils.instantiate(dependent.deletePostcondition(), Condition.class, context),
Utils.instantiate(dependent.activationCondition(), Condition.class, context),
eventSourceName);

// extract potential configuration
DependentResourceConfigurationResolver.configureSpecFromConfigured(spec,
controllerConfiguration,
dependentType);

specsMap.put(dependentName, spec);
}
return specsMap.values().stream().toList();
}

private static <T> T valueOrDefault(
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration controllerConfiguration,
Function<io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration, T> mapper,
T defaultValue) {
if (controllerConfiguration == null) {
return defaultValue;
} else {
return mapper.apply(controllerConfiguration);
}
}

@SuppressWarnings("rawtypes")
private static String getName(String name, Class<? extends DependentResource> dependentType) {
if (name.isBlank()) {
name = DependentResource.defaultNameFor(dependentType);
}
return name;
}

@SuppressWarnings("unused")
private static <T> Configurator<T> configuratorFor(Class<T> instanceType,
Reconciler<?> reconciler) {
return instance -> configureFromAnnotatedReconciler(instance, reconciler);
}

@SuppressWarnings({"unchecked", "rawtypes"})
private static void configureFromAnnotatedReconciler(Object instance, Reconciler<?> reconciler) {
if (instance instanceof AnnotationConfigurable configurable) {
final Class<? extends Annotation> configurationClass =
(Class<? extends Annotation>) Utils.getFirstTypeArgumentFromSuperClassOrInterface(
instance.getClass(), AnnotationConfigurable.class);
final var configAnnotation = reconciler.getClass().getAnnotation(configurationClass);
if (configAnnotation != null) {
configurable.initFrom(configAnnotation);
}
}
}

@Override
protected void logMissingReconcilerWarning(String reconcilerKey, String reconcilersNameMessage) {
logger.warn("Configuration for reconciler '{}' was not found. {}", reconcilerKey,
Expand Down Expand Up @@ -95,6 +179,15 @@ public <R extends HasMetadata> ControllerConfiguration<R> getConfigurationFor(
return config;
}

/**
* Override if a different class resolution is needed
*
* @return the custom {@link ResourceClassResolver} implementation to use
*/
protected ResourceClassResolver getResourceClassResolver() {
return DEFAULT_RESOLVER;
}

@SuppressWarnings({"unchecked", "rawtypes"})
protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconciler<P> reconciler) {
final var annotation = reconciler.getClass().getAnnotation(
Expand All @@ -109,7 +202,7 @@ protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconcile
" annotation for reconciler: " + reconciler);
}
Class<Reconciler<P>> reconcilerClass = (Class<Reconciler<P>>) reconciler.getClass();
final var resourceClass = getResourceClassResolver().getResourceClass(reconcilerClass);
final var resourceClass = getResourceClassResolver().getPrimaryResourceClass(reconcilerClass);

final var name = ReconcilerUtils.getNameFor(reconciler);
final var generationAware = valueOrDefault(
Expand Down Expand Up @@ -192,51 +285,6 @@ public boolean handleExceptionsInReconciler() {
return config;
}

@SuppressWarnings({"unchecked", "rawtypes"})
private static List<DependentResourceSpec> dependentResources(
Workflow annotation,
ControllerConfiguration<?> controllerConfiguration) {
final var dependents = annotation.dependents();


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

final var specsMap = new LinkedHashMap<String, DependentResourceSpec>(dependents.length);
for (Dependent dependent : dependents) {
final Class<? extends DependentResource> dependentType = dependent.type();

final var dependentName = getName(dependent.name(), dependentType);
var spec = specsMap.get(dependentName);
if (spec != null) {
throw new IllegalArgumentException(
"A DependentResource named '" + dependentName + "' already exists: " + spec);
}

final var name = controllerConfiguration.getName();

var eventSourceName = dependent.useEventSourceWithName();
eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName;
final var context = Utils.contextFor(name, dependentType, null);
spec = new DependentResourceSpec(dependentType, dependentName,
Set.of(dependent.dependsOn()),
Utils.instantiate(dependent.readyPostcondition(), Condition.class, context),
Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context),
Utils.instantiate(dependent.deletePostcondition(), Condition.class, context),
Utils.instantiate(dependent.activationCondition(), Condition.class, context),
eventSourceName);

// extract potential configuration
DependentResourceConfigurationResolver.configureSpecFromConfigured(spec,
controllerConfiguration,
dependentType);

specsMap.put(dependentName, spec);
}
return specsMap.values().stream().toList();
}

protected boolean createIfNeeded() {
return true;
}
Expand All @@ -245,42 +293,4 @@ protected boolean createIfNeeded() {
public boolean checkCRDAndValidateLocalModel() {
return Utils.shouldCheckCRDAndValidateLocalModel();
}

private static <T> T valueOrDefault(
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration controllerConfiguration,
Function<io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration, T> mapper,
T defaultValue) {
if (controllerConfiguration == null) {
return defaultValue;
} else {
return mapper.apply(controllerConfiguration);
}
}

@SuppressWarnings("rawtypes")
private static String getName(String name, Class<? extends DependentResource> dependentType) {
if (name.isBlank()) {
name = DependentResource.defaultNameFor(dependentType);
}
return name;
}

@SuppressWarnings("unused")
private static <T> Configurator<T> configuratorFor(Class<T> instanceType,
Reconciler<?> reconciler) {
return instance -> configureFromAnnotatedReconciler(instance, reconciler);
}

@SuppressWarnings({"unchecked", "rawtypes"})
private static void configureFromAnnotatedReconciler(Object instance, Reconciler<?> reconciler) {
if (instance instanceof AnnotationConfigurable configurable) {
final Class<? extends Annotation> configurationClass =
(Class<? extends Annotation>) Utils.getFirstTypeArgumentFromSuperClassOrInterface(
instance.getClass(), AnnotationConfigurable.class);
final var configAnnotation = reconciler.getClass().getAnnotation(configurationClass);
if (configAnnotation != null) {
configurable.initFrom(configAnnotation);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,6 @@ default ManagedWorkflowFactory getWorkflowFactory() {
return ManagedWorkflowFactory.DEFAULT;
}

default ResourceClassResolver getResourceClassResolver() {
return new DefaultResourceClassResolver();
}

/**
* Creates a new {@link ConfigurationService} instance used to configure an
* {@link io.javaoperatorsdk.operator.Operator} instance, starting from the specified base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceFactory;

@SuppressWarnings("unused")
@SuppressWarnings({"unused", "UnusedReturnValue"})
public class ConfigurationServiceOverrider {

private static final Logger log = LoggerFactory.getLogger(ConfigurationServiceOverrider.class);
Expand All @@ -32,7 +32,6 @@ public class ConfigurationServiceOverrider {
private InformerStoppedHandler informerStoppedHandler;
private Boolean stopOnInformerErrorDuringStartup;
private Duration cacheSyncTimeout;
private ResourceClassResolver resourceClassResolver;
private Boolean ssaBasedCreateUpdateMatchForDependentResources;
private Set<Class<? extends HasMetadata>> defaultNonSSAResource;
private Boolean previousAnnotationForDependentResources;
Expand Down Expand Up @@ -128,12 +127,6 @@ public ConfigurationServiceOverrider withCacheSyncTimeout(Duration cacheSyncTime
return this;
}

public ConfigurationServiceOverrider withResourceClassResolver(
ResourceClassResolver resourceClassResolver) {
this.resourceClassResolver = resourceClassResolver;
return this;
}

public ConfigurationServiceOverrider withSSABasedCreateUpdateMatchForDependentResources(
boolean value) {
this.ssaBasedCreateUpdateMatchForDependentResources = value;
Expand Down Expand Up @@ -258,12 +251,6 @@ public Duration cacheSyncTimeout() {
return overriddenValueOrDefault(cacheSyncTimeout, ConfigurationService::cacheSyncTimeout);
}

@Override
public ResourceClassResolver getResourceClassResolver() {
return overriddenValueOrDefault(resourceClassResolver,
ConfigurationService::getResourceClassResolver);
}

@Override
public boolean ssaBasedCreateUpdateMatchForDependentResources() {
return overriddenValueOrDefault(ssaBasedCreateUpdateMatchForDependentResources,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class DefaultResourceClassResolver implements ResourceClassResolver {

@SuppressWarnings("unchecked")
@Override
public <R extends HasMetadata> Class<R> getResourceClass(
public <R extends HasMetadata> Class<R> getPrimaryResourceClass(
Class<? extends Reconciler<R>> reconcilerClass) {
return (Class<R>) Utils.getFirstTypeArgumentFromSuperClassOrInterface(reconcilerClass,
Reconciler.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

public interface ResourceClassResolver {

<R extends HasMetadata> Class<R> getResourceClass(Class<? extends Reconciler<R>> reconcilerClass);
<P extends HasMetadata> Class<P> getPrimaryResourceClass(
Class<? extends Reconciler<P>> reconcilerClass);

}
Loading