Skip to content

Reconcile api proposal #1030

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 3 commits into from
Mar 14, 2022
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 @@ -26,25 +26,27 @@ public AbstractDependentResource() {
}

@Override
public void reconcile(P primary, Context<P> context) {
final var creatable = isCreatable(primary, context);
final var updatable = isUpdatable(primary, context);
if (creatable || updatable) {
var maybeActual = getResource(primary);
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
final var isCreatable = isCreatable(primary, context);
final var isUpdatable = isUpdatable(primary, context);
var maybeActual = getResource(primary);
if (isCreatable || isUpdatable) {
if (maybeActual.isEmpty()) {
if (creatable) {
if (isCreatable) {
var desired = desired(primary, context);
log.debug("Creating dependent {} for primary {}", desired, primary);
handleCreate(desired, primary, context);
var createdResource = handleCreate(desired, primary, context);
return ReconcileResult.resourceCreated(createdResource);
}
} else {
final var actual = maybeActual.get();
if (updatable) {
if (isUpdatable) {
final var match = updater.match(actual, primary, context);
if (!match.matched()) {
final var desired = match.computedDesired().orElse(desired(primary, context));
log.debug("Updating dependent {} for primary {}", desired, primary);
handleUpdate(actual, desired, primary, context);
var updatedResource = handleUpdate(actual, desired, primary, context);
return ReconcileResult.resourceUpdated(updatedResource);
}
} else {
log.debug("Update skipped for dependent {} as it matched the existing one", actual);
Expand All @@ -55,15 +57,17 @@ public void reconcile(P primary, Context<P> context) {
"Dependent {} is read-only, implement Creator and/or Updater interfaces to modify it",
getClass().getSimpleName());
}
return ReconcileResult.noOperation(maybeActual.orElse(null));
}

protected void handleCreate(R desired, P primary, Context<P> context) {
protected R handleCreate(R desired, P primary, Context<P> context) {
ResourceID resourceID = ResourceID.fromResource(primary);
R created = null;
try {
prepareEventFiltering(desired, resourceID);
created = creator.create(desired, primary, context);
cacheAfterCreate(resourceID, created);
return created;
} catch (RuntimeException e) {
cleanupAfterEventFiltering(desired, resourceID, created);
throw e;
Expand Down Expand Up @@ -97,13 +101,14 @@ private void prepareEventFiltering(R desired, ResourceID resourceID) {
}
}

protected void handleUpdate(R actual, R desired, P primary, Context<P> context) {
protected R handleUpdate(R actual, R desired, P primary, Context<P> context) {
ResourceID resourceID = ResourceID.fromResource(primary);
R updated = null;
try {
prepareEventFiltering(desired, resourceID);
updated = updater.update(actual, desired, primary, context);
cacheAfterUpdate(actual, resourceID, updated);
return updated;
} catch (RuntimeException e) {
cleanupAfterEventFiltering(desired, resourceID, updated);
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import io.javaoperatorsdk.operator.api.reconciler.Context;

public interface DependentResource<R, P extends HasMetadata> {
void reconcile(P primary, Context<P> context);
ReconcileResult<R> reconcile(P primary, Context<P> context);

default void cleanup(P primary, Context<P> context) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.javaoperatorsdk.operator.api.reconciler.dependent;

import java.util.Optional;

public class ReconcileResult<R> {

private R resource;
private Operation operation;

public static <T> ReconcileResult<T> resourceCreated(T resource) {
return new ReconcileResult<>(resource, Operation.CREATED);
}

public static <T> ReconcileResult<T> resourceUpdated(T resource) {
return new ReconcileResult<>(resource, Operation.UPDATED);
}

public static <T> ReconcileResult<T> noOperation(T resource) {
return new ReconcileResult<>(resource, Operation.NONE);
}

private ReconcileResult(R resource, Operation operation) {
this.resource = resource;
this.operation = operation;
}

public Optional<R> getResource() {
return Optional.ofNullable(resource);
}

public Operation getOperation() {
return operation;
}

public enum Operation {
CREATED, UPDATED, NONE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.javaoperatorsdk.operator.api.reconciler.dependent.AbstractDependentResource;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredEqualsMatcher;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
import io.javaoperatorsdk.operator.processing.event.source.ConcurrentHashMapCache;
import io.javaoperatorsdk.operator.processing.event.source.UpdatableCache;
Expand Down Expand Up @@ -43,11 +44,11 @@ public Optional<R> getResource(HasMetadata primaryResource) {
public abstract Optional<R> fetchResource(HasMetadata primaryResource);

@Override
public void reconcile(P primary, Context<P> context) {
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
var resourceId = ResourceID.fromResource(primary);
Optional<R> resource = fetchResource(primary);
resource.ifPresentOrElse(r -> cache.put(resourceId, r), () -> cache.remove(resourceId));
super.reconcile(primary, context);
return super.reconcile(primary, context);
}

public void cleanup(P primary, Context<P> context) {
Expand All @@ -56,15 +57,17 @@ public void cleanup(P primary, Context<P> context) {
}

@Override
protected void handleCreate(R desired, P primary, Context<P> context) {
protected R handleCreate(R desired, P primary, Context<P> context) {
var res = this.creator.create(desired, primary, context);
cache.put(ResourceID.fromResource(primary), res);
return res;
}

@Override
protected void handleUpdate(R actual, R desired, P primary, Context<P> context) {
protected R handleUpdate(R actual, R desired, P primary, Context<P> context) {
var res = updater.update(actual, desired, primary, context);
cache.put(ResourceID.fromResource(primary), res);
return res;
}

public Matcher.Result<R> match(R actualResource, P primary, Context context) {
Expand Down