You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
1. Dependent resources are explicitly created and can be access later by reference.
305
-
2. Event sources are produced by the dependent resources, but needs to be explicitly registered in
306
-
this case by implementing
307
-
the [`EventSourceInitializer`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java)
308
-
interface.
309
-
3. The input html is validated, and error message is set in case it is invalid.
310
-
4. Reconciliation of dependent resources is called explicitly, but here the workflow
311
-
customization is fully in the hand of the developer.
312
-
5. An `Ingress` is created but only in case `exposed` flag set to true on custom resource. Tries to
313
-
delete it if not.
314
-
6. Status is set in a different way, this is just an alternative way to show, that the actual state
315
-
can be read using the reference. This could be written in a same way as in the managed example.
Note also the Workflows feature makes it possible to also support this conditional creation use
322
-
case in managed dependent resources.
230
+
You can see a commented example of how to do
231
+
so [here](https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java).
323
232
324
233
## Creating/Updating Kubernetes Resources
325
234
@@ -352,17 +261,17 @@ Since SSA is a complex feature, JOSDK implements a feature flag allowing users t
352
261
these implementations. See
353
262
in [ConfigurationService](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L332-L358).
354
263
355
-
It is, however, important to note that these implementations are default, generic
356
-
implementations that the framework can provide expected behavior out of the box. In many
357
-
situations, these will work just fine but it is also possible to provide matching algorithms
264
+
It is, however, important to note that these implementations are default, generic
265
+
implementations that the framework can provide expected behavior out of the box. In many
266
+
situations, these will work just fine but it is also possible to provide matching algorithms
358
267
optimized for specific use cases. This is easily done by simply overriding
359
-
the `match(...)`[method](https://github.com/java-operator-sdk/java-operator-sdk/blob/e16559fd41bbb8bef6ce9d1f47bffa212a941b09/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java#L156-L156).
268
+
the `match(...)`[method](https://github.com/java-operator-sdk/java-operator-sdk/blob/e16559fd41bbb8bef6ce9d1f47bffa212a941b09/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java#L156-L156).
360
269
361
-
It is also possible to bypass the matching logic altogether to simply rely on the server-side
270
+
It is also possible to bypass the matching logic altogether to simply rely on the server-side
362
271
apply mechanism if always sending potentially unchanged resources to the cluster is not an issue.
363
272
JOSDK's matching mechanism allows to spare some potentially useless calls to the Kubernetes API
364
-
server. To bypass the matching feature completely, simply override the `match` method to always
365
-
return `false`, thus telling JOSDK that the actual state never matches the desired one, making
273
+
server. To bypass the matching feature completely, simply override the `match` method to always
274
+
return `false`, thus telling JOSDK that the actual state never matches the desired one, making
366
275
it always update the resources using SSA.
367
276
368
277
WARNING: Older versions of Kubernetes before 1.25 would create an additional resource version for every SSA update
resource, since there could be multiple instances of that type which could possibly be used, each
302
+
associated with the same primary resource. In this situation, JOSDK automatically selects the appropriate secondary
303
+
resource matching the desired state associated with the primary resource. This makes sense because the desired
304
+
state computation already needs to be able to discriminate among multiple related secondary resources to tell JOSDK how
305
+
they should be reconciled.
306
+
307
+
There might be casees, though, where it might be problematic to call the `desired` method several times (for example, because it is costly to do so), it is always possible to override this automated discrimination using several means:
308
+
309
+
- Implement your own `getSecondaryResource` method on your `DependentResource` implementation from scratch.
310
+
- Override the `selectManagedSecondaryResource` method, if your `DependentResource` extends `AbstractDependentResource`.
311
+
This should be relatively simple to override this method to optimize the matching to your needs. You can see an
312
+
example of such an implementation in
313
+
the [`ExternalWithStateDependentResource`](https://github.com/operator-framework/java-operator-sdk/blob/6cd0f884a7c9b60c81bd2d52da54adbd64d6e118/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalWithStateDependentResource.java#L43-L49)
314
+
class.
315
+
- Override the `managedSecondaryResourceID` method, if your `DependentResource` extends `KubernetesDependentResource`,
316
+
where it's very often possible to easily determine the `ResourceID` of the secondary resource. This would probably be
317
+
the easiest solution if you're working with Kubernetes resources.
318
+
319
+
### Sharing an Event Source Between Dependent Resources
406
320
407
321
Dependent resources usually also provide event sources. When dealing with multiple dependents of
408
322
the same type, one needs to decide whether these dependent resources should track the same
@@ -418,10 +332,10 @@ would look as follows:
418
332
useEventSourceWithName = "configMapSource")
419
333
```
420
334
421
-
A sample is provided as an integration test both
422
-
for [managed](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleManagedDependentSameTypeIT.java)
for [managed](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleManagedDependentNoDiscriminatorIT.java)
@@ -484,15 +398,18 @@ also be created, one per dependent resource.
484
398
See [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/ExternalStateBulkIT.java)
485
399
as a sample.
486
400
487
-
488
401
## GenericKubernetesResource based Dependent Resources
489
402
490
-
In rare circumstances resource handling where there is no class representation or just typeless handling might be needed.
For dependent resource this is supported by [GenericKubernetesDependentResource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java#L8-L8)
495
-
. See samples [here](https://github.com/java-operator-sdk/java-operator-sdk/tree/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource).
409
+
For dependent resource this is supported
410
+
by [GenericKubernetesDependentResource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java#L8-L8)
To contrast, see the same sample, this time [without SSA](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/patchresourceandstatusnossa/PatchResourceAndStatusNoSSAReconciler.java#L16-L16).
102
+
103
+
Non-SSA based patch is still supported.
104
+
You can control whether or not to use SSA
105
+
using [`ConfigurationServcice.useSSAToPatchPrimaryResource()`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L385-L385)
106
+
and the related `ConfigurationServiceOverrider.withUseSSAToPatchPrimaryResource` method.
107
+
Related integration test can be
108
+
found [here](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/patchresourceandstatusnossa/PatchResourceAndStatusNoSSAReconciler.java).
109
+
110
+
Handling resources directly using the client, instead of delegating these updates operations to JOSDK by returning
111
+
an `UpdateControl` at the end of your reconciliation, should work appropriately. However, we do recommend to
112
+
use `UpdateControl` instead since JOSDK makes sure that the operations are handled properly, since there are subtleties
113
+
to be aware of. For example, if you are using a finalizer, JOSDK makes sure to include it in your fully specified intent
114
+
so that it is not unintentionally removed from the resource (which would happen if you omit it, since your controller is
115
+
the designated manager for that field and Kubernetes interprets the finalizer being gone from the specified intent as a
the [`ObservedGenerationAwareStatus`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java)
178
-
convenience implementation that you can extend in your own status class implementations.
179
-
- The other condition is that the `CustomResource.getStatus()` method should not return `null`.
180
-
So the status should be instantiated when the object is returned using the `UpdateControl`.
181
-
182
-
If these conditions are fulfilled and generation awareness is activated, the observed generation
183
-
is automatically set by the framework after the `reconcile` method is called. Note that the
184
-
observed generation is also updated even when `UpdateControl.noUpdate()` is returned from the
185
-
reconciler. See this feature at work in
186
-
the [WebPage example](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStatus.java#L5)
Initializing status automatically on custom resource could be done by overriding the `initStatus` method
199
-
of `CustomResource`. However, this is NOT advised, since breaks the status patching if you use:
200
-
`UpdateControl.patchStatus`. See
201
-
also [javadocs](https://github.com/java-operator-sdk/java-operator-sdk/blob/3994f5ffc1fb000af81aa198abf72a5f75fd3e97/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java#L41-L42)
From v5 by default finalizer is added using Served Side Apply. See also UpdateControl in docs.
216
186
217
187
## Generation Awareness and Event Filtering
218
188
@@ -231,9 +201,7 @@ To turn off this feature, set `generationAwareEventProcessing` to `false` for th
231
201
## Support for Well Known (non-custom) Kubernetes Resources
232
202
233
203
A Controller can be registered for a non-custom resource, so well known Kubernetes resources like (
234
-
`Ingress`, `Deployment`,...). Note that automatic observed generation handling is not supported
235
-
for these resources, though, in this case, the handling of the observed generation is probably
236
-
handled by the primary controller.
204
+
`Ingress`, `Deployment`,...).
237
205
238
206
See
239
207
the [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/deployment/DeploymentReconciler.java)
@@ -243,11 +211,12 @@ for reconciling deployments.
1.[Result of managed dependent resources](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ManagedDependentResourceContext.java#L55-L57)
11
+
is not `Optional` anymore. In case you use this result, simply use the result
12
+
objects directly.
13
+
2.`EventSourceInitializer` is not a separate interface anymore. It is part of the `Reconciler` interface with a
14
+
default implementation. You can simply remove this interface from your reconciler. The
where it is demonstrated. Also, the related part of
43
+
a [workaround](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/StatusPatchSSAMigrationIT.java#L110-L116).
44
+
45
+
6.`ManagedDependentResourceContext` has been renamed to `ManagedWorkflowAndDependentResourceContext` and is accessed
46
+
via the accordingly renamed `managedWorkflowAndDependentResourceContext` method.
47
+
7.`ResourceDiscriminator` was removed. In most of the cases you can just delete the discriminator, everything should
48
+
work without it by default. To optimize and handle special cases see the relevant section
49
+
in [Dependent Resource documentation](/docs/dependent-resources#multiple-dependent-resources-of-same-type).
50
+
8.`ConfigurationService.getTerminationTimeoutSeconds` and associated overriding mechanism have been removed,
51
+
use `Operator.stop(Duration)` instead.
52
+
9.`Operator.installShutdownHook()` has been removed, use `Operator.installShutdownHook(Duration)` instead
53
+
10. Automated observed generation handling feature was removed (`ObservedGenerationAware` interface
54
+
and `ObservedGenerationAwareStatus` class were deleted). Manually handling observed generation is fairly easy to do
55
+
in your reconciler, however, it cannot be done automatically when using SSA. We therefore removed the feature since
56
+
it would have been confusing to have a different behavior for SSA and non-SSA cases. For an example of how to do
57
+
observed generation handling manually in your reconciler, see
2. Root nodes, i.e. nodes in the graph that do not depend on other nodes are reconciled first,
199
199
in a parallel manner.
200
200
3. A DR is reconciled if it does not depend on any other DRs, or *ALL* the DRs it depends on are
201
-
reconciled and ready. If a DR defines a reconcile pre-condition and/or an activation condition,
201
+
reconciled and ready. If a DR defines a reconcile pre-condition and/or an activation condition,
202
202
then these condition must become `true` before the DR is reconciled.
203
203
4. A DR is considered *ready* if it got successfully reconciled and any ready post-condition it
204
204
might define is `true`.
@@ -328,10 +328,38 @@ provides such a delete post-condition implementation in the form of
328
328
329
329
Also, check usage in an [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manageddependentdeletecondition/ManagedDependentDefaultDeleteConditionReconciler.java).
330
330
331
-
In such cases the Kubernetes Dependent Resource should extend `CRUDNoGCKubernetesDependentResource`
331
+
In such cases the Kubernetes Dependent Resource should extend `CRUDNoGCKubernetesDependentResource`
332
332
and NOT `CRUDKubernetesDependentResource` since otherwise the Kubernetes Garbage Collector would delete the resources.
333
333
In other words if a Kubernetes Dependent Resource depends on another dependent resource, it should not implement
334
-
`GargageCollected` interface, otherwise the deletion order won't be guaranteed.
334
+
`GargageCollected` interface, otherwise the deletion order won't be guaranteed.
335
+
336
+
337
+
## Explicit Managed Workflow Invocation
338
+
339
+
Managed workflows, i.e. ones that are declared via annotations and therefore completely managed by JOSDK, are reconciled
340
+
before the primary resource. Each dependent resource that can be reconciled (according to the workflow configuration)
341
+
will therefore be reconciled before the primary reconciler is called to reconcile the primary resource. There are,
342
+
however, situations where it would be be useful to perform additional steps before the workflow is reconciled, for
343
+
example to validate the current state, execute arbitrary logic or even skip reconciliation altogether. Explicit
344
+
invocation of managed workflow was therefore introduced to solve these issues.
345
+
346
+
To use this feature, you need to set the `explicitInvocation` field to `true` on the `@Workflow` annotation and then
347
+
call the `reconcileManagedWorkflow` method from the `
348
+
ManagedWorkflowAndDependentResourceContext` retrieved from the reconciliation `Context` provided as part of your primary
349
+
resource reconciler `reconcile` method arguments.
350
+
351
+
See
352
+
related [integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/WorkflowExplicitInvocationIT.java)
353
+
for more details.
354
+
355
+
For `cleanup`, if the `Cleaner` interface is implemented, the `cleanupManageWorkflow()` needs to be called explicitly.
356
+
However, if `Cleaner` interface is not implemented, it will be called implicitly.
357
+
See
358
+
related [integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/WorkflowExplicitCleanupIT.java).
359
+
360
+
While nothing prevents calling the workflow multiple times in a reconciler, it isn't typical or even recommended to do
361
+
so. Conversely, if explicit invocation is requested but `reconcileManagedWorkflow` is not called in the primary resource
362
+
reconciler, the workflow won't be reconciled at all.
0 commit comments