Setters

Create high-level [setters] to provide imperative configuration editing commands.

Creating a setter requires that the package has a Kptfile. If one does not exist for the package, run kpt pkg init DIR/ to create one.

Setters explained

Following is a short explanation of the command that will be demonstrated in this guide.

Data model

  • Fields reference setters through OpenAPI definitions specified as line comments – e.g. # { "$kpt-set": "replicas-setter" }
  • OpenAPI definitions are provided through the Kptfile

Command control flow

  1. Read the package Kptfile and resources.
  2. Change the setter OpenAPI value in the Kptfile
  3. Locate all fields which reference the setter and change their values.
  4. Write both the modified Kptfile and resources back to the package.

This guide walks you through an end-to-end example to create, invoke and delete setters.

Steps

  1. Creating a Setter
  2. Targeting fields using the path
  3. Invoking a Setter
  4. Deleting a Setter
  5. OpenAPI Validations
  6. Required Setters
  7. Setting Lists

Creating a Setter

Setters may be created either manually (by editing the Kptfile directly), or programmatically (through the create-setter command). The create-setter command will:

  1. create a new OpenAPI definition for a setter in the Kptfile
  2. create references to the setter definition on the resource fields
cat <<EOF >deployment.yaml
# deployment.yaml -- original
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3
EOF
# create or update a setter named "replicas"
# match fields with the value "3"
kpt cfg create-setter . replicas 3
# Kptfile -- updated
openAPI:
  definitions:
    io.k8s.cli.setters.replicas:
      x-k8s-cli:
        setter:
          name: "replicas"
          value: "3"
# deployment.yaml -- updated
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3 # {"$kpt-set":"replicas"}

Targeting fields using the path

The basic way to create a setter only matches fields based on the value. But in some situations there might be several fields with the same value, but not all of them should be targeted by the setter. In these situations, use the --field flag to provide either the name of the field, the full path to the field, or a partial (suffix) path to the field. Only fields that match both the path and the value will be targeted by the setter.

# create a setter named "replicas" and but only target the field name replicas in the spec
kpt cfg create-setter hello-world/ replicas 3 --field="spec.replicas"
# deployment-foo.yaml
kind: Deployment
metadata:
  name: foo
  annotations:
    replicas: 3
spec:
  replicas: 3 # {"$kpt-set":"replicas"}

The path is always just the names of the properties on the path to the field, regardless whether the field is nested inside a sequence. Targeting specific elements inside a sequence is not supported.

# create a setter named "mountName" and only target the name of the volume mount
kpt cfg create-setter hello-world/ mountName nginx --field="spec.containers.volumeMounts.name"
# deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - name: nginx # {"$kpt-set":"mountName"}
          mountPath: /usr/share/nginx
        - name: temp
          mountPath: /tmp

Invoking a Setter

kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3 # {"$kpt-set":"replicas"}
# set the replicas field to 5
kpt cfg set . replicas 5
# deployment.yaml -- updated
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3 # {"$kpt-set":"replicas"}

Deleting a Setter

Setters may be deleted either manually (by editing the Kptfile directly), or programmatically (through the delete-setter command). The delete-setter command will:

  1. delete an OpenAPI definition for a setter in the Kptfile
  2. remove references to the setter definition on the resource fields
# Kptfile -- original
openAPI:
  definitions:
    io.k8s.cli.setters.replicas:
      x-k8s-cli:
        setter:
          name: "replicas"
          value: "3"
# deployment.yaml -- original
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3 # {"$kpt-set":"replicas"}
# delete a setter named "replicas"
kpt cfg delete-setter . replicas
# Kptfile -- updated
openAPI:
# deployment.yaml -- updated
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3

OpenAPI Validations

Users can input any additional validation constraints during create-setter operation in the form of openAPI schema. Relevant openAPI specification constraints can be provided in json file format. The set operation validates the input value against provided schema during setter creation and throws an error if the input value doesn’t meet any of the constraints. This example walks you through the steps to work with openAPI validations.

cat <<EOF >schema.json
{"maximum": 10, "type": "integer"}
EOF

# create setter with openAPI property constraints
kpt cfg create-setter . replicas 5 --schema-path schema.json

The command creates setter with the following definition

openAPI:
  definitions:
    io.k8s.cli.setters.replicas:
      maximum: 10
      type: integer
      x-k8s-cli:
        setter:
          name: replicas
          value: "5"
# try to set value not adhering to the constraints
kpt cfg set . replicas 11
error: The input value doesn't validate against provided OpenAPI schema:
validation failure list: replicas in body should be less than or equal to 10
Example schema for integer validation

{
  "maximum": 10,
  "type": "integer",
  "minimum": 3,
  "format": "int64",
  "multipleOf": 2
}

Example schema for string validation

{
  "maxLength": 10,
  "type": "string",
  "minLength": 3,
  "pattern": "^[A-Za-z]+$",
  "enum": [
    "nginx",
    "ubuntu"
  ]
}

Example schema for array validation

{
  "maxItems": 10,
  "type": "array",
  "minItems": 3,
  "uniqueItems": true,
  "items": {
    "type": "string",
    "maxLength": 4
  }
}

Relevant resources for more information: OpenAPI types

Required setters

Package publisher can mark a setter as required to convey the consumer that the setter value must be set before triggering live apply/preview operation on the package. This example walks you through the steps to work with required setters.

# create a setter named "replicas" and mark it as required
kpt cfg create-setter . replicas 3 --required
# deployment-foo.yaml
kind: Deployment
metadata:
  name: foo
spec:
  replicas: 3 # {"$kpt-set":"replicas"}
# Kptfile
openAPI:
  definitions:
    io.k8s.cli.setters.replicas:
      x-k8s-cli:
        setter:
          name: "replicas"
          value: "3"
          required: true
# if you live apply/preview without setting the value
kpt live apply .

error: setter replicas is required but not set, please set it and try again
# set the replicas value
kpt cfg set hello-world/ replicas 4

kpt live apply hello-world/
# Success

Setting Lists

It is possible to create setters for fields which are a list of strings/integers. The setter type must be array, and the reference must be on the list field. The list setter will take variable args for its value rather than a single value.

Note: You should skip passing the value arg while creating array setters. field flag is required for array setters.

cat <<EOF >example.yaml
# example.yaml
apiVersion: example.com/v1beta1
kind: Example
spec:
  list:
  - "a"
  - "b"
EOF
# Kptfile
kind: Kptfile
kpt cfg create-setter . list --type array --field spec.list
# example.yaml
apiVersion: example.com/v1beta1
kind: Example
spec:
  list: # {"$kpt-set":"list"}
    - "a"
    - "b"
# Kptfile
kind: Kptfile
openAPI:
  definitions:
    io.k8s.cli.setters.list:
      type: array
      x-k8s-cli:
        setter:
          name: list
          listValues:
            - a
            - b
kpt cfg set . list c d e
# example.yaml
apiVersion: example.com/v1beta1
kind: Example
spec:
  list: # {"$kpt-set":"list"}
    - "c"
    - "d"
    - "e"
# Kptfile
kind: Kptfile
openAPI:
  definitions:
    io.k8s.cli.setters.list:
      type: array
      x-k8s-cli:
        setter:
          name: list
          listValues:
            - "c"
            - "d"
            - "e"

Last modified October 27, 2020: Regenerate docs (69c9e8e2)