Skip to content

Commit 1d38a5f

Browse files
committed
feat: dependent resource in the condition instead of resource (#1690)
1 parent 532fa82 commit 1d38a5f

File tree

10 files changed

+85
-34
lines changed

10 files changed

+85
-34
lines changed

docs/documentation/v4-3-migration.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
title: Migrating from v4.2 to v4.3
3+
description: Migrating from v4.2 to v4.3
4+
layout: docs
5+
permalink: /docs/v4-3-migration
6+
---
7+
8+
# Migrating from v4.2 to v4.3
9+
10+
## Condition API Change
11+
12+
In Workflows the target of the condition was the managed resource itself, not a dependent resource. This changed, from
13+
not the API contains the dependent resource.
14+
15+
New API:
16+
17+
```java
18+
public interface Condition<R, P extends HasMetadata> {
19+
20+
boolean isMet(DependentResource<R, P> dependentResource, P primary, Context<P> context);
21+
22+
}
23+
```
24+
25+
Former API:
26+
27+
```java
28+
public interface Condition<R, P extends HasMetadata> {
29+
30+
boolean isMet(P primary, R secondary, Context<P> context);
31+
32+
}
33+
```
34+
35+
Migration is trivial. Since the secondary resource can be accessed from the dependent resource. So to access the secondary
36+
resource just use `dependentResource.getSecondaryResource(primary,context)`.

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutor.java

+1-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import io.fabric8.kubernetes.api.model.HasMetadata;
1515
import io.javaoperatorsdk.operator.api.reconciler.Context;
1616
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
17-
import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource;
1817

1918
@SuppressWarnings("rawtypes")
2019
public abstract class AbstractWorkflowExecutor<P extends HasMetadata> {
@@ -103,15 +102,7 @@ protected synchronized void handleNodeExecutionFinish(
103102
@SuppressWarnings("unchecked")
104103
protected <R> boolean isConditionMet(Optional<Condition<R, P>> condition,
105104
DependentResource<R, P> dependentResource) {
106-
if (condition.isEmpty()) {
107-
return true;
108-
}
109-
var resources = dependentResource instanceof BulkDependentResource
110-
? ((BulkDependentResource) dependentResource).getSecondaryResources(primary, context)
111-
: dependentResource.getSecondaryResource(primary, context).orElse(null);
112-
113-
return condition.map(c -> c.isMet(primary,
114-
(R) resources, context))
105+
return condition.map(c -> c.isMet(dependentResource, primary, context))
115106
.orElse(true);
116107
}
117108
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/Condition.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.fabric8.kubernetes.api.model.HasMetadata;
44
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
56

67
public interface Condition<R, P extends HasMetadata> {
78

@@ -10,12 +11,10 @@ public interface Condition<R, P extends HasMetadata> {
1011
* {@link io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource} based on the
1112
* observed cluster state.
1213
*
14+
* @param dependentResource for which the condition applies to
1315
* @param primary the primary resource being considered
14-
* @param secondary the secondary resource associated with the specified primary resource or
15-
* {@code null} if no such secondary resource exists (for example because it's been
16-
* deleted)
1716
* @param context the current reconciliation {@link Context}
1817
* @return {@code true} if the condition holds, {@code false} otherwise
1918
*/
20-
boolean isMet(P primary, R secondary, Context<P> context);
19+
boolean isMet(DependentResource<R, P> dependentResource, P primary, Context<P> context);
2120
}

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,9 @@ public UpdateControl<ConfigMap> reconcile(ConfigMap resource, Context<ConfigMap>
362362
private static class TestCondition implements Condition<ConfigMap, ConfigMap> {
363363

364364
@Override
365-
public boolean isMet(ConfigMap primary, ConfigMap secondary, Context<ConfigMap> context) {
365+
public boolean isMet(DependentResource<ConfigMap, ConfigMap> dependentResource,
366+
ConfigMap primary,
367+
Context<ConfigMap> context) {
366368
return true;
367369
}
368370
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
package io.javaoperatorsdk.operator.sample.bulkdependent;
22

3-
import java.util.Map;
4-
53
import io.fabric8.kubernetes.api.model.ConfigMap;
64
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
76
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
87

98
public class SampleBulkCondition
10-
implements Condition<Map<String, ConfigMap>, BulkDependentTestCustomResource> {
9+
implements Condition<ConfigMap, BulkDependentTestCustomResource> {
1110

1211
// We use ConfigMaps here just to show how to check some properties of resources managed by a
1312
// BulkDependentResource. In real life example this would be rather based on some status of those
1413
// resources, like Pods.
1514

1615
@Override
17-
public boolean isMet(BulkDependentTestCustomResource primary, Map<String, ConfigMap> secondary,
16+
public boolean isMet(
17+
DependentResource<ConfigMap, BulkDependentTestCustomResource> dependentResource,
18+
BulkDependentTestCustomResource primary,
1819
Context<BulkDependentTestCustomResource> context) {
19-
return secondary.values().stream().noneMatch(cm -> cm.getData().isEmpty());
20+
21+
var resources = ((CRUDConfigMapBulkDependentResource) dependentResource)
22+
.getSecondaryResources(primary, context);
23+
return resources.values().stream().noneMatch(cm -> cm.getData().isEmpty());
2024
}
2125
}

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/dependent/StatefulSetReadyCondition.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@
22

33
import io.fabric8.kubernetes.api.model.apps.StatefulSet;
44
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
56
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
67
import io.javaoperatorsdk.operator.sample.complexdependent.ComplexDependentCustomResource;
78

89
public class StatefulSetReadyCondition
910
implements Condition<StatefulSet, ComplexDependentCustomResource> {
1011

1112
@Override
12-
public boolean isMet(ComplexDependentCustomResource primary, StatefulSet secondary,
13+
public boolean isMet(
14+
DependentResource<StatefulSet, ComplexDependentCustomResource> dependentResource,
15+
ComplexDependentCustomResource primary,
1316
Context<ComplexDependentCustomResource> context) {
1417

15-
var readyReplicas = secondary.getStatus().getReadyReplicas();
16-
return readyReplicas != null && readyReplicas > 0;
18+
return dependentResource.getSecondaryResource(primary, context).map(secondary -> {
19+
var readyReplicas = secondary.getStatus().getReadyReplicas();
20+
return readyReplicas != null && readyReplicas > 0;
21+
})
22+
.orElse(false);
1723
}
1824
}

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/workflowallfeature/ConfigMapDeletePostCondition.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import io.fabric8.kubernetes.api.model.ConfigMap;
77
import io.javaoperatorsdk.operator.api.reconciler.Context;
8+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
89
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
910

1011
public class ConfigMapDeletePostCondition
@@ -14,9 +15,11 @@ public class ConfigMapDeletePostCondition
1415

1516
@Override
1617
public boolean isMet(
17-
WorkflowAllFeatureCustomResource primary, ConfigMap secondary,
18+
DependentResource<ConfigMap, WorkflowAllFeatureCustomResource> dependentResource,
19+
WorkflowAllFeatureCustomResource primary,
1820
Context<WorkflowAllFeatureCustomResource> context) {
19-
var configMapDeleted = secondary == null;
21+
22+
var configMapDeleted = dependentResource.getSecondaryResource(primary, context).isEmpty();
2023
log.debug("Config Map Deleted: {}", configMapDeleted);
2124
return configMapDeleted;
2225
}

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/workflowallfeature/ConfigMapReconcileCondition.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
import io.fabric8.kubernetes.api.model.ConfigMap;
44
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
56
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
67

78
public class ConfigMapReconcileCondition
89
implements Condition<ConfigMap, WorkflowAllFeatureCustomResource> {
910

1011
@Override
11-
public boolean isMet(WorkflowAllFeatureCustomResource primary, ConfigMap secondary,
12+
public boolean isMet(
13+
DependentResource<ConfigMap, WorkflowAllFeatureCustomResource> dependentResource,
14+
WorkflowAllFeatureCustomResource primary,
1215
Context<WorkflowAllFeatureCustomResource> context) {
16+
1317
return primary.getSpec().isCreateConfigMap();
1418
}
1519
}

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/workflowallfeature/DeploymentReadyCondition.java

+10-7
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@
22

33
import io.fabric8.kubernetes.api.model.apps.Deployment;
44
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
56
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
67

78
public class DeploymentReadyCondition
89
implements Condition<Deployment, WorkflowAllFeatureCustomResource> {
910
@Override
10-
public boolean isMet(WorkflowAllFeatureCustomResource primary, Deployment deployment,
11+
public boolean isMet(
12+
DependentResource<Deployment, WorkflowAllFeatureCustomResource> dependentResource,
13+
WorkflowAllFeatureCustomResource primary,
1114
Context<WorkflowAllFeatureCustomResource> context) {
12-
if (deployment == null) {
13-
return false;
14-
}
15-
var readyReplicas = deployment.getStatus().getReadyReplicas();
16-
17-
return readyReplicas != null && deployment.getSpec().getReplicas().equals(readyReplicas);
15+
return dependentResource.getSecondaryResource(primary, context)
16+
.map(deployment -> {
17+
var readyReplicas = deployment.getStatus().getReadyReplicas();
18+
return readyReplicas != null && deployment.getSpec().getReplicas().equals(readyReplicas);
19+
})
20+
.orElse(false);
1821
}
1922
}

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ExposedIngressCondition.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
44
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
56
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
67

78
public class ExposedIngressCondition implements Condition<Ingress, WebPage> {
9+
810
@Override
9-
public boolean isMet(WebPage primary, Ingress secondary, Context<WebPage> context) {
11+
public boolean isMet(DependentResource<Ingress, WebPage> dependentResource,
12+
WebPage primary, Context<WebPage> context) {
1013
return primary.getSpec().getExposed();
1114
}
1215
}

0 commit comments

Comments
 (0)