Giter Club home page Giter Club logo

celpatch's Introduction

Proof of concept: Use CEL templates to mutate Kubernetes resources.

This uses CEL expressions to create "apply configurations" of objects, which are then merged into a Kubernetes resource using the "merge" operation of server side apply.

For example, given an original object:

apiVersion: group.example.com/v1
kind: Example
metadata:
  name: "alpha"
spec:
  replicas: 1
  list:
    - "a"
    - "b"
  listMap:
    - key: "k1"
      value: "1"
    - key: "k2"
      value: "2"
status:
  availableReplicas: 0

The following CEL expression creates an apply configuration:

Object{
  spec: Object.spec{
    deploymentName: oldObject.metadata.name + '-deployment',
    list: oldObject.spec.list.filter(e, e != 'b'),
    listMap: [
      Object.spec.listMap.item{
        key: "k2",
        value: string(4 * 50)
      }
    ]
  }
}

Which merges into the original object resulting in:

apiVersion: group.example.com/v1
kind: Example
metadata:
  name: alpha
spec:
  deploymentName: alpha-deployment
  list:
    - a
  listMap:
    - key: k1
      value: "1"
    - key: k2
      value: "200"
  replicas: 1
status:
  availableReplicas: 0

Note that because a server side apply merging is used, schema merge directives added to OpenAPI such as x-kubernetes-list-type: map are respected.

Because there is no field manager used for the merge, the merge is applied as if a never-before-used field manager is used to perform the apply. This means that we must do something special to make it possible to unset fields.

We will use CEL's optional type feature:

Object{
    spec: Object.spec{
        ?fieldToRemove: optional.none() # plz remove
    }
}

Sometimes the current state of the object will be needed. This is available via the oldObject variable. For example, to update all containers in a pod to use the "Always" imagePullPolicy:

Object{
    spec: Object.spec{
        containers: oldObject.spec.containers.map(c,
            Object.spec.containers.item{
                name: c.name,
                imagePullPolicy: "Always"
            })
        )
    }
}

On rare occasions, it may be necessary to perform apply directly on part of an object. For example, imagine that the field "widgets" is a list of objects, but the field is not a listType=map, and so there is no way to merge in an added field to each widget using server side apply directly like was done with the above imagePullPolicy example.

A workaround is to recreate all the widgets list, but use apply() on each widget to merge in a single field change:

Object{
    spec: Object.spec{
        containers: oldObject.spec.widgets.map(oldWidget,
            objects.apply(oldWidget, Object.spec.widgets.item{
                part: "xyz"
            })
        )
    }
}

Note that such fields are very rare in the Kubernetes API since they don't work well with server side apply. But this may come in handy with CRDs when the CRD author fails to use x-kubernetes-list-type: map.

Notes

CEL has always supported object construction like the Object{} expression in the above examples. However, we do not need CEL object construction is Kubernetes for validation features, so we had never implemented the NewValue function for Kubernetes types that is required for CEL expressions to actually use object construction. Would need to enable it and define how type names are represented in CEL for OpenAPI. This example uses "Object" name as the root type and then uses the path in the OpenAPIv3 schema to identify nested types.

This repo also contains examples that perform version conversion and that use different approaches.

For example, the mutate-templates directory shows an approach where templates containing CEL expressions are embedded in YAML.

TODO

  • Support listType=map for apply() function's field removal
  • Experiment with Guided APIs, in particular, using field paths to specify which field to modify.

Mutation cases to test:

  • Sidecar injection
  • Auto-population of fields (AlwaysPullImages)
  • Inject environment variable
  • Modify args
  • Inject readiness/liveness probes
  • Clear a field
  • Inject labels/annotations
  • Add if not present

Conversion cases to test:

  • Rename a field
  • Change the type of a field
  • Move a field to a different location in the object
  • Move field from annotations to object (the annotation should be unset in the version with the field)
  • Re-key a listType=map
  • Split a field into two fields (e.g. field="a/b" becomes field1="a", field2="b")
  • Convert from scalar field to a list of scalars, (e.g. field="a" becomes field1=["a"])
  • Conditionally convert (if apply the transformation, else do nothing)
  • Complex type instantiation (e.g. spec.x,spec.y,spec.z becomes spec.subobj.x, spec.subobj.y, spec.subobj.z)
  • convert from an annotation to a field?
  • Deletions (unsetting a object property, removing a list element or a map entry)
  • Apply a transform to all the objects in a list (e.g. rename a field in a list)

celpatch's People

Contributors

jpbetz avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.