Skip to content

Commit 302250d

Browse files
authored
Merge pull request #589 from karlkfi/karl-readme-update
chore: Update readme with features and packages
2 parents b00a8f8 + 596a6f5 commit 302250d

File tree

1 file changed

+181
-30
lines changed

1 file changed

+181
-30
lines changed

README.md

Lines changed: 181 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
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+
1829
The current implementation of `kubectl apply --prune` uses labels to identify the
1930
set of previously applied objects in the prune set calculation. But the use of labels
2031
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
2233
the current `kubectl apply --prune` deficiencies by storing the set of previously
2334
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
2536
to the applied objects are stored in the `data` section of the `ConfigMap`.
2637

2738
The 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

60128
In the following example, the `config.kubernetes.io/depends-on` annotation
61129
identifies 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
92187
kind: 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

124275
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).

0 commit comments

Comments
 (0)