Skip to content

Commit

Permalink
Merge pull request #318 from java-operator-sdk/fixes
Browse files Browse the repository at this point in the history
Fixes
  • Loading branch information
metacosm authored Jan 26, 2021
2 parents 03b6517 + 7608163 commit cb585d7
Show file tree
Hide file tree
Showing 23 changed files with 369 additions and 181 deletions.
149 changes: 87 additions & 62 deletions operator-framework-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,97 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>1.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>1.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>operator-framework-core</artifactId>
<name>Operator SDK - Framework - Core</name>
<description>Core framework for implementing Kubernetes operators</description>
<packaging>jar</packaging>
<artifactId>operator-framework-core</artifactId>
<name>Operator SDK - Framework - Core</name>
<description>Core framework for implementing Kubernetes operators</description>
<packaging>jar</packaging>

<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
</plugin>
<plugin>
<!-- Used to generate the version / commit information -->
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.0.3</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>initialize</phase>
</execution>
</executions>
<configuration>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/version.properties
</generateGitPropertiesFilename>
<includeOnlyProperties>
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
<includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
</includeOnlyProperties>
<commitIdGenerationMode>full</commitIdGenerationMode>
</configuration>
</plugin>
</plugins>
</build>


<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>openshift-client</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>openshift-client</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.13.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.18.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.13.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.18.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.javaoperatorsdk.operator;

import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.api.Controller;
import io.javaoperatorsdk.operator.api.ResourceController;
import java.util.Locale;
Expand All @@ -13,11 +12,6 @@ public static String getDefaultFinalizerName(String crdName) {
return crdName + FINALIZER_NAME_SUFFIX;
}

public static boolean hasGivenFinalizer(CustomResource resource, String finalizer) {
return resource.getMetadata().getFinalizers() != null
&& resource.getMetadata().getFinalizers().contains(finalizer);
}

public static String getNameFor(Class<? extends ResourceController> controllerClass) {
// if the controller annotation has a name attribute, use it
final var annotation = controllerClass.getAnnotation(Controller.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import io.javaoperatorsdk.operator.processing.event.DefaultEventSourceManager;
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEventSource;
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
import io.javaoperatorsdk.operator.processing.retry.Retry;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -29,11 +28,44 @@ public Operator(KubernetesClient k8sClient, ConfigurationService configurationSe
this.configurationService = configurationService;
}

/**
* Finishes the operator startup process. This is mostly used in injection-aware applications
* where there is no obvious entrypoint to the application which can trigger the injection process
* and start the cluster monitoring processes.
*/
public void start() {
final var version = configurationService.getVersion();
log.info(
"Operator {} (commit: {}) built on {} starting...",
version.getSdkVersion(),
version.getCommit(),
version.getBuiltTime());
}

/**
* Registers the specified controller with this operator.
*
* @param controller the controller to register
* @param <R> the {@code CustomResource} type associated with the controller
* @throws OperatorException if a problem occurred during the registration process
*/
public <R extends CustomResource> void register(ResourceController<R> controller)
throws OperatorException {
register(controller, null);
}

/**
* Registers the specified controller with this operator, overriding its default configuration by
* the specified one (usually created via {@link
* io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider#override(ControllerConfiguration)},
* passing it the controller's original configuration.
*
* @param controller the controller to register
* @param configuration the configuration with which we want to register the controller, if {@code
* null}, the controller's orginal configuration is used
* @param <R> the {@code CustomResource} type associated with the controller
* @throws OperatorException if a problem occurred during the registration process
*/
public <R extends CustomResource> void register(
ResourceController<R> controller, ControllerConfiguration<R> configuration)
throws OperatorException {
Expand All @@ -49,55 +81,57 @@ public <R extends CustomResource> void register(
if (configuration == null) {
configuration = existing;
}

final var retry = GenericRetry.fromConfiguration(configuration.getRetryConfiguration());
final var targetNamespaces = configuration.getNamespaces().toArray(new String[] {});
registerController(controller, configuration.watchAllNamespaces(), retry, targetNamespaces);
}
}
Class<R> resClass = configuration.getCustomResourceClass();
String finalizer = configuration.getFinalizer();
final var client = k8sClient.customResources(resClass);
EventDispatcher dispatcher =
new EventDispatcher(
controller, finalizer, new EventDispatcher.CustomResourceFacade(client));

@SuppressWarnings("rawtypes")
private <R extends CustomResource> void registerController(
ResourceController<R> controller,
boolean watchAllNamespaces,
Retry retry,
String... targetNamespaces)
throws OperatorException {
final var configuration = configurationService.getConfigurationFor(controller);
Class<R> resClass = configuration.getCustomResourceClass();
String finalizer = configuration.getFinalizer();
MixedOperation client = k8sClient.customResources(resClass);
EventDispatcher eventDispatcher =
new EventDispatcher(
controller, finalizer, new EventDispatcher.CustomResourceFacade(client));
// check that the custom resource is known by the cluster
final var crdName = configuration.getCRDName();
final var crd =
k8sClient.apiextensions().v1().customResourceDefinitions().withName(crdName).get();
final var controllerName = configuration.getName();
if (crd == null) {
throw new OperatorException(
"'"
+ crdName
+ "' CRD was not found on the cluster, controller "
+ controllerName
+ " cannot be registered");
}

CustomResourceCache customResourceCache = new CustomResourceCache();
DefaultEventHandler defaultEventHandler =
new DefaultEventHandler(
customResourceCache, eventDispatcher, controller.getClass().getName(), retry);
DefaultEventSourceManager eventSourceManager =
new DefaultEventSourceManager(defaultEventHandler, retry != null);
defaultEventHandler.setEventSourceManager(eventSourceManager);
eventDispatcher.setEventSourceManager(eventSourceManager);
CustomResourceCache customResourceCache = new CustomResourceCache();
DefaultEventHandler defaultEventHandler =
new DefaultEventHandler(customResourceCache, dispatcher, controllerName, retry);
DefaultEventSourceManager eventSourceManager =
new DefaultEventSourceManager(defaultEventHandler, retry != null);
defaultEventHandler.setEventSourceManager(eventSourceManager);
dispatcher.setEventSourceManager(eventSourceManager);

controller.init(eventSourceManager);
CustomResourceEventSource customResourceEventSource =
createCustomResourceEventSource(
client,
customResourceCache,
watchAllNamespaces,
targetNamespaces,
defaultEventHandler,
configuration.isGenerationAware(),
finalizer);
eventSourceManager.registerCustomResourceEventSource(customResourceEventSource);
controller.init(eventSourceManager);
final boolean watchAllNamespaces = configuration.watchAllNamespaces();
CustomResourceEventSource customResourceEventSource =
createCustomResourceEventSource(
client,
customResourceCache,
watchAllNamespaces,
targetNamespaces,
defaultEventHandler,
configuration.isGenerationAware(),
finalizer);
eventSourceManager.registerCustomResourceEventSource(customResourceEventSource);

log.info(
"Registered Controller: '{}' for CRD: '{}' for namespaces: {}",
controller.getClass().getSimpleName(),
resClass,
targetNamespaces.length == 0
? "[all/client namespace]"
: Arrays.toString(targetNamespaces));
log.info(
"Registered Controller: '{}' for CRD: '{}' for namespaces: {}",
controller.getClass().getSimpleName(),
resClass,
watchAllNamespaces ? "[all namespaces]" : Arrays.toString(targetNamespaces));
}
}

private CustomResourceEventSource createCustomResourceEventSource(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
public abstract class AbstractConfigurationService implements ConfigurationService {

private final Map<String, ControllerConfiguration> configurations = new ConcurrentHashMap<>();
private final Version version;

public AbstractConfigurationService(Version version) {
this.version = version;
}

protected <R extends CustomResource> void register(ControllerConfiguration<R> config) {
final var name = config.getName();
Expand Down Expand Up @@ -41,4 +46,9 @@ public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor
public Set<String> getKnownControllerNames() {
return configurations.keySet();
}

@Override
public Version getVersion() {
return version;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,41 @@
import io.javaoperatorsdk.operator.api.ResourceController;
import java.util.Set;

/** An interface from which to retrieve configuration information. */
public interface ConfigurationService {

/**
* Retrieves the configuration associated with the specified controller
*
* @param controller the controller we want the configuration of
* @param <R> the {@code CustomResource} type associated with the specified controller
* @return the {@link ControllerConfiguration} associated with the specified controller or {@code
* null} if no configuration exists for the controller
*/
<R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
ResourceController<R> controller);

/**
* Retrieves the Kubernetes client configuration
*
* @return the configuration of the Kubernetes client, defaulting to the provided
* auto-configuration
*/
default Config getClientConfiguration() {
return Config.autoConfigure(null);
}

/**
* Retrieves the set of the names of controllers for which a configuration exists
*
* @return the set of known controller names
*/
Set<String> getKnownControllerNames();

/**
* Retrieves the {@link Version} information associated with this particular instance of the SDK
*
* @return the version information
*/
Version getVersion();
}
Loading

0 comments on commit cb585d7

Please sign in to comment.