8.2 KiB
Simple addition of one string value
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:
DEMO_HOME=$(mktemp -d)
mkdir -p $DEMO_HOME/bases/iam-iap-tunnel
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:
who need particular access to one or more projects.
Define an instance of IAMCustomRole:
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 resourceRef/external fields in these instances
are intentionally incomplete, and will be completed
by kustomize below.
The boilerplate in these instances could be removed by making a custom generator, but that's for different tutorial.
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:
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/kustomization.yaml
resources:
- customroles.yaml
- policymembers.yaml
EOF
Make a transformer, which at the moment has no equivalent directive in the kustomization file.
Its purpose will be more evident momentarily.
mkdir -p $DEMO_HOME/transformers/setProject
cat <<'EOF' >$DEMO_HOME/transformers/setProject/kustomization.yaml
resources:
- setProject.yaml
EOF
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
Now make the cat, dog and fox variants.
These are the targets that one could independently apply to a cluster.
cat <<'EOF' >$DEMO_HOME/projects/cat-111/kustomization.yaml
resources:
- ../../bases/iam-iap-tunnel
transformers:
- ../../transformers/setProject
EOF
cat <<'EOF' >$DEMO_HOME/projects/dog-222/kustomization.yaml
resources:
- ../../bases/iam-iap-tunnel
transformers:
- ../../transformers/setProject
EOF
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:
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:
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:
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.
Confirm this is happens:
kustomize build $DEMO_HOME/projects/dog-222 >$DEMO_HOME/out_actual.yaml
Confirm expectations:
diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
Build all the projects at once like this:
kustomize build $DEMO_HOME/all