Skip to content

Commit 6a39d2e

Browse files
committed
docs
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent 880a455 commit 6a39d2e

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

docs/content/en/docs/documentation/reconciler.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,63 @@ In this mode:
258258
- you cannot use managed dependent resources since those manage the finalizers and other logic related to the normal
259259
execution mode.
260260

261-
See also [sample](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/triggerallevent/finalizerhandling) for selectively adding finalizers for resources;
261+
See also [sample](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/triggerallevent/finalizerhandling) for selectively adding finalizers for resources;
262+
263+
### Expectations
264+
265+
Expectations are a pattern to make sure to check in the reconciliation that your secondary resources are in a certain state.
266+
For a more detailed explanation see [this blogpost](https://ahmet.im/blog/controller-pitfalls/#expectations-pattern).
267+
You can find framework support for this pattern in [`io.javaoperatorsdk.operator.processing.expectation`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/expectation/)
268+
package. See also related [integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/expectation/ExpectationReconciler.java).
269+
Note that this feature is marked as `@Experimental`, since based on feedback the API might be improved / changed, but we intend
270+
to support it, later also might be integrated to Dependent Resources and/or Workflows.
271+
272+
The idea is the nutshell, is that you can track your expectations in the expectation manager in the reconciler.
273+
Which has an api that covers the common use cases.
274+
275+
The following sample is the simplified version of the integration tests that implements a logic that creates a
276+
deployment and sets status message if there are the target three replicas ready:
277+
278+
```java
279+
public class ExpectationReconciler implements Reconciler<ExpectationCustomResource> {
280+
281+
// some code is omitted
282+
283+
private final ExpectationManager<ExpectationCustomResource> expectationManager =
284+
new ExpectationManager<>();
285+
286+
@Override
287+
public UpdateControl<ExpectationCustomResource> reconcile(
288+
ExpectationCustomResource primary, Context<ExpectationCustomResource> context) {
289+
290+
// exiting asap if there is an expectation that is not timed out neither fulfilled yet
291+
if (expectationManager.ongoingExpectationPresent(primary, context)) {
292+
return UpdateControl.noUpdate();
293+
}
294+
295+
var deployment = context.getSecondaryResource(Deployment.class);
296+
if (deployment.isEmpty()) {
297+
createDeployment(primary, context);
298+
expectationManager.setExpectation(
299+
primary, Duration.ofSeconds(timeout), deploymentReadyExpectation(context));
300+
return UpdateControl.noUpdate();
301+
} else {
302+
// checks the expectation if it is fulfilled also removes it,
303+
// in your logic you might add a next expectation based on your workflow.
304+
// Expectations have a name, so you can easily distinguish them if there is more of them.
305+
var res = expectationManager.checkExpectation("deploymentReadyExpectation",primary, context);
306+
if (res.isFulfilled()) {
307+
return pathchStatusWithMessage(primary, DEPLOYMENT_READY);
308+
} else if (res.isTimedOut()) {
309+
// you might add some other timeout handling here
310+
return pathchStatusWithMessage(primary, DEPLOYMENT_TIMEOUT);
311+
}
312+
}
313+
return UpdateControl.noUpdate();
314+
315+
}
316+
}
317+
```
318+
319+
320+

operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/expectation/ExpectationReconciler.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,24 @@ public UpdateControl<ExpectationCustomResource> reconcile(
7272
primary, Duration.ofSeconds(timeout), deploymentReadyExpectation(context));
7373
return UpdateControl.noUpdate();
7474
} else {
75-
var res = expectationManager.checkExpectation(primary, context);
75+
// checks the expectation if it is fulfilled also removes it,
76+
// in your logic you might add a next expectation based on your workflow
77+
// Expectations have a name, so you can easily distinguish them if there is more of them.
78+
var res =
79+
expectationManager.checkExpectation(DEPLOYMENT_READY_EXPECTATION_NAME, primary, context);
80+
// Note that this happens only once, since if the expectation is fulfilled, it is also removed
81+
// from the manager.
7682
if (res.isFulfilled()) {
77-
return pathStatusWithMessage(primary, DEPLOYMENT_READY);
83+
return pathchStatusWithMessage(primary, DEPLOYMENT_READY);
7884
} else if (res.isTimedOut()) {
79-
return pathStatusWithMessage(primary, DEPLOYMENT_TIMEOUT);
85+
// you might add some other timeout handling here
86+
return pathchStatusWithMessage(primary, DEPLOYMENT_TIMEOUT);
8087
}
8188
}
8289
return UpdateControl.noUpdate();
8390
}
8491

85-
private static UpdateControl<ExpectationCustomResource> pathStatusWithMessage(
92+
private static UpdateControl<ExpectationCustomResource> pathchStatusWithMessage(
8693
ExpectationCustomResource primary, String message) {
8794
primary.setStatus(new ExpectationCustomResourceStatus());
8895
primary.getStatus().setMessage(message);

0 commit comments

Comments
 (0)