Skip to content

Support Standard Kuberentes Resources not just CustomResource #678

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 31 commits into from
Nov 22, 2021
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c2179ac
feat!: has metada instead of CustomResource in the core of the system
csviri Nov 12, 2021
f8dcf1f
feat: simple IT
csviri Nov 12, 2021
bfed546
fix: add config map IT
csviri Nov 12, 2021
a8d14e8
fix: formatting
csviri Nov 12, 2021
ae93774
feat!: has metada instead of CustomResource in the core of the system
csviri Nov 12, 2021
4535fc4
feat: simple IT
csviri Nov 12, 2021
6853b84
fix: add config map IT
csviri Nov 12, 2021
0b21975
fix: formatting
csviri Nov 12, 2021
e02f1be
Merge remote-tracking branch 'origin/support-non-cr' into support-non-cr
csviri Nov 17, 2021
fddedb5
fix: rebase + update
csviri Nov 17, 2021
24d6194
fix: Integration Tests
csviri Nov 17, 2021
29f53c6
fix: formatting
csviri Nov 17, 2021
cbf7a14
fix: better naming? customResource -> resource
csviri Nov 17, 2021
fafe9b0
refactor: resourcId
csviri Nov 17, 2021
71bb232
fix: formatting
csviri Nov 17, 2021
4682d92
fix: added intergation test for deployment, removed config map tests
csviri Nov 18, 2021
8f08cca
fix: format
csviri Nov 18, 2021
9189a94
fix: IT test update
csviri Nov 18, 2021
0446fd6
fix: format
csviri Nov 18, 2021
ef7f9b7
Merge branch 'v2' into support-non-cr
csviri Nov 19, 2021
3d82e02
fix: merged v2, fixes
csviri Nov 19, 2021
0fa1a5f
refactor: rename method more appropriately
metacosm Nov 19, 2021
d091e96
refactor: rename method more appropriately
metacosm Nov 19, 2021
d385a0e
chore: add todo to remind us to use HasStatus when available
metacosm Nov 19, 2021
6bba18e
chore: more renaming
metacosm Nov 19, 2021
a876548
chore: add todo to remind us to use HasStatus when available
metacosm Nov 19, 2021
fdf5bab
fix: rename
csviri Nov 22, 2021
7f23e2c
Merge branch 'support-non-cr' of github.com:java-operator-sdk/java-op…
csviri Nov 22, 2021
2a96c84
fix: test timeout
csviri Nov 22, 2021
61ee5e3
fix: naming improvements and poll interval
csviri Nov 22, 2021
29d2a14
fix: test tuning
csviri Nov 22, 2021
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
7 changes: 7 additions & 0 deletions docs/documentation/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ mostly for the cases when there is a long waiting period after a delete operatio
you might want to either schedule a timed event to make sure the
`deleteResource` is executed again or use event sources get notified about the state changes of a deleted resource.

## Automatic Observed Generation Handling

## Support for Well Known (non-custom) Kubernetes Resources

A Controller can be registered for a non-custom resource, so well known Kubernetes resources like (
Ingress,Deployment,...). Note that automatic observed generation handling is not supported for these resources.

## Automatic Retries on Error

When an exception is thrown from a controller, the framework will schedule an automatic retry of the reconciliation. The
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import io.javaoperatorsdk.operator.api.monitoring.Metrics;
import io.javaoperatorsdk.operator.api.reconciler.RetryInfo;
import io.javaoperatorsdk.operator.processing.event.CustomResourceID;
import io.javaoperatorsdk.operator.processing.event.Event;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;

Expand Down Expand Up @@ -53,38 +53,38 @@ public void receivedEvent(Event event) {
}

@Override
public void cleanupDoneFor(CustomResourceID customResourceUid) {
public void cleanupDoneFor(ResourceID customResourceUid) {
incrementCounter(customResourceUid, "events.delete");
}

public void reconcileCustomResource(CustomResourceID customResourceID,
public void reconcileCustomResource(ResourceID resourceID,
RetryInfo retryInfo) {
incrementCounter(customResourceID, RECONCILIATIONS + "started",
incrementCounter(resourceID, RECONCILIATIONS + "started",
RECONCILIATIONS + "retries.number", "" + retryInfo.getAttemptCount(),
RECONCILIATIONS + "retries.last", "" + retryInfo.isLastAttempt());
}

@Override
public void finishedReconciliation(CustomResourceID customResourceID) {
incrementCounter(customResourceID, RECONCILIATIONS + "success");
public void finishedReconciliation(ResourceID resourceID) {
incrementCounter(resourceID, RECONCILIATIONS + "success");
}

public void failedReconciliation(CustomResourceID customResourceID, RuntimeException exception) {
public void failedReconciliation(ResourceID resourceID, RuntimeException exception) {
var cause = exception.getCause();
if (cause == null) {
cause = exception;
} else if (cause instanceof RuntimeException) {
cause = cause.getCause() != null ? cause.getCause() : cause;
}
incrementCounter(customResourceID, RECONCILIATIONS + "failed", "exception",
incrementCounter(resourceID, RECONCILIATIONS + "failed", "exception",
cause.getClass().getSimpleName());
}

public <T extends Map<?, ?>> T monitorSizeOf(T map, String name) {
return registry.gaugeMapSize(PREFIX + name + ".size", Collections.emptyList(), map);
}

private void incrementCounter(CustomResourceID id, String counterName, String... additionalTags) {
private void incrementCounter(ResourceID id, String counterName, String... additionalTags) {
var tags = List.of(
"name", id.getName(),
"name", id.getName(), "namespace", id.getNamespace().orElse(""),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.Version;
Expand Down Expand Up @@ -114,7 +114,7 @@ public void close() {
* @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(Reconciler<R> controller)
public <R extends HasMetadata> void register(Reconciler<R> controller)
throws OperatorException {
register(controller, null);
}
Expand All @@ -132,7 +132,7 @@ public void close() {
* @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(
public <R extends HasMetadata> void register(
Reconciler<R> reconciler, ControllerConfiguration<R> configuration)
throws OperatorException {
final var existing = configurationService.getConfigurationFor(reconciler);
Expand All @@ -157,7 +157,7 @@ public void close() {
log.info(
"Registered Controller: '{}' for CRD: '{}' for namespace(s): {}",
configuration.getName(),
configuration.getCustomResourceClass(),
configuration.getResourceClass(),
watchedNS);
}
}
Expand Down Expand Up @@ -195,7 +195,7 @@ public synchronized void stop() {

public synchronized void add(Controller controller) {
final var configuration = controller.getConfiguration();
final var crdName = configuration.getCRDName();
final var crdName = configuration.getResourceTypeName();
final var existing = controllers.get(crdName);
if (existing != null) {
throw new OperatorException("Cannot register controller '" + configuration.getName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.ControllerUtils;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;

Expand All @@ -18,15 +18,15 @@ public AbstractConfigurationService(Version version) {
this.version = version;
}

protected <R extends CustomResource<?, ?>> void register(ControllerConfiguration<R> config) {
protected <R extends HasMetadata> void register(ControllerConfiguration<R> config) {
put(config, true);
}

protected <R extends CustomResource<?, ?>> void replace(ControllerConfiguration<R> config) {
protected <R extends HasMetadata> void replace(ControllerConfiguration<R> config) {
put(config, false);
}

private <R extends CustomResource<?, ?>> void put(
private <R extends HasMetadata> void put(
ControllerConfiguration<R> config, boolean failIfExisting) {
final var name = config.getName();
if (failIfExisting) {
Expand All @@ -39,7 +39,7 @@ public AbstractConfigurationService(Version version) {
config.setConfigurationService(this);
}

protected <R extends CustomResource<?, ?>> void throwExceptionOnNameCollision(
protected <R extends HasMetadata> void throwExceptionOnNameCollision(
String newControllerClassName, ControllerConfiguration<R> existing) {
throw new IllegalArgumentException(
"Controller name '"
Expand All @@ -51,7 +51,7 @@ public AbstractConfigurationService(Version version) {
}

@Override
public <R extends CustomResource<?, ?>> ControllerConfiguration<R> getConfigurationFor(
public <R extends HasMetadata> ControllerConfiguration<R> getConfigurationFor(
Reconciler<R> controller) {
final var key = keyFor(controller);
final var configuration = configurations.get(key);
Expand All @@ -73,7 +73,7 @@ private String getControllersNameMessage() {
+ ".";
}

protected <R extends CustomResource<?, ?>> String keyFor(Reconciler<R> controller) {
protected <R extends HasMetadata> String keyFor(Reconciler<R> controller) {
return ControllerUtils.getNameFor(controller);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.javaoperatorsdk.operator.api.config;

import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.api.model.HasMetadata;

public interface Cloner {

<T extends CustomResource<?, ?>> T clone(T object);
<R extends HasMetadata> R clone(R object);

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
Expand All @@ -19,10 +20,9 @@ public interface ConfigurationService {
private final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

@Override
public <T extends CustomResource<?, ?>> T clone(T object) {
public HasMetadata clone(HasMetadata object) {
try {
return OBJECT_MAPPER.readValue(OBJECT_MAPPER.writeValueAsString(object),
(Class<T>) object.getClass());
return OBJECT_MAPPER.readValue(OBJECT_MAPPER.writeValueAsString(object), object.getClass());
} catch (JsonProcessingException e) {
throw new IllegalStateException(e);
}
Expand All @@ -37,7 +37,7 @@ public interface ConfigurationService {
* @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(
<R extends HasMetadata> ControllerConfiguration<R> getConfigurationFor(
Reconciler<R> controller);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import java.util.Set;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;

Expand Down Expand Up @@ -61,7 +61,7 @@ public ConfigurationServiceOverrider withMetrics(Metrics metrics) {
public ConfigurationService build() {
return new ConfigurationService() {
@Override
public <R extends CustomResource<?, ?>> ControllerConfiguration<R> getConfigurationFor(
public <R extends HasMetadata> ControllerConfiguration<R> getConfigurationFor(
Reconciler<R> controller) {
return original.getConfigurationFor(controller);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@
import java.util.Collections;
import java.util.Set;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.ControllerUtils;
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEventFilter;
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEventFilters;
import io.javaoperatorsdk.operator.processing.event.internal.ResourceEventFilter;
import io.javaoperatorsdk.operator.processing.event.internal.ResourceEventFilters;

public interface ControllerConfiguration<R extends CustomResource<?, ?>> {
public interface ControllerConfiguration<R extends HasMetadata> {

default String getName() {
return ControllerUtils.getDefaultReconcilerName(getAssociatedReconcilerClassName());
}

default String getCRDName() {
return CustomResource.getCRDName(getCustomResourceClass());
default String getResourceTypeName() {
return CustomResource.getCRDName(getResourceClass());
}

default String getFinalizer() {
return ControllerUtils.getDefaultFinalizerName(getCRDName());
return ControllerUtils.getDefaultFinalizerName(getResourceTypeName());
}

/**
Expand All @@ -39,7 +40,7 @@ default boolean isGenerationAware() {
return true;
}

default Class<R> getCustomResourceClass() {
default Class<R> getResourceClass() {
ParameterizedType type = (ParameterizedType) getClass().getGenericInterfaces()[0];
return (Class<R>) type.getActualTypeArguments()[0];
}
Expand Down Expand Up @@ -110,7 +111,7 @@ default boolean useFinalizer() {
*
* @return filter
*/
default CustomResourceEventFilter<R> getEventFilter() {
return CustomResourceEventFilters.passthrough();
default ResourceEventFilter<R> getEventFilter() {
return ResourceEventFilters.passthrough();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
import java.util.List;
import java.util.Set;

import io.fabric8.kubernetes.client.CustomResource;
import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEventFilter;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.processing.event.internal.ResourceEventFilter;

public class ControllerConfigurationOverrider<R extends CustomResource<?, ?>> {
public class ControllerConfigurationOverrider<R extends HasMetadata> {

private String finalizer;
private boolean generationAware;
private final Set<String> namespaces;
private RetryConfiguration retry;
private String labelSelector;
private CustomResourceEventFilter<R> customResourcePredicate;
private ResourceEventFilter<R> customResourcePredicate;
private final ControllerConfiguration<R> original;

private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
Expand Down Expand Up @@ -69,7 +69,7 @@ public ControllerConfigurationOverrider<R> withLabelSelector(String labelSelecto
}

public ControllerConfigurationOverrider<R> withCustomResourcePredicate(
CustomResourceEventFilter<R> customResourcePredicate) {
ResourceEventFilter<R> customResourcePredicate) {
this.customResourcePredicate = customResourcePredicate;
return this;
}
Expand All @@ -78,18 +78,18 @@ public ControllerConfiguration<R> build() {
return new DefaultControllerConfiguration<>(
original.getAssociatedReconcilerClassName(),
original.getName(),
original.getCRDName(),
original.getResourceTypeName(),
finalizer,
generationAware,
namespaces,
retry,
labelSelector,
customResourcePredicate,
original.getCustomResourceClass(),
original.getResourceClass(),
original.getConfigurationService());
}

public static <R extends CustomResource<?, ?>> ControllerConfigurationOverrider<R> override(
public static <R extends HasMetadata> ControllerConfigurationOverrider<R> override(
ControllerConfiguration<R> original) {
return new ControllerConfigurationOverrider<>(original);
}
Expand Down
Loading