11# cli-utils
22
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.
76
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.
1310
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**
1523
1624### Pruning
1725
26+ The Applier automatically deletes objects that were previously applied and then
27+ removed from the input set on a subsequent apply.
28+
1829The current implementation of ` kubectl apply --prune ` uses labels to identify the
1930set of previously applied objects in the prune set calculation. But the use of labels
2031has 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
2233the current ` kubectl apply --prune ` deficiencies by storing the set of previously
2334applied 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
2536to the applied objects are stored in the ` data ` section of the ` ConfigMap ` .
2637
2738The following example illustrates a ` ConfigMap ` resource used as an inventory object:
@@ -47,15 +58,72 @@ metadata:
4758 cli-utils.sigs.k8s.io/inventory-id : 46d8946c-c1fa-4e1d-9357-b37fb9bae25f
4859` ` `
4960
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.
5189
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.
59127
60128In the following example, the `config.kubernetes.io/depends-on` annotation
61129identifies that `pod-c` must be successfully applied prior to `pod-a`
@@ -74,19 +142,46 @@ spec:
74142 image: k8s.gcr.io/pause:2.0
75143` ` `
76144
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+
77160# ## Apply-Time Mutation
78161
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.
87167
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` :
90185
91186` ` ` yaml
92187kind: Pod
@@ -119,6 +214,62 @@ spec:
119214 value: "${pob-b-ip}:${pob-b-port}"
120215` ` `
121216
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+
122273# # Community, discussion, contribution, and support
123274
124275Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).
0 commit comments