This is an example of implementing a KCL function for Kustomize. KCL is a constraint-based record & functional domain language. Full documents of KCL can be found here.
KCL can be used to create functions to mutate and/or validate the YAML Kubernetes Resource Model (KRM) input/output format, and we provide Kustomize KCL functions to simplify the function authoring process.
Let’s write a KCL function that adds annotation managed-by=kustomize-kcl
only to Deployment resources.
cat ./examples/set-annotation/local-resource/example-use.yaml | go run main.go
The output YAML is
apiVersion: krm.kcl.dev/v1alpha1 kind: KCLRun metadata: name: set-annotation annotations: config.kubernetes.io/function: | container: image: docker.io/kcllang/kustomize-kcl:v0.2.0 config.kubernetes.io/path: example-use.yaml internal.config.kubernetes.io/path: example-use.yaml # EDIT THE SOURCE! # This should be your KCL code which preloads the `ResourceList` to `option("resource_list") spec: source: | [resource | {if resource.kind == "Deployment": metadata.annotations: {"managed-by" = "kustomize-kcl"}} for resource in option("resource_list").items] --- apiVersion: v1 kind: Service metadata: name: test annotations: config.kubernetes.io/path: example-use.yaml internal.config.kubernetes.io/path: example-use.yaml spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx annotations: managed-by: kustomize-kcl config.kubernetes.io/path: example-use.yaml internal.config.kubernetes.io/path: example-use.yaml spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
# Note: you need add sudo and --as-current-user flags to ensure KCL has permission to write temp files in the container filesystem. kustomize fn run examples/set-annotation/local-resource/ --dry-run
The output YAML is
apiVersion: krm.kcl.dev/v1alpha1 kind: KCLRun metadata: name: set-annotation annotations: config.kubernetes.io/function: | container: image: docker.io/kcllang/kustomize-kcl:v0.2.0 config.kubernetes.io/path: example-use.yaml internal.config.kubernetes.io/path: example-use.yaml # EDIT THE SOURCE! # This should be your KCL code which preloads the `ResourceList` to `option("resource_list") spec: source: | [resource | {if resource.kind == "Deployment": metadata.annotations: {"managed-by" = "kustomize-kcl"}} for resource in option("resource_list").items] --- apiVersion: v1 kind: Service metadata: name: test annotations: config.kubernetes.io/path: example-use.yaml internal.config.kubernetes.io/path: example-use.yaml spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx annotations: managed-by: kustomize-kcl config.kubernetes.io/path: example-use.yaml internal.config.kubernetes.io/path: example-use.yaml spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
This exists non-zero if the KCL code has no errors.
The function is implemented as an image, and built using make image
, and its function is implemented as a go program, which reads a collection of input Resource configuration, passing them to KCL.
See the API struct definition in main.go
for documentation.
source
- the KCL function code.params
- top-level arguments for KCL
The function is invoked by authoring a local Resource with metadata.annotations.[config.kubernetes.io/function]
.
Here's what you can do in the KCL script:
- Read resources from
option("resource_list")
. Theoption("resource_list")
complies with the KRM Functions Specification. You can read the input resources fromoption("resource_list")["items"]
and thefunctionConfig
fromoption("resource_list")["functionConfig"]
. - Return a KPM list for output resources.
- Return an error using
assert {condition}, {error_message}
. - Read the environment variables. e.g.
option("PATH")
(Not yet implemented). - Read the OpenAPI schema. e.g.
option("open_api")["definitions"]["io.k8s.api.apps.v1.Deployment"]
(Not yet implemented).
See here for more examples.
You can directly use KCL standard libraries without importing them, such as regex.match
, math.log
.