Skip to content

Commit 76650a5

Browse files
csvirimetacosmscrocquesel
authored
docs: dependent resources (#1026)
* docs: dependent resources * docs: dr motivation * docs: add flow chart to motivation, detail design * fix: remove now fixed fix-me :) [skip-ci] * fix: missing word Co-authored-by: Sébastien CROCQUESEL <[email protected]> * fix: re-order sentences Co-authored-by: Sébastien CROCQUESEL <[email protected]> * fix: clarify Co-authored-by: Sébastien CROCQUESEL <[email protected]> * fix: split sentence Co-authored-by: Sébastien CROCQUESEL <[email protected]> * fix: split sentence Co-authored-by: Sébastien CROCQUESEL <[email protected]> * fix: remove extra word Co-authored-by: Sébastien CROCQUESEL <[email protected]> * fix: header * fix: simplify dependent logic [skip-ci] * fix: reword [skip ci] Co-authored-by: Attila Mészáros <[email protected]> Co-authored-by: Chris Laprun <[email protected]> Co-authored-by: Chris Laprun <[email protected]> Co-authored-by: Sébastien CROCQUESEL <[email protected]>
1 parent cb1fa11 commit 76650a5

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

docs/_data/sidebar.yml

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

0 commit comments

Comments
 (0)