Skip to content

fix: clean up controller default name generation #282

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 6 commits into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from 4 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
@@ -1,8 +1,6 @@
package io.javaoperatorsdk.operator;

import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.api.ResourceController;
import java.util.Locale;

public class ControllerUtils {

Expand All @@ -16,20 +14,4 @@ public static boolean hasGivenFinalizer(CustomResource resource, String finalize
return resource.getMetadata().getFinalizers() != null
&& resource.getMetadata().getFinalizers().contains(finalizer);
}

public static String getDefaultNameFor(ResourceController controller) {
return getDefaultNameFor(controller.getClass());
}

public static String getDefaultNameFor(Class<? extends ResourceController> controllerClass) {
return getDefaultResourceControllerName(controllerClass.getSimpleName());
}

public static String getDefaultResourceControllerName(String rcControllerClassName) {
final var lastDot = rcControllerClassName.lastIndexOf('.');
if (lastDot > 0) {
rcControllerClassName = rcControllerClassName.substring(lastDot);
}
return rcControllerClassName.toLowerCase(Locale.ROOT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ public interface ResourceController<R extends CustomResource> {
default void init(EventSourceManager eventSourceManager) {}

default String getName() {
final var clazz = getClass();
return getNameFor(this);
}

static String getNameFor(Class<? extends ResourceController> controllerClass) {
// if the controller annotation has a name attribute, use it
final var annotation = clazz.getAnnotation(Controller.class);
final var annotation = controllerClass.getAnnotation(Controller.class);
if (annotation != null) {
final var name = annotation.name();
if (!Controller.NULL.equals(name)) {
Expand All @@ -52,6 +54,27 @@ default String getName() {
}

// otherwise, use the lower-cased full class name
return clazz.getCanonicalName().toLowerCase(Locale.ROOT);
return getDefaultNameFor(controllerClass);
}

static String getNameFor(ResourceController controller) {
return getNameFor(controller.getClass());
}

static String getDefaultNameFor(ResourceController controller) {
return getDefaultNameFor(controller.getClass());
}

static String getDefaultNameFor(Class<? extends ResourceController> controllerClass) {
return getDefaultResourceControllerName(controllerClass.getSimpleName());
}

static String getDefaultResourceControllerName(String rcControllerClassName) {
// if the name is fully qualified, extract the simple class name
final var lastDot = rcControllerClassName.lastIndexOf('.');
if (lastDot > 0) {
rcControllerClassName = rcControllerClassName.substring(lastDot);
}
return rcControllerClassName.toLowerCase(Locale.ROOT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.javaoperatorsdk.operator.api.config;

import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.api.ResourceController;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public abstract class AbstractConfigurationService implements ConfigurationService {

protected final Map<String, ControllerConfiguration> configurations = new ConcurrentHashMap<>();

protected <R extends CustomResource> void register(ControllerConfiguration<R> config) {
final var name = config.getName();
final var existing = configurations.get(name);
if (existing != null) {
throw new IllegalArgumentException(
"Controller name '"
+ name
+ "' is used by both "
+ existing.getAssociatedControllerClassName()
+ " and "
+ config.getAssociatedControllerClassName());
}
configurations.put(name, config);
}

@Override
public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
ResourceController<R> controller) {
return configurations.get(controller.getName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public interface ControllerConfiguration<R extends CustomResource> {

Class<? extends CustomResourceDoneable<R>> getDoneableClass();

String getAssociatedControllerClassName();

default boolean isClusterScoped() {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ private ControllerConfiguration createControllerConfiguration(
.filter(t -> t.name().equals(RESOURCE_CONTROLLER))
.findFirst()
.map(Type::asParameterizedType)
.orElseThrow(); // shouldn't happen since we're only dealing with ResourceController
// implementors already
// shouldn't happen since we're only dealing with ResourceController implementors
// already
.orElseThrow();
final var crType = rcInterface.arguments().get(0).name().toString();

// create ResourceController bean
Expand Down Expand Up @@ -137,11 +138,14 @@ private ControllerConfiguration createControllerConfiguration(
controllerAnnotation, "crdName", AnnotationValue::asString, EXCEPTION_SUPPLIER);
final var configuration =
new QuarkusControllerConfiguration(
resourceControllerClassName,
valueOrDefault(
controllerAnnotation,
"name",
AnnotationValue::asString,
() -> ControllerUtils.getDefaultResourceControllerName(info.simpleName())),
() ->
ResourceController.getDefaultResourceControllerName(
resourceControllerClassName)),
crdName,
valueOrDefault(
controllerAnnotation,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
package io.javaoperatorsdk.quarkus.extension;

import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.javaoperatorsdk.operator.api.ResourceController;
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;

public class QuarkusConfigurationService implements ConfigurationService {
private final Map<String, ControllerConfiguration> controllerConfigurations;
public class QuarkusConfigurationService extends AbstractConfigurationService {
@Inject KubernetesClient client;

public QuarkusConfigurationService(List<ControllerConfiguration> configurations) {
if (configurations != null && !configurations.isEmpty()) {
controllerConfigurations = new ConcurrentHashMap<>(configurations.size());
configurations.forEach(c -> controllerConfigurations.put(c.getName(), c));
} else {
controllerConfigurations = Collections.emptyMap();
configurations.forEach(this::register);
}
}

@Override
public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
ResourceController<R> controller) {
return controllerConfigurations.get(controller.getName());
}

@Override
public Config getClientConfiguration() {
return client.getConfiguration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

public class QuarkusControllerConfiguration<R extends CustomResource>
implements ControllerConfiguration<R> {
private final String associatedControllerClassName;
private final String name;
private final String crdName;
private final String finalizer;
Expand All @@ -23,6 +24,7 @@ public class QuarkusControllerConfiguration<R extends CustomResource>

@RecordableConstructor
public QuarkusControllerConfiguration(
String associatedControllerClassName,
String name,
String crdName,
String finalizer,
Expand All @@ -32,6 +34,7 @@ public QuarkusControllerConfiguration(
String crClass,
String doneableClassName,
RetryConfiguration retryConfiguration) {
this.associatedControllerClassName = associatedControllerClassName;
this.name = name;
this.crdName = crdName;
this.finalizer = finalizer;
Expand Down Expand Up @@ -87,23 +90,27 @@ public boolean isGenerationAware() {

@Override
public Class<R> getCustomResourceClass() {
try {
return (Class<R>) Thread.currentThread().getContextClassLoader().loadClass(crClass);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Couldn't find class " + crClass);
}
return (Class<R>) loadClass(crClass);
}

@Override
public Class<? extends CustomResourceDoneable<R>> getDoneableClass() {
return (Class<? extends CustomResourceDoneable<R>>) loadClass(doneableClassName);
}

private Class<?> loadClass(String className) {
try {
return (Class<CustomResourceDoneable<R>>)
Thread.currentThread().getContextClassLoader().loadClass(doneableClassName);
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Couldn't find class " + doneableClassName);
throw new IllegalArgumentException("Couldn't find class " + className);
}
}

@Override
public String getAssociatedControllerClassName() {
return associatedControllerClassName;
}

@Override
public boolean isClusterScoped() {
return clusterScoped;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@
import io.fabric8.openshift.client.DefaultOpenShiftClient;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.api.ResourceController;
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
import io.javaoperatorsdk.operator.config.runtime.AnnotationConfiguration;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand All @@ -25,9 +22,8 @@

@Configuration
@EnableConfigurationProperties({OperatorConfigurationProperties.class})
public class OperatorAutoConfiguration implements ConfigurationService {
public class OperatorAutoConfiguration extends AbstractConfigurationService {
@Autowired private OperatorConfigurationProperties configuration;
private final Map<String, ControllerConfiguration> controllers = new ConcurrentHashMap<>();

@Bean
@ConditionalOnMissingBean
Expand Down Expand Up @@ -60,18 +56,12 @@ public Operator operator(

private ResourceController<?> processController(ResourceController<?> controller) {
final var controllerPropertiesMap = configuration.getControllers();
var controllerProps = controllerPropertiesMap.get(controller.getName());
final var cfg = new ConfigurationWrapper(controller, controllerProps);
this.controllers.put(controller.getName(), cfg);
final var name = controller.getName();
var controllerProps = controllerPropertiesMap.get(name);
register(new ConfigurationWrapper(controller, controllerProps));
return controller;
}

@Override
public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
ResourceController<R> controller) {
return controllers.get(controller.getName());
}

private static class ConfigurationWrapper<R extends CustomResource>
extends AnnotationConfiguration<R> {
private final Optional<ControllerProperties> properties;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

import io.fabric8.kubernetes.client.KubernetesClient;
import io.javaoperatorsdk.operator.ControllerUtils;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.api.ResourceController;
import java.util.List;
Expand Down Expand Up @@ -39,10 +38,7 @@ public void loadsKubernetesClientPropertiesProperly() {
@Test
public void loadsRetryPropertiesProperly() {
final var retryProperties =
config
.getControllers()
.get(ControllerUtils.getDefaultNameFor(TestController.class))
.getRetry();
config.getControllers().get(ResourceController.getNameFor(TestController.class)).getRetry();
assertEquals(3, retryProperties.getMaxAttempts());
assertEquals(1000, retryProperties.getInitialInterval());
assertEquals(1.5, retryProperties.getIntervalMultiplier());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public AnnotationConfiguration(ResourceController<R> controller) {

@Override
public String getName() {
final var name = annotation.name();
return Controller.NULL.equals(name) ? ControllerUtils.getDefaultNameFor(controller) : name;
return controller.getName();
}

@Override
Expand Down Expand Up @@ -63,4 +62,9 @@ public boolean isClusterScoped() {
public Set<String> getNamespaces() {
return Set.of(annotation.namespaces());
}

@Override
public String getAssociatedControllerClassName() {
return controller.getClass().getCanonicalName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.api.ResourceController;
import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultConfigurationService implements ConfigurationService {
public class DefaultConfigurationService extends AbstractConfigurationService {

private static final ConfigurationService instance = new DefaultConfigurationService();
private final Map<String, ControllerConfiguration> configurations = new ConcurrentHashMap<>();

public static ConfigurationService instance() {
return instance;
Expand All @@ -19,15 +17,12 @@ public static ConfigurationService instance() {
@Override
public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
ResourceController<R> controller) {
if (controller == null) {
return null;
var config = super.getConfigurationFor(controller);
if (config == null) {
// create the the configuration on demand and register it
config = new AnnotationConfiguration(controller);
register(config);
}
final var name = controller.getName();
var configuration = configurations.get(name);
if (configuration == null) {
configuration = new AnnotationConfiguration(controller);
configurations.put(name, configuration);
}
return configuration;
return config;
}
}