1
1
# cli-utils
2
2
3
- The cli-utils repository contains an actuation library, which wraps ` kubectl apply ` code.
4
- This library allows importers to easily execute ` kubectl apply ` , while also
5
- addressing several deficiencies of the current implementation of ` kubectl apply ` .
6
- The library enhances ` kubectl apply ` in the following ways:
3
+ ` cli-utils ` is a collection of Go libraries designed to facilitate bulk
4
+ actuation of Kubernetes resource objects by wraping and enahancing
5
+ ` kubectl apply ` with a more user friendly abstraction.
7
6
8
- 1 . ** Pruning** : adds new, experimental automatic object deletion functionality.
9
- 2 . ** Sorting** : adds optional resource sorting functionality to apply or delete objects
10
- in a particular order.
11
- 3 . ** Apply Time Mutation** : adds optional functionality to dynamically substitute fields
12
- from one resource config into another.
7
+ While the name incidates a focus on CLI utilities, the project has evolved to
8
+ encompass a broader scope, including CLI use and server-side use in GitOps
9
+ controllers.
13
10
14
- TODO(seans): Add examples of API, once we've achieved an alpha API.
11
+ ## Features
12
+
13
+ 1 . ** Pruning**
14
+ 1 . ** Status Interpretation**
15
+ 1 . ** Status Lookup**
16
+ 1 . ** Diff & Preview**
17
+ 1 . ** Waiting for Reconciliation**
18
+ 1 . ** Resource Ordering**
19
+ 1 . ** Explicit Dependency Ordering**
20
+ 1 . ** Implicit Dependency Ordering**
21
+ 1 . ** Apply Time Mutation**
22
+ 1 . ** CLI Printers**
15
23
16
24
### Pruning
17
25
26
+ The Applier automatically deletes objects that were previously applied and then
27
+ removed from the input set on a subsequent apply.
28
+
18
29
The current implementation of ` kubectl apply --prune ` uses labels to identify the
19
30
set of previously applied objects in the prune set calculation. But the use of labels
20
31
has significant downsides. The current ` kubectl apply --prune ` implemenation is alpha,
21
- and it is improbable that it will graduate to beta. This library attempts to address
32
+ and it is improbable that it will graduate to beta. ` cli-utils ` attempts to address
22
33
the current ` kubectl apply --prune ` deficiencies by storing the set of previously
23
34
applied objects in an ** inventory** object which is applied to the cluster. The
24
- ** inventory ** object is a ` ConfigMap ` with the ` inventory-id ` label , and references
35
+ reference implimentation uses a ` ConfigMap ` as an ** inventory** object , and references
25
36
to the applied objects are stored in the ` data ` section of the ` ConfigMap ` .
26
37
27
38
The following example illustrates a ` ConfigMap ` resource used as an inventory object:
@@ -47,15 +58,72 @@ metadata:
47
58
cli-utils.sigs.k8s.io/inventory-id : 46d8946c-c1fa-4e1d-9357-b37fb9bae25f
48
59
` ` `
49
60
50
- ### Apply Sort Ordering
61
+ ### Status Interpretation
62
+
63
+ The ` kstatus` library can be used to read an object's current status and interpret
64
+ whether that object has be reconciled (aka Current) or not, including whether it
65
+ is expected to never reconcile (aka Failed).
66
+
67
+ # ## Status Lookup
68
+
69
+ In addition to performing interpritation of status from an object in-memory,
70
+ ` cli-utils` can also be used to query status from the server, allowing you to
71
+ retrieve the status of previously or concurrently applied objects.
72
+
73
+ # ## Diff & Preview
74
+
75
+ ` cli-utils` can be used to compare local object manifests with remote objects
76
+ from the server. These can be compared locally with diff or remotely with
77
+ preview (aka dry-run). This can be useful for discovering drift or previewing
78
+ which changes would be made, if the loal manifests were applied.
79
+
80
+ # ## Waiting for Reconciliation
81
+
82
+ The Applier automatically watches applied and deleted objects and tracks their
83
+ status, blocking until the objects have reconciled, failed, or been fully
84
+ deleted.
85
+
86
+ This functionality is similar to `kubectl delete <resource> <name> --wait`, in
87
+ that is waits for all finalizers to complete, except it also works for creates
88
+ and updates.
51
89
52
- Adding an optional ` config.kubernetes.io/depends-on: <OBJECT>` annotation to a
53
- resource config provides apply ordering functionality. After manually specifying
54
- the dependency relationship among applied resources with this annotation, the
55
- library will sort the resources and apply/prune them in the correct order.
56
- Importantly, the library will wait for an object to reconcile successfully within
57
- the cluster before applying dependent resources. Prune (deletion) ordering is
58
- the opposite of apply ordering.
90
+ While there is a `kubectl apply <resource> <name> --wait`, it only waits for
91
+ deletes when combined with `--prune`. `cli-utils` provides an alternative that
92
+ works for all spec changes, waiting for reconciliation, the convergence of
93
+ status to the desired specification. After reconciliation, it is expected that
94
+ the object has reached a steady state until the specification is changed again.
95
+
96
+ # ## Resource Ordering
97
+
98
+ The Applier and Destroyer use resource type to determine which order to apply
99
+ and delete objects.
100
+
101
+ In contrast, when using `kubectl apply`, the objects are applied in alphanumeric
102
+ order of their file names, and top to bottom in each file. With `cli-utils`,
103
+ this manual sorting is unnecessary for many common use cases.
104
+
105
+ # ## Explicit Dependency Ordering
106
+
107
+ While resource ordering provides a smart default user experience, sometimes
108
+ resource type alone is not enough to determine desired ordering. In these cases,
109
+ the user can use explicit dependency ordering by adding a
110
+ `config.kubernetes.io/depends-on : <OBJECT_REFERENCE>` annotation to an object.
111
+
112
+ The Applier and Destroyer use these explicit dependency directives to build a
113
+ dependency tree and flatten it for determining apply ordering. When deleting,
114
+ the order is reversed, ensuring that dependencies are not deleted before the
115
+ objects that depend on them (aka dependents).
116
+
117
+ In addition to ordering the applies and deletes, dependency ordering also waits
118
+ for dependency reconciliation when applying and deletion finalization when
119
+ deleting. This ensures that dependencies are not just applied first, but have
120
+ reconciled before their dependents are applied. Likewise, dependents are not
121
+ just deleted first, but have completed finalization before their dependencies
122
+ are deleted.
123
+
124
+ Also, because dependency ordering is enforced during actuation, a dependency
125
+ cannot be pruned by the Applier unless all its dependents are also deleted. This
126
+ prevents accidental premature deletion of objects that are still in active use.
59
127
60
128
In the following example, the `config.kubernetes.io/depends-on` annotation
61
129
identifies that `pod-c` must be successfully applied prior to `pod-a`
@@ -74,19 +142,46 @@ spec:
74
142
image: k8s.gcr.io/pause:2.0
75
143
` ` `
76
144
145
+ # ## Implicit Dependency Ordering
146
+
147
+ In addition to being able to specify explicit dependencies, `cli-utils`
148
+ automatically detects some implicit dependencies.
149
+
150
+ Implicit dependencies include :
151
+
152
+ 1. Namespace-scoped resource objects depend on their Namespace.
153
+ 2. Custom resource objects depend on their Custom Resource Definition
154
+
155
+ Like resource ordering, implicit dependency ordering improves the apply and
156
+ delete experience to reduce the need to manually specify ordering for many
157
+ common use cases. This allows more objects to be applied together all at once,
158
+ with less manual orchestration.
159
+
77
160
# ## Apply-Time Mutation
78
161
79
- **apply-time mutation** functionality allows library users to dynamically fill in
80
- resource field values from one object into another, even though they are applied
81
- at the same time. By adding a `config.kubernetes.io/apply-time-mutation` annotation,
82
- a resource specifies the field in another object as well as the location for the
83
- local field subsitution. For example, if an object's IP address is set during
84
- actuation, another object applied at the same time can reference that IP address.
85
- This functionality leverages the previously described **Apply Sort Ordering** to
86
- ensure the source resource field is populated before applying the target resource.
162
+ The Applier can dynamically modify objects before applying them, performing
163
+ field value substitution using input(s) from dependency fields.
164
+
165
+ This allows for applying objects together in a set that you would otherwise need
166
+ to seperate into multiple sets, with manual modifications between applies.
87
167
88
- In the following example, `pod-a` will substitute the IP address/port from the
89
- source `pod-b` into the `pod-a` SERVICE_HOST environment variable :
168
+ Apply-Time Mutation is configured using the
169
+ ` config.kubernetes.io/apply-time-mutation` annotation on the target object to be
170
+ modified. The annotation may specify one or more substitutions. Each
171
+ substitution inncludes a source object, and source field path, and a parget
172
+ field path, with an optional token.
173
+
174
+ If the token is specified, the token is
175
+ replaced in the target field value string with the source field value. If the
176
+ token is not specified, the whole target field value is replaced with the
177
+ source field value. This alternatively allows either templated interpretation or
178
+ type preservation.
179
+
180
+ The source and target field paths are specified using JSONPath, allowing for
181
+ robust navigation of complex resource field hierarchies using a familiar syntax.
182
+
183
+ In the following example, `pod-a` will substitute the IP address and port from
184
+ the spec and status of the source `pod-b` into the spec of the target `pod-a` :
90
185
91
186
` ` ` yaml
92
187
kind: Pod
@@ -119,6 +214,62 @@ spec:
119
214
value: "${pob-b-ip}:${pob-b-port}"
120
215
` ` `
121
216
217
+ The primary reason to do this with Apply-Time Mutation, instead of client-side
218
+ manifest templating is that the pod IP is populated by a controller at runtime
219
+ during reconciliation, and is not known before applying.
220
+
221
+ That said, this is a toy example using built-in types. For pods, you probably
222
+ actually want to use DNS for service discovery instead.
223
+
224
+ Most use cases for Apply-Time Mutation are actually using custom resources, as a
225
+ temporary alternative to building higher level abstractions, modifying
226
+ interfaces, or creating dependencies between otherwise independent interfaces.
227
+
228
+ # ## CLI Printers
229
+
230
+ Since the original intent of `cli-utils` was to contain common code for CLIs,
231
+ and end-to-end testing requires a reference implimentation, a few printers are
232
+ included to translate from the primary event stream into STDOUT text :
233
+
234
+ 1. **Event Printer** : The event printer just prints text to STDOT whenever an
235
+ event is recieved.
236
+ 1. **JSON Printer** : The JSON printer converts events into a JSON string per
237
+ line, intended for automated interpretation by machine.
238
+ 1. **Table Printer** : The table printer writes and updates in-place a table
239
+ with one object per line, intended for human consumption.
240
+
241
+ # # Packages
242
+
243
+ ├── **cmd** : the kapply CLI command
244
+ ├── **examples** : examples that serve as additional end-to-end tests using mdrip
245
+ ├── **hack** : hacky scripts used by make
246
+ ├── **pkg**
247
+ │ ├── **apis** : API resources that satisfy the kubernetes Object interface
248
+ │ ├── **apply** : bulk applier and destroyer
249
+ │ ├── **common** : placeholder for common tools that should probably have their own package
250
+ │ ├── **config** : inventory config bootstrapping
251
+ │ ├── **errors** : error printing
252
+ │ ├── **flowcontrol** : flow control enablement discovery
253
+ │ ├── **inventory** : inventory resource reference implimentation
254
+ │ ├── **jsonpath** : utility for using jsonpath to read & write Unstructured object fields
255
+ │ ├── **kstatus** : object status event watcher with ability to reduce status to a single enum
256
+ │ ├── **manifestreader** : bolk resource object manifest reading and parsing
257
+ │ ├── **multierror** : error composition
258
+ │ ├── **object** : library for dealing with Unstructured objects
259
+ │ ├── **ordering** : sort functionality for objects
260
+ │ ├── **print** : CLI output
261
+ │ ├── **printers** : CLI output
262
+ │ └── **testutil** : utility for facilitating testing
263
+ ├── **release** : goreleaser config
264
+ ├── **scripts** : scripts used by make
265
+ └── **test** : end-to-end and stress tests
266
+
267
+ # # kapply
268
+
269
+ To facilitate testing, this repository includes a reference CLI called `kapply`.
270
+ The `kapply` tool is not intended for direct consumer use, but may be useful
271
+ when trying to determine how to best utilize the `cli-utils` library packages.
272
+
122
273
# # Community, discussion, contribution, and support
123
274
124
275
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).
0 commit comments