Skip to content

Commit

Permalink
feat: explicit node configuration in WorkflowBuilder (#2511)
Browse files Browse the repository at this point in the history
* feat: explicit node configuration in WorkflowBuilder

Fixes #2284

Signed-off-by: Chris Laprun <[email protected]>

* refactor: rename more appropriately

Signed-off-by: Chris Laprun <[email protected]>

---------

Signed-off-by: Chris Laprun <[email protected]>
  • Loading branch information
metacosm authored Sep 19, 2024
1 parent 1ed539b commit 706aef2
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,25 @@ public class WorkflowBuilder<P extends HasMetadata> {
private final Map<String, DependentResourceNode<?, P>> dependentResourceNodes =
new HashMap<>();
private boolean throwExceptionAutomatically = THROW_EXCEPTION_AUTOMATICALLY_DEFAULT;
private DependentResourceNode currentNode;
private boolean isCleaner = false;

public WorkflowBuilder<P> addDependentResource(DependentResource dependentResource) {
currentNode = new DependentResourceNode<>(dependentResource);
isCleaner = isCleaner || dependentResource.isDeletable();
final var actualName = dependentResource.name();
dependentResourceNodes.put(actualName, currentNode);
return this;
}

public WorkflowBuilder<P> dependsOn(Set<DependentResource> dependentResources) {
for (var dependentResource : dependentResources) {
var dependsOn = getNodeByDependentResource(dependentResource);
currentNode.addDependsOnRelation(dependsOn);
}
return this;
}

public WorkflowBuilder<P> dependsOn(DependentResource... dependentResources) {
if (dependentResources != null) {
return dependsOn(new HashSet<>(Arrays.asList(dependentResources)));
}
return this;
public WorkflowNodeConfigurationBuilder addDependentResourceAndConfigure(
DependentResource dependentResource) {
final var currentNode = doAddDependentResource(dependentResource);
return new WorkflowNodeConfigurationBuilder(currentNode);
}

public WorkflowBuilder<P> withReconcilePrecondition(Condition reconcilePrecondition) {
currentNode.setReconcilePrecondition(reconcilePrecondition);
return this;
}

public WorkflowBuilder<P> withReadyPostcondition(Condition readyPostcondition) {
currentNode.setReadyPostcondition(readyPostcondition);
return this;
}

public WorkflowBuilder<P> withDeletePostcondition(Condition deletePostcondition) {
currentNode.setDeletePostcondition(deletePostcondition);
public WorkflowBuilder<P> addDependentResource(DependentResource dependentResource) {
doAddDependentResource(dependentResource);
return this;
}

public WorkflowBuilder<P> withActivationCondition(Condition activationCondition) {
currentNode.setActivationCondition(activationCondition);
return this;
private DependentResourceNode doAddDependentResource(DependentResource dependentResource) {
final var currentNode = new DependentResourceNode<>(dependentResource);
isCleaner = isCleaner || dependentResource.isDeletable();
final var actualName = dependentResource.name();
dependentResourceNodes.put(actualName, currentNode);
return currentNode;
}

DependentResourceNode getNodeByDependentResource(DependentResource<?, ?> dependentResource) {
Expand Down Expand Up @@ -89,4 +64,70 @@ DefaultWorkflow<P> buildAsDefaultWorkflow() {
return new DefaultWorkflow(new HashSet<>(dependentResourceNodes.values()),
throwExceptionAutomatically, isCleaner);
}

public class WorkflowNodeConfigurationBuilder {
private final DependentResourceNode currentNode;

private WorkflowNodeConfigurationBuilder(DependentResourceNode currentNode) {
this.currentNode = currentNode;
}

public WorkflowBuilder<P> addDependentResource(DependentResource<?, ?> dependentResource) {
return WorkflowBuilder.this.addDependentResource(dependentResource);
}

public WorkflowNodeConfigurationBuilder addDependentResourceAndConfigure(
DependentResource<?, ?> dependentResource) {
final var currentNode = WorkflowBuilder.this.doAddDependentResource(dependentResource);
return new WorkflowNodeConfigurationBuilder(currentNode);
}

public Workflow<P> build() {
return WorkflowBuilder.this.build();
}

DefaultWorkflow<P> buildAsDefaultWorkflow() {
return WorkflowBuilder.this.buildAsDefaultWorkflow();
}

public WorkflowBuilder<P> withThrowExceptionFurther(boolean throwExceptionFurther) {
return WorkflowBuilder.this.withThrowExceptionFurther(throwExceptionFurther);
}

public WorkflowNodeConfigurationBuilder toDependOn(Set<DependentResource> dependentResources) {
for (var dependentResource : dependentResources) {
var dependsOn = getNodeByDependentResource(dependentResource);
currentNode.addDependsOnRelation(dependsOn);
}
return this;
}

public WorkflowNodeConfigurationBuilder toDependOn(DependentResource... dependentResources) {
if (dependentResources != null) {
return toDependOn(new HashSet<>(Arrays.asList(dependentResources)));
}
return this;
}

public WorkflowNodeConfigurationBuilder withReconcilePrecondition(
Condition reconcilePrecondition) {
currentNode.setReconcilePrecondition(reconcilePrecondition);
return this;
}

public WorkflowNodeConfigurationBuilder withReadyPostcondition(Condition readyPostcondition) {
currentNode.setReadyPostcondition(readyPostcondition);
return this;
}

public WorkflowNodeConfigurationBuilder withDeletePostcondition(Condition deletePostcondition) {
currentNode.setDeletePostcondition(deletePostcondition);
return this;
}

public WorkflowNodeConfigurationBuilder withActivationCondition(Condition activationCondition) {
currentNode.setActivationCondition(activationCondition);
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ void setup() {
void cleanUpDiamondWorkflow() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dr1).dependsOn(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dr1, dd2)
.addDependentResourceAndConfigure(dr1).toDependOn(dd1)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dr1, dd2)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -73,9 +73,9 @@ void cleanUpDiamondWorkflow() {
void dontDeleteIfDependentErrored() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dd2)
.addDependentResource(errorDD).dependsOn(dd2)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dd2)
.addDependentResourceAndConfigure(errorDD).toDependOn(dd2)
.withThrowExceptionFurther(false)
.build();

Expand All @@ -95,7 +95,8 @@ void dontDeleteIfDependentErrored() {
void cleanupConditionTrivialCase() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1).withDeletePostcondition(notMetCondition)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.withDeletePostcondition(notMetCondition)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -110,7 +111,7 @@ void cleanupConditionTrivialCase() {
void cleanupConditionMet() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1).withDeletePostcondition(metCondition)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1).withDeletePostcondition(metCondition)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -126,9 +127,10 @@ void cleanupConditionMet() {
void cleanupConditionDiamondWorkflow() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dd1).withDeletePostcondition(notMetCondition)
.addDependentResource(dd4).dependsOn(dd2, dd3)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dd1)
.withDeletePostcondition(notMetCondition)
.addDependentResourceAndConfigure(dd4).toDependOn(dd2, dd3)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand Down Expand Up @@ -162,10 +164,10 @@ void dontDeleteIfGarbageCollected() {
void ifDependentActiveDependentNormallyDeleted() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dd1)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dd1)
.withActivationCondition(metCondition)
.addDependentResource(dd4).dependsOn(dd2, dd3)
.addDependentResourceAndConfigure(dd4).toDependOn(dd2, dd3)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -182,11 +184,11 @@ void ifDependentActiveDependentNormallyDeleted() {
void ifDependentActiveDeletePostConditionIsChecked() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dd1)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dd1)
.withDeletePostcondition(notMetCondition)
.withActivationCondition(metCondition)
.addDependentResource(dd4).dependsOn(dd2, dd3)
.addDependentResourceAndConfigure(dd4).toDependOn(dd2, dd3)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -206,10 +208,10 @@ void ifDependentActiveDeletePostConditionIsChecked() {
void ifDependentInactiveDeleteIsNotCalled() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dd1)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dd1)
.withActivationCondition(notMetCondition)
.addDependentResource(dd4).dependsOn(dd2, dd3)
.addDependentResourceAndConfigure(dd4).toDependOn(dd2, dd3)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -225,11 +227,11 @@ void ifDependentInactiveDeleteIsNotCalled() {
void ifDependentInactiveDeletePostConditionNotChecked() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResource(dd2).dependsOn(dd1)
.addDependentResource(dd3).dependsOn(dd1)
.addDependentResourceAndConfigure(dd2).toDependOn(dd1)
.addDependentResourceAndConfigure(dd3).toDependOn(dd1)
.withDeletePostcondition(notMetCondition)
.withActivationCondition(notMetCondition)
.addDependentResource(dd4).dependsOn(dd2, dd3)
.addDependentResourceAndConfigure(dd4).toDependOn(dd2, dd3)
.build();

var res = workflow.cleanup(new TestCustomResource(), mockContext);
Expand All @@ -243,7 +245,7 @@ void ifDependentInactiveDeletePostConditionNotChecked() {
@Test
void singleInactiveDependent() {
var workflow = new WorkflowBuilder<TestCustomResource>()
.addDependentResource(dd1)
.addDependentResourceAndConfigure(dd1)
.withActivationCondition(notMetCondition)
.build();

Expand Down
Loading

0 comments on commit 706aef2

Please sign in to comment.