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
Copy file name to clipboardExpand all lines: docs/controllers/application.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,8 @@
1
1
# The Application
2
2
3
-
The **application** is a Rust application manages a [Controller]. It needs a [[reconciler]] that will be called with entries of your chosen [[object]], and a few dependencies to deal with async streams, error handling, and upstream Kubernetes structs.
3
+
The **application** is a Rust application that manages a [Controller]. It needs a [[reconciler]] that will be called with entries of your chosen [[object]], and a few dependencies to deal with async streams, error handling, and upstream Kubernetes structs.
4
4
5
-
This document shows how to create a __minimal__ application, with the builtin`Pod` type as the main object, and a no-op reconciler.
5
+
This document shows how to create a __minimal__ application, with the built-in`Pod` type as the main object, and a no-op reconciler.
6
6
7
7
## Requirements
8
8
@@ -75,7 +75,7 @@ For the purposes of this demo we will import [Pod]:
75
75
usek8s_openapi::api::core::v1::Pod;
76
76
```
77
77
78
-
### Seting up the controller
78
+
### Setting up the controller
79
79
80
80
This is where we will start defining our `main` and glue everything together:
81
81
@@ -121,7 +121,7 @@ To make this reconciler useful, we can reuse the one created in the [[reconciler
121
121
122
122
## Checkpoint
123
123
124
-
If you copy-pasted everything above, and fixed imports, you should have a `main.rs` with this:
124
+
If you copy-pasted everything above and fixed imports, you should have a `main.rs` with this:
125
125
126
126
```rust
127
127
usestd::{sync::Arc, time::Duration};
@@ -202,7 +202,7 @@ If you now edit a pod (via `kubectl edit pod traefik-xxx` and make a change), or
202
202
203
203
!!! note "Where to Go From Here"
204
204
205
-
You have created the [[application]] using a trivial reconciler and a builtin object. See the [[object]] and [[reconciler]] chapters to change it into something more useful. The documents under __Concepts__ on the left navigation menu shows the core concepts that are instrumental to help create the right abstraction.
205
+
You have created the [[application]] using a trivial reconciler and a built-in object. See the [[object]] and [[reconciler]] chapters to change it into something more useful. The documents under __Concepts__ on the left navigation menu shows the core concepts that are instrumental to help create the right abstraction.
Copy file name to clipboardExpand all lines: docs/controllers/gc.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,10 +48,10 @@ This is explained in more detail in [Kubernetes.io :: Finalizers](https://kubern
48
48
49
49
You should mark objects with a finalizer if it needs external cleanup to run in the event it is deleted.
50
50
51
-
The main way to use finalizers with controllers is to define a unique finalizer name (many controllers can finalize an object) and make the [finalizer] helper manage it. The finalizer helper is desingned to be used within a reconciler and split the work depending on the state we are in:
51
+
The main way to use finalizers with controllers is to define a unique finalizer name (many controllers can finalize an object) and make the [finalizer] helper manage it. The finalizer helper is designed to be used within a reconciler and split the work depending on the state we are in:
52
52
53
-
-have a deletion happened, and we need to cleanup? we are in the `Event::Cleanup` arm
54
-
- no deletion has been recorded? we are in the normal `Event::Apply` arm
53
+
-Has a deletion occurred, and do we need to clean up? If so, we are in the `Event::Cleanup` arm
54
+
-Has no deletion been recorded? Then we are in the normal `Event::Apply` arm
55
55
56
56
!!! warning "Finalizers can prevent objects from being deleted"
57
57
@@ -61,7 +61,7 @@ The main way to use finalizers with controllers is to define a unique finalizer
61
61
62
62
In the [secret_syncer example](https://github.com/kube-rs/kube/blob/main/examples/secret_syncer.rs), the controller manages an artificially external secret resource (in reality the example puts it in Kubernetes, but please ignore that) on changes to a `ConfigMap`.
63
63
64
-
Because we cannot normally watch external resources through Kubernetes watches, we have not setup any [[relations]] for the secret. Instead we use the [finalizer] helper in a reconciler (here as a lambda), and delegate to two more specific reconcilers:
64
+
Because we cannot normally watch external resources through Kubernetes watches, we have not setup any [[relations]] for the secret. Instead, we use the [finalizer] helper in a reconciler (here as a lambda), and delegate to two more specific reconcilers:
Copy file name to clipboardExpand all lines: docs/controllers/object.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ We will outline how they interact with controllers and the basics of how to set
14
14
15
15
## Typed Resource
16
16
17
-
This is the most common, and simplest case. Your source of truth is an existing [Kubernetes object found in the openapi spec](https://arnavion.github.io/k8s-openapi/v0.14.x/k8s_openapi/trait.Resource.html#implementors).
17
+
This is the most common, and simplest case. Your source of truth is an existing [Kubernetes object found in the openapi spec](https://docs.rs/k8s-openapi/latest/k8s_openapi/trait.Resource.html#implementors).
18
18
19
19
To use a typed Kubernetes resource as a source of truth in a [Controller], import it from [k8s-openapi], and create an [Api] from it, then pass it to the [Controller].
20
20
@@ -110,7 +110,7 @@ Here, a separate `crdgen` bin entry would install your custom resource using `ca
110
110
111
111
!!! warning "CRD Installation"
112
112
113
-
Be careful with installing CRDs inside a controller at starup. It is customary to provide a generated yaml file so consumers can install a CRD out of band to better support [gitops](https://fluxcd.io/flux/components/helm/helmreleases/#crds) and [helm](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/). See [[security#crd-access]].
113
+
Be careful with installing CRDs inside a controller at startup. It is customary to provide a generated yaml file so consumers can install a CRD out of band to better support [gitops](https://fluxcd.io/flux/components/helm/helmreleases/#crds) and [helm](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/). See [[security#crd-access]].
114
114
115
115
### Imported Custom Resource
116
116
@@ -198,7 +198,7 @@ Untyped resources are using [DynamicObject]; an umbrella container for arbitrary
198
198
199
199
The [DynamicObject] consists of **just the unavoidable properties** like `apiVersion`, `kind`, and `metadata`, whereas the entire spec is loaded onto an arbitrary [serde_json::Value] via [flattening].
200
200
201
-
The benefits you get is that:
201
+
The benefits you get are that:
202
202
203
203
- you avoid having to write out fields manually
204
204
- you **can** achieve tolerance against multiple versions of your object
@@ -270,7 +270,7 @@ This is functionally similar way to deriving `CustomResource` on an incomplete s
270
270
271
271
!!! warning "Partial or dynamic typing always needs additional type information"
272
272
273
-
All usage of `DynamicObject` or `Object` require the use of alternate constructors for multiple interfaces such as [Api] and [Controller]. These constructors have an additional `_with` suffix to carry an associated type for the [Resource] trait.
273
+
All usage of `DynamicObject` or `Object` requires the use of alternate constructors for multiple interfaces such as [Api] and [Controller]. These constructors have an additional `_with` suffix to carry an associated type for the [Resource] trait.
@@ -42,7 +42,7 @@ The state of the world is your main Kubernetes object along with **anything** yo
42
42
43
43
!!! info "The World >= Kubernetes"
44
44
45
-
While your **main** object **must** reside **within Kubernetes**, it is possibly to manage/act on changes **outside Kubernetes**.
45
+
While your **main** object **must** reside **within Kubernetes**, it is possible to manage/act on changes **outside Kubernetes**.
46
46
47
47
You do not have to configure the world, as any [side effect](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) you perform implicitly becomes the world for your controller. It is, however, beneficial to specify any [[relations]] your object has with the world to ensure `reconcile` is correctly invoked:
48
48
@@ -72,7 +72,7 @@ Notice that the [ReconcileReason] is **not included** in the signature of `recon
72
72
73
73
As a result, the reason is just a __best-effort property__ (that we only include for telemetry). You should not attempt to write logic against the reason in your reconciler.
74
74
75
-
Instead, you must write a **defensive reconciler** and handle missed messages, and paritial runs:
75
+
Instead, you must write a **defensive reconciler** and handle missed messages, and partial runs:
76
76
77
77
- assume nothing about why reconciliation started
78
78
- assume the reconciler could have failed at any question mark
@@ -86,7 +86,7 @@ A function is said to be **idempotent** if it can be applied multiple times with
86
86
87
87
!!! warning "A reconciler must be [idempotent]"
88
88
89
-
If a reconciler is triggered twice for the same object, it must cause the same outcome. Care must be taken to ensure operations are not dependent on all-or-nothing approaches, and the flow of the reconciler must be able to recover from errors occurring in a previous reconcile runs.
89
+
If a reconciler is triggered twice for the same object, it must cause the same outcome. Care must be taken to ensure operations are not dependent on all-or-nothing approaches, and the flow of the reconciler must be able to recover from errors occurring in previous reconcile runs.
90
90
91
91
Let us create a reconciler for a custom `PodManager` resource that will:
92
92
@@ -112,7 +112,7 @@ Now, what happens if the timestamp creation fails after the pod got created? The
112
112
113
113
If your reconciler **errored** half-way through a run; the only way you would know **what failed**, is if you check everything.
114
114
115
-
Therefore the correct way to do these two actions it to do them independently:
115
+
Therefore the correct way to do these two actions is to do them independently:
<!-- TODO: ReconcileRequest::from sets reason to Unknow, needs a method to set reason, ReconcileReason -> controller::Reason -->
49
49
50
-
In this case we are extracing an object reference from the spec of our object. Regardless of how you get the information, your mapper must return an iterator of [ObjectRef] for the root object(s) that must be reconciled as a result of the change.
50
+
In this case, we are extracting an object reference from the spec of our object. Regardless of how you get the information, your mapper must return an iterator of [ObjectRef] for the root object(s) that must be reconciled as a result of the change.
51
51
52
52
As a theoretical example; every [HPA](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) object bundles a scale ref to the workload, so you could use this to build a Controller for `Deployment` using HPA as a watched object.
53
53
@@ -62,7 +62,7 @@ Free-form relations to external apis often serve to lift an external resource in
62
62
### External Watches
63
63
If you want changes on an external API to cause changes in the cluster, you will need to a way to stream changes from the external api.
64
64
65
-
The _change events_ must be be provided as a `Stream<Item = ObjectRef>` and passed to [Controller::reconcile_on]. As an example:
65
+
The _change events_ must be provided as a `Stream<Item = ObjectRef>` and passed to [Controller::reconcile_on]. As an example:
In this case we have some opaque `fn watch_external_objects()` which here returns `-> impl Stream<Item = ExternalObject>`. It is meant to return changes from the external API. Whenever a new item is found on the stream, the controller will reconcile the matching cluster object.
79
+
In this case, we have some opaque `fn watch_external_objects()` which here returns `-> impl Stream<Item = ExternalObject>`. It is meant to return changes from the external API. Whenever a new item is found on the stream, the controller will reconcile the matching cluster object.
80
80
81
81
(The example assumes __matching names__ between the external resource and cluster resource, and a __fixed namespace__ for the cluster resources.)
82
82
@@ -85,7 +85,7 @@ In this case we have some opaque `fn watch_external_objects()` which here return
85
85
If you do not have a streaming interface (like if you are doing periodic HTTP GETs), you can wrap your data in a `Stream` via either [async_stream](https://docs.rs/async-stream/latest/async_stream/) or by using channels (say [tokio::sync::mpsc](https://docs.rs/tokio/latest/tokio/sync/mpsc/index.html), using the [Receiver](https://docs.rs/tokio/latest/tokio/sync/mpsc/struct.Receiver.html) side as a stream).
86
86
87
87
### External Writes
88
-
If you want to populate an external API from a cluster resource, the you must update the external api from your [[reconciler]] (using the necessary client libraries for that API).
88
+
If you want to populate an external API from a cluster resource, you must update the external api from your [[reconciler]] (using the necessary client libraries for that API).
89
89
90
90
To avoid build-up of generated objects on the external side, you will want to use [[gc#finalizers]], to ensure the external resource gets _safely_ cleaned up on `kubectl delete`.
Copy file name to clipboardExpand all lines: docs/controllers/schemas.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -100,7 +100,7 @@ See [examples/crd_derive_custom_schema](https://github.com/kube-rs/kube/blob/823
100
100
101
101
### Overriding Members
102
102
103
-
When you are implementing or deriving `JsonSchema`, you can overriding specific parts of a `JsonSchema` schema using [`#[schemars(schema_with)]`](https://graham.cool/schemars/examples/7-custom_serialization/). Some specific examples:
103
+
When you are implementing or deriving `JsonSchema`, you can override specific parts of a `JsonSchema` schema using [`#[schemars(schema_with)]`](https://graham.cool/schemars/examples/7-custom_serialization/). Some specific examples:
104
104
105
105
- [overriding merge strategy on a vec](https://github.com/kube-rs/kube/blob/823f4b8db3852e6bdd271e72c56b8c40d6f962a8/examples/crd_derive_schema.rs#L85-L102)
106
106
- [overriding x-kubernetes properties on a condition](https://github.com/kube-rs/kube/blob/823f4b8db3852e6bdd271e72c56b8c40d6f962a8/examples/crd_derive.rs#L60-L85)
@@ -114,9 +114,9 @@ When using `#[kube(schema = "disabled)]`, you are telling [[kube-derive]] not to
114
114
115
115
Setting this option means the [CustomResourceDefinition] provided by [CustomResourceExt] will require modification.
116
116
117
-
Any manual schemas must be attached on the generated [CustomResourceDefinition] before use. An example of this can be found in [examples/crd_derive_no_schema](https://github.com/kube-rs/kube/blob/main/examples/crd_derive_no_schema.rs).
117
+
Any manual schemas must be attached to the generated [CustomResourceDefinition] before use. An example of this can be found in [examples/crd_derive_no_schema](https://github.com/kube-rs/kube/blob/main/examples/crd_derive_no_schema.rs).
118
118
119
-
The main reason for going down this approach is if you are porting a controller with a CRD from another language and you want to 100% conformance to the existing schema out of the gate.
119
+
The main reason for going down this approach is if you are porting a controller with a CRD from another language and you want 100% conformance to the existing schema out of the gate.
120
120
121
121
This method allows eliding the `#[derive(JsonSchema)]` instruction, and possibly also `schemars` from the dependency tree if you are careful with features.
122
122
@@ -138,7 +138,7 @@ This approach will let you use the [1.25 Common Expression Language feature](htt
138
138
There are currently no recommended ways of doing client-side validation with this approach, but there are new [cel parser/interpreter crates](https://crates.io/search?q=cel) and a [cel expression playground](https://playcel.undistro.io/) that might be useful here.
139
139
140
140
### Deriving via Garde
141
-
Using [garde] is a nice for the simple case because it allows doing both client-side validation, and server-side validation, with the caveat that it only works on both sides for **basic validation rules** as [schemars can only pick up on some of them](https://graham.cool/schemars/deriving/attributes/#supported-validator-attributes).
141
+
Using [garde] is nice for the simple case because it allows doing both client-side validation, and server-side validation, with the caveat that it only works on both sides for **basic validation rules** as [schemars can only pick up on some of them](https://graham.cool/schemars/deriving/attributes/#supported-validator-attributes).
142
142
143
143
See [CustomResource#schema-validation](https://docs.rs/kube/latest/kube/derive.CustomResource.html#schema-validation).
0 commit comments