Skip to content

Fixes #318

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 18 commits into from
Jan 26, 2021
Merged

Fixes #318

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
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