Skip to content

Kubernetes Resource Model KCL Specification and Integrations including Kubectl, Kustomize, Helm, Helmfile, Crossplane, KPT, etc.

License

Notifications You must be signed in to change notification settings

kcl-lang/krm-kcl

Repository files navigation

Kubernetes Resource Model (KRM) KCL Specification

Go Report Card GoDoc License

The KRM KCL function SDK contains a KRM KCL spec and an interpreter to run KCL codes to generate, mutate or validate Kubernetes resources.

The KCL programming language can be used to:

  • Add labels or annotations based on a condition.
  • Inject a sidecar container in all KRM resources that contain a PodTemplate.
  • Validate all KRM resources using KCL schema.
  • Use an abstract model to generate KRM resources.

Test the KRM Function

Unit Tests

You need to put your KCL script source in the functionConfig of kind KCLRun and then the function will run the KCL script that you provide.

This function can be used both declaratively and imperatively.

make test

Integration Tests

You need to put your KCL source code or url in the functionConfig of kind KCLRun and then the function will run the KCL code that you provide.

# Verify that the annotation is added to the `Deployment` resource and the other resource `Service` 
# does not have this annotation.
export TEST_FILE=./pkg/options/testdata/yaml_stream/kcl-run-code.yaml
diff \
  <(cat ${TEST_FILE}) \
  <(cat ${TEST_FILE} | go run main.go)

FunctionConfig

To use a KCLRun as the functionConfig, the KCL source must be specified in the source field. Additional parameters can be specified in the params field. The params field supports any complex data structure as long as it can be represented in YAML.

apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
  name: conditionally-add-annotations
spec:
  params:
    toMatch:
      config.kubernetes.io/local-config: "true"
    toAdd:
      configmanagement.gke.io/managed: disabled
  source: |
    params = option("params")
    toMatch = params.toMatch
    toAdd = params.toAdd
    items = [item | {
       # If all annotations are matched, patch more annotations
       if all key, value in toMatch {
          item.metadata.annotations[key] == value
       }:
           metadata.annotations: toAdd
    } for item in option("items")]

In the example above, the script accesses the toMatch parameters using option("params").toMatch.

Besides, the source field supports different KCL sources, which can come from a local file, VCS such as GitHub, OCI registry, HTTP, etc. You can see the specific usage here. Take an OCI source as an example.

apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
  name: set-annotation
spec:
  params:
    annotations:
      config.kubernetes.io/local-config: "true"
  source: oci://ghcr.io/kcl-lang/set-annotation
  credentials: # If private OCI registry
    url: https://<oci-host-url> # or KCL_SRC_URL environment variable
    username: <username> # or KCL_SRC_USERNAME environment variable
    password: <password> # or KCL_SRC_PASSWORD environment variable

For Git Source, we can access specific branches or private repositories through these parameters

Annotations

apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
  name: set-annotation
  annotations:
    krm.kcl.dev/allow-insecure-source: "true"  # Set plain http for the source managed by KCLRun such as a local registry localhost:7900 or insecure http source
spec:
  params:
    annotations:
      config.kubernetes.io/local-config: "true"
  source: oci://localhost:7900/my-repo/set-annotation

Resource Match Constraints

apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
spec:
  params:
    annotations:
      config.kubernetes.io/local-config: "true"
  source: oci://ghcr.io/kcl-lang/set-annotation
  matchConstraints:  # Set resource filter match constraints for the matched types.
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["apps/v1"]
      kinds: ["Deployment"]

Run Config

apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
spec:
  params:
    annotations:
      config.kubernetes.io/local-config: "true"
  source: oci://ghcr.io/kcl-lang/set-annotation
  config: # See [pkg/api/ConfigSpec]
    vendor: true
    sortKeys: true
    disableNone: true
    # omit other fields

External Dependencies

apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
spec:
  # Set the dependencies are the external dependencies for the KCL code.
  # The format of the `dependencies` field is same as the [dependencies]` in the `kcl.mod` file
  dependencies:
    k8s = "1.31"
  source: |
    import k8s.api.core.v1 as k8core

    k8core.Pod {
        spec.containers: [{
            name = "main"
        }]
    }

Guides for Developing KCL

Here's what you can do in the KCL script:

  • Read the input resources from option("items") and the functionConfig from option("functionConfig").
  • Read resources from option("resource_list"). The option("resource_list") complies with the KRM Functions Specification.
  • Return a KRM list for output resources through the variable items.
  • Return an error using assert {condition}, {error_message}.
  • Read the PATH variables. e.g. option("PATH").
  • Read the environment variables. e.g. option("env").

Library

You can directly use KCL standard libraries by importing them e.g., import regex, import math and using them e.g., regex.match, math.log.

Tutorial

  • See here to study more features of KCL.

Examples

  • See here for more examples.

Tools and Integrations

About

Kubernetes Resource Model KCL Specification and Integrations including Kubectl, Kustomize, Helm, Helmfile, Crossplane, KPT, etc.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages