|
1 | 1 | ---
|
2 |
| -title: Dependent Resources Feature |
3 |
| -description: Dependent Resources Feature |
4 |
| -layout: docs |
5 |
| -permalink: /docs/dependent-resources |
| 2 | +title: Dependent Resources Feature description: Dependent Resources Feature layout: docs permalink: |
| 3 | +/docs/dependent-resources |
6 | 4 | ---
|
7 | 5 |
|
8 | 6 | # Dependent Resources
|
9 | 7 |
|
10 |
| -DISCLAIMER: Dependent Resources is relatively new and implementation wise not a simple concept, some APIs could be still |
11 |
| -a subject of change in the future. However, in case of non-backwards compatible change is expected to be trivial to |
12 |
| -migrate. |
| 8 | +DISCLAIMER: The Dependent Resource support is relatively new and, while we strove to cover what we |
| 9 | +anticipate will be the most common use cases, the implementation is not simple and might still |
| 10 | +evolve. As a result, some APIs could be still a subject of change in the future. However, |
| 11 | +non-backwards compatible changes are expected to be trivial to adapt to. |
13 | 12 |
|
14 | 13 | ## Motivations and Goals
|
15 | 14 |
|
16 |
| -During a reconciliation controller is managing other "secondary" resources. Typically, the following steps are executed: |
| 15 | +Most operators need to deal with secondary resources when trying to realize the desired state |
| 16 | +described by the primary resource it is in charge of. For example, the Kubernetes-native |
| 17 | +`Deployment` controller needs to manage `ReplicaSet` instances as part of a `Deployment`'s |
| 18 | +reconciliation process. In this instance, `ReplicatSet` is considered a secondary resource for |
| 19 | +the `Deployment` controller. |
17 | 20 |
|
18 |
| -1. Check if the desired resource already exists (usually if already present in the cache of an EventSource). |
19 |
| -2. If the resource not exists create one with the desired spec. |
20 |
| -3. If resource already exists, check if the spec of the resources is the same as desired. |
21 |
| - 1. If the actual spec is different from the desired spec update it. |
| 21 | +Controllers that deal with secondary resources typically need to perform the following steps, for |
| 22 | +each secondary resource: |
22 | 23 |
|
23 |
| -The process how the resource is read, created, updated or the desired state is compared to the actual state in |
24 |
| -Kubernetes API are all generic sub-problems in a reconciler implementation. |
25 |
| -The motivation behind Dependent Resource is hide the mentioned problems (and much |
26 |
| -more) from the developer and provide a system that allows managing the secondary resources in an |
27 |
| -elegant and structured way. |
| 24 | +```mermaid |
| 25 | +flowchart TD |
| 26 | +
|
| 27 | +A{Secondary resource exists?} |
| 28 | +A -- Yes --> match |
| 29 | +A -- No --> compute |
| 30 | +
|
| 31 | +compute[Compute desired state based on primary state] --> Create --> Done |
| 32 | +match{Matches desired state as defined by primary?} |
| 33 | +match -- Yes --> Done |
| 34 | +match -- No --> Update |
| 35 | +
|
| 36 | +``` |
| 37 | + |
| 38 | +As this process is pretty much similar for each dependent resource, it makes sense for the SDK to |
| 39 | +offer some level of support for these repetitive actions to remove the boilerplate code. While these |
| 40 | +steps are not difficult in and of themselves, there are some subtleties that can lead to bugs or |
| 41 | +sub-optimal code if not done right. It should be possible to handle common cases (such as dealing |
| 42 | +with Kubernetes-native secondary resources) in a semi-declarative way with only a minimal amount of |
| 43 | +code, JOSDK taking care of wiring everything accordingly. |
| 44 | + |
| 45 | +Moreover, in order for your reconciler to get informed of events on these secondary resources, you |
| 46 | +need to configure and create event sources and maintain them. JOSDK already makes it rather easy to |
| 47 | +deal with these but we felt that we could make things even simpler. |
| 48 | + |
| 49 | +Finally, there are also opportunities for the SDK to transparently add features that are even |
| 50 | +trickier to get right, such as immediate caching of updated or created resources (so that your |
| 51 | +reconciler doesn't need to wait for a cluster roundtrip to continue its work) and associated event |
| 52 | +filtering (so that something your reconciler just changed doesn't re-trigger a reconciliation, for |
| 53 | +example). |
28 | 54 |
|
29 | 55 | ## Design
|
30 | 56 |
|
| 57 | +### `DependentResource` vs. `AbstractDependentResource` |
| 58 | + |
| 59 | +The new `DependentResource` interface lies at the core of the design and strives to encapsulate the |
| 60 | +logic that is required to reconcile the state of the associated secondary resource based on the |
| 61 | +state of the primary one. For most cases, this logic will follow the flow expressed above and JOSDK |
| 62 | +provides a very convenient implementation of this logic in the form of the |
| 63 | +`AbstractDependentResource` class. If your logic doesn't fit this pattern, though, you can still |
| 64 | +provide your own `reconcile` method implementation. While the benefits of using dependent resources |
| 65 | +are less obvious in that case, this allows you to separate the logic necessary to deal with each |
| 66 | +secondary resource in its own class that can then be tested in isolation via unit tests. You can |
| 67 | +also use the declarative support with your own implementations as we shall see later on. |
| 68 | + |
| 69 | +`AbstractDependentResource` is designed so that classes extending it specify which functionality |
| 70 | +they support by implementing trait interfaces. This design has been selected to express the fact |
| 71 | +that not all secondary resources are completely under the control of the primary reconciler: some |
| 72 | +dependent resources are only ever created or updated for example and we needed a way to let JOSDK |
| 73 | +when that is the case. We therefore provide trait interfaces: `Creator`, |
| 74 | +`Updater` and `Deleter` to express that the `DependentResource` implementation will provide custom |
| 75 | +functionality to create, update and delete its associated secondary resources, respectively. If |
| 76 | +these traits are not implemented then parts of the logic described above is never triggered: if your |
| 77 | +implementation doesn't implement `Creator`, for example, |
| 78 | +`AbstractDependentResource` will never try to create the associated secondary resource, even if it |
| 79 | +doesn't exist. It is thus possible to create read-only dependent resources that will trigger your |
| 80 | +reconciler whenever a user interacts with them but that are never modified by your reconciler |
| 81 | +itself. |
| 82 | + |
| 83 | +### Batteries included: convenient `DependentResource` implementations! |
| 84 | + |
| 85 | +JOSDK also offers several other convenient implementations building on top of |
| 86 | +`AbstractDependentResource` that you can use as starting points for your own implementations. |
| 87 | + |
| 88 | +One such implementation is the `KubernetesDependentResource` class that makes it really easy to work |
| 89 | +with Kubernetes-native resources as, in this case, you usually only need to provide an |
| 90 | +implementation for the `desired` method to tell JOSDK what the desired state of your secondary |
| 91 | +resource should be based on the specified primary resource state. JOSDK takes care of everything |
| 92 | +else using default implementations that you can override in case you need more precise control of |
| 93 | +what's going on. |
| 94 | + |
| 95 | +We also provide implementations that makes it very easy to cache |
| 96 | +(`AbstractCachingDependentResource`) or make it easy to poll for changes in external |
| 97 | +resources (`PollingDependentResource`, `PerResourcePollingDependentResource`). |
| 98 | + |
| 99 | +FIX-ME: the following currently isn't true but we should put all in the same package hierarchy, see |
| 100 | +https://github.com/java-operator-sdk/java-operator-sdk/issues/1049 |
| 101 | +All the provided implementations can be found in |
| 102 | +the `io/javaoperatorsdk/operator/processing/dependent` package. |
| 103 | + |
31 | 104 | ## Managed Dependent Resources
|
32 | 105 |
|
| 106 | +As mentioned previously, one goal of this implementation is to make it possible to |
| 107 | +semi-declaratively create and wire dependent resources. You can annotate your reconciler with |
| 108 | +`@Dependent` annotations that specify which `DependentResource` implementation it depends upon and |
| 109 | +JOSDK will take the appropriate steps to wire everything thing together and call your |
| 110 | +`DependentResource` implementations `reconcile` method before your primary resource is reconciled. |
| 111 | +This makes sense in most use cases where the logic associated with the primary resource is usually |
| 112 | +limited to status handling based on the state of the secondary resources. This behavior and |
| 113 | +automated handling is referred to as "managed" because the `DependentResource` |
| 114 | +implementations are managed by JOSDK. |
| 115 | + |
33 | 116 | ## Standalone Dependent Resources
|
34 | 117 |
|
35 |
| -## Other Problems Handled by Dependent Resources |
| 118 | +## Other Dependent Resources features |
0 commit comments