mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
406 lines
9.7 KiB
Markdown
406 lines
9.7 KiB
Markdown
# Simple addition of one string value
|
|
|
|
[DRY]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
|
|
|
|
Suppose you have several distinct cloud _projects_
|
|
(on GCP or AWS or whatever) named:
|
|
|
|
* cat-111
|
|
* dog-222
|
|
* fox-333
|
|
|
|
These might be project names within the company,
|
|
cloud billing identifiers, or both.
|
|
|
|
Further suppose
|
|
|
|
* You want to deploy these projects to different
|
|
k8s namespaces, named after the projects.
|
|
|
|
* You need to specify the project name
|
|
in various resource subfields.
|
|
|
|
* You want to name the configuration
|
|
directories using the project name.
|
|
|
|
Additionally you might want to deploy the
|
|
projects one at a time, or all at once.
|
|
|
|
Ideally, you'll want to avoid specifying
|
|
the project name in more than one place
|
|
(i.e. you want to stay [DRY]).
|
|
|
|
Here's a possible layout:
|
|
|
|
|
|
> ```
|
|
> ├── all
|
|
> │ └── kustomization.yaml
|
|
> │
|
|
> ├── bases
|
|
> │ └── iam-iap-tunnel
|
|
> │ ├── kustomization.yaml
|
|
> │ └── policymembers.yaml
|
|
> │
|
|
> └── projects
|
|
> ├── cat-111
|
|
> │ └── kustomization.yaml
|
|
> ├── dog-222
|
|
> │ └── kustomization.yaml
|
|
> └── fox-333
|
|
> └── kustomization.yaml
|
|
> ```
|
|
|
|
This layout allows each project to be
|
|
individually buildable:
|
|
|
|
> ```
|
|
> kustomize build projects/cat-111
|
|
> kustomize build projects/dog-222
|
|
> kustomize build projects/fox-333
|
|
> ```
|
|
|
|
or collectively buildable:
|
|
|
|
> ```
|
|
> kustomize build all
|
|
> ```
|
|
|
|
-----
|
|
Make a place to work:
|
|
|
|
<!-- @makePlaceToWork @testAgainstLatestRelease -->
|
|
```
|
|
DEMO_HOME=$(mktemp -d)
|
|
```
|
|
|
|
<!-- @defineLayout @testAgainstLatestRelease -->
|
|
```
|
|
mkdir -p $DEMO_HOME/bases/iam-iap-tunnel
|
|
mkdir -p $DEMO_HOME/transformers/setProject
|
|
mkdir -p $DEMO_HOME/projects/cat-111
|
|
mkdir -p $DEMO_HOME/projects/dog-222
|
|
mkdir -p $DEMO_HOME/projects/fox-333
|
|
```
|
|
|
|
To ground this example with a common problem,
|
|
assume a set of engineers:
|
|
|
|
* red@example.com
|
|
* blue@example.com
|
|
* yellow@example.com
|
|
|
|
who need particular access to one or more projects.
|
|
|
|
Define an instance of `IAMCustomRole`:
|
|
|
|
<!-- @customRole @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/customroles.yaml
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMCustomRole
|
|
metadata:
|
|
name: engineer
|
|
spec:
|
|
title: Colorful Engineer
|
|
permissions:
|
|
- iap.tunnelInstances.accessViaIAP
|
|
stage: GA
|
|
EOF
|
|
```
|
|
|
|
Define corresponding instances of `IAMPolicyMember`.
|
|
|
|
The values in the `resourceRef/external` fields in these instances
|
|
are only partially complete. kustomize will add projectIds to
|
|
these below.
|
|
|
|
The boilerplate in these instances could be eliminated
|
|
by making a _custom generator_, but that's for a
|
|
different tutorial, and with only three instances here
|
|
it's not worth the effort.
|
|
|
|
<!-- @policyMembers @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/policymembers.yaml
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMPolicyMember
|
|
metadata:
|
|
name: iap-tunnel-red
|
|
spec:
|
|
member: user:red@example.com
|
|
role: roles/engineer
|
|
resourceRef:
|
|
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
|
kind: Project
|
|
external: projects
|
|
---
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMPolicyMember
|
|
metadata:
|
|
name: iap-tunnel-blue
|
|
spec:
|
|
member: user:blue@example.com
|
|
role: roles/engineer
|
|
resourceRef:
|
|
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
|
kind: Project
|
|
external: projects
|
|
---
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMPolicyMember
|
|
metadata:
|
|
name: iap-tunnel-yellow
|
|
spec:
|
|
member: user:yellow@example.com
|
|
role: roles/engineer
|
|
resourceRef:
|
|
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
|
kind: Project
|
|
external: projects
|
|
EOF
|
|
```
|
|
|
|
Make a base that combines these:
|
|
|
|
<!-- @makeBase @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/kustomization.yaml
|
|
resources:
|
|
- customroles.yaml
|
|
- policymembers.yaml
|
|
EOF
|
|
```
|
|
|
|
Make a transformer configuration file.
|
|
|
|
The transformer used is called `ValueAddTransformer`. It's
|
|
intended to implement the 'add' operation of
|
|
[IETF RFC 6902 JSON]. The add operation is simple declaration
|
|
of what value to add, and a powerful syntax for specifying where
|
|
to add the value. The value can, for example, be inserted
|
|
into an existing field holding a file path as either a prefix,
|
|
a postfix, or some change
|
|
in the middle (e.g. `/volume/data` becomes `/volume/projectId/data`).
|
|
|
|
[IETF RFC 6902 JSON]: https://tools.ietf.org/html/rfc6902
|
|
|
|
|
|
At the time of writing, this transformer has no dedicated keyword
|
|
in the kustomization file to hold its config. This means
|
|
the config must live in its own file:
|
|
|
|
<!-- @defineSetProjectTransformer @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/transformers/setProject/setProject.yaml
|
|
apiVersion: builtin
|
|
kind: ValueAddTransformer
|
|
metadata:
|
|
name: dirNameAdd
|
|
|
|
# Omitting the 'value:' field means that the current
|
|
# kustomization root directory name will be used as
|
|
# the value.
|
|
# value: not specified!
|
|
|
|
targets:
|
|
- fieldPath: metadata/namespace
|
|
- selector:
|
|
kind: IAMPolicyMember
|
|
fieldPath: spec/resourceRef/external
|
|
filePathPosition: 2
|
|
EOF
|
|
```
|
|
|
|
This file defined both the value to insert and a list of places to
|
|
insert it. It's saying 1) _take the name of the directory I am in_ and
|
|
2) use the name as a namespace on all objects in scope, and 3) add that
|
|
name to the 2nd position in the file path found in the `spec/resourceRef/external`
|
|
field of all `IAMPolicyMember` instances.
|
|
|
|
|
|
To be used, this transformer config file must be referenced
|
|
from some kustomization file's `transformers:` field.
|
|
|
|
This field can contain a path directly to the transformer config file,
|
|
or a path to an encapsulating kustomization root. The latter approach
|
|
allows any number of transformers to be loaded as a group from a local
|
|
or remote location.
|
|
|
|
Here's an example of the latter case that uses a kustomization file to
|
|
list pointers to transformer configs, although in this case it
|
|
references only one transformer config.
|
|
|
|
<!-- @makeTransformerDir @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/transformers/setProject/kustomization.yaml
|
|
resources:
|
|
- setProject.yaml
|
|
EOF
|
|
```
|
|
|
|
Now make the _cat_, _dog_ and _fox_ _variants_.
|
|
|
|
These are the targets that one could
|
|
independently apply to a cluster.
|
|
|
|
<!-- @defineCat @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/projects/cat-111/kustomization.yaml
|
|
resources:
|
|
- ../../bases/iam-iap-tunnel
|
|
transformers:
|
|
- ../../transformers/setProject
|
|
EOF
|
|
```
|
|
|
|
<!-- @defineDog @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/projects/dog-222/kustomization.yaml
|
|
resources:
|
|
- ../../bases/iam-iap-tunnel
|
|
transformers:
|
|
- ../../transformers/setProject
|
|
EOF
|
|
```
|
|
|
|
<!-- @defineFox @testAgainstLatestRelease -->
|
|
```
|
|
cat <<'EOF' >$DEMO_HOME/projects/fox-333/kustomization.yaml
|
|
resources:
|
|
- ../../bases/iam-iap-tunnel
|
|
transformers:
|
|
- ../../transformers/setProject
|
|
EOF
|
|
```
|
|
|
|
Then, optionally, a target to deploy all the projects at once:
|
|
|
|
<!-- @defineAllTarget @testAgainstLatestRelease -->
|
|
```
|
|
mkdir -p $DEMO_HOME/all
|
|
cat <<'EOF' >$DEMO_HOME/all/kustomization.yaml
|
|
resources:
|
|
- ../projects/cat-111
|
|
- ../projects/dog-222
|
|
- ../projects/fox-333
|
|
EOF
|
|
```
|
|
|
|
The layout is now:
|
|
|
|
<!-- @showLayout -->
|
|
```
|
|
tree $DEMO_HOME
|
|
```
|
|
|
|
It should look like:
|
|
|
|
> ```
|
|
> /tmp/someTmpDir
|
|
> ├── all
|
|
> │ └── kustomization.yaml
|
|
> ├── bases
|
|
> │ └── iam-iap-tunnel
|
|
> │ ├── customroles.yaml
|
|
> │ ├── kustomization.yaml
|
|
> │ └── policymembers.yaml
|
|
> ├── projects
|
|
> │ ├── cat-111
|
|
> │ │ └── kustomization.yaml
|
|
> │ ├── dog-222
|
|
> │ │ └── kustomization.yaml
|
|
> │ └── fox-333
|
|
> │ └── kustomization.yaml
|
|
> └── transformers
|
|
> └── setProject
|
|
> ├── kustomization.yaml
|
|
> └── setProject.yaml
|
|
> ```
|
|
|
|
The expected output from building the dog project
|
|
is as follows:
|
|
|
|
<!-- @definedExpectedOutput @testAgainstLatestRelease -->
|
|
```
|
|
cat <<EOF >$DEMO_HOME/out_expected.yaml
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMCustomRole
|
|
metadata:
|
|
name: engineer
|
|
namespace: dog-222
|
|
spec:
|
|
permissions:
|
|
- iap.tunnelInstances.accessViaIAP
|
|
stage: GA
|
|
title: Colorful Engineer
|
|
---
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMPolicyMember
|
|
metadata:
|
|
name: iap-tunnel-blue
|
|
namespace: dog-222
|
|
spec:
|
|
member: user:blue@example.com
|
|
resourceRef:
|
|
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
|
external: projects/dog-222
|
|
kind: Project
|
|
role: roles/engineer
|
|
---
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMPolicyMember
|
|
metadata:
|
|
name: iap-tunnel-red
|
|
namespace: dog-222
|
|
spec:
|
|
member: user:red@example.com
|
|
resourceRef:
|
|
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
|
external: projects/dog-222
|
|
kind: Project
|
|
role: roles/engineer
|
|
---
|
|
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
|
kind: IAMPolicyMember
|
|
metadata:
|
|
name: iap-tunnel-yellow
|
|
namespace: dog-222
|
|
spec:
|
|
member: user:yellow@example.com
|
|
resourceRef:
|
|
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
|
external: projects/dog-222
|
|
kind: Project
|
|
role: roles/engineer
|
|
EOF
|
|
```
|
|
|
|
In this output, the namespace of all instances is the
|
|
project name `dog-222`, and the project name also appears
|
|
in the resourceRef field of the `IAMPolicyMember` instances.
|
|
|
|
This project name only appears in the project _directory name_,
|
|
achieving our [DRY] goal.
|
|
|
|
Run the build:
|
|
|
|
<!-- @runIt @testAgainstLatestRelease -->
|
|
```
|
|
kustomize build $DEMO_HOME/projects/dog-222 >$DEMO_HOME/out_actual.yaml
|
|
```
|
|
|
|
and confirm that the actual output matches the expected output:
|
|
|
|
<!-- @diffShouldExitZero @testAgainstLatestRelease -->
|
|
```
|
|
diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
|
|
```
|
|
|
|
Build all the projects at once like this:
|
|
|
|
<!-- @buildAll @testAgainstLatestRelease -->
|
|
```
|
|
kustomize build $DEMO_HOME/all
|
|
```
|