This composition function is a fork of the upstream function-patch-and-transform that adds support for Conditional invocation of the function and the rendering of individual resources.
The function can be installed as a Crossplane package, and runs in a Composition Function. This feature requires a minium Crossplane version of 1.14.
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-conditional-patch-and-transform
annotations:
render.crossplane.io/runtime: Development
spec:
package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.4.0
This function enables conditional rendering of the entire function or select resources.
The language used for Conditionals is the Common Expression Language (CEL), which is widely used in the Kubernetes ecosystem.
Composition authors express a CEL condition, and if it returns true
, patch-and-transforms defined in the input
will be processed.
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: conditional-pt.fn.crossplane.io/v1beta1
kind: Resources
condition: observed.composite.resource.spec.env == "prod" && observed.composite.resource.spec.render == true
resources: [...all your resources...]
Using the following XR and RunFunctionRequest inputs (click to expand):
apiVersion: nopexample.org/v1alpha1
kind: XNopResource
metadata:
name: test-resource
spec:
env: dev
render: true
{
"desired": {
"composite": {
"resource": {
"apiVersion": "nopexample.org/v1alpha1",
"kind": "XNopResource",
"metadata": {
"name": "test-resource"
},
"spec": {
"env": "dev",
"render": true
}
}
},
"resources": {
"test": {
"resource": {
"apiVersion": "example.org/v1",
"kind": "CD",
"metadata": {
"name": "cool-42",
"namespace": "default"
}
}
}
}
},
"observed": {
"composite": {
"resource": {
"apiVersion": "nopexample.org/v1alpha1",
"kind": "XNopResource",
"metadata": {
"name": "test-resource"
},
"spec": {
"env": "dev",
"render": true
},
"status": {
"id": "123",
"ready": false
}
}
}
}
}
You can use the CEL Playground to test various queries.
Here are some example queries on the XR and RunFunctionRequest:
desired.composite.resource.spec.env == "dev"
evaluates totrue
desired.composite.resource.spec.render == true,
evaluates totrue
desired.composite.resource.spec.render == false"
evaluates tofalse
observed.composite.resource.status.ready == true"
evaluates tofalse
size(desired.resources) == 0
evaluates tofalse
"test" in desired.resources
evaluates totrue
"bad-resource" in desired.resources
evaluates tofalse
In a similar manner, individual Managed Resources can also be rendered conditionally, see the example at examples/conditional-resources.
Each resource can have a condition
.
resources:
- name: blue-resource
condition: observed.composite.resource.spec.deployment.blue == true
base:
apiVersion: nop.crossplane.io/v1alpha1
kind: NopResource
spec:
forProvider:
If this condition is set in the Claim/XR, the resource will be rendered:
apiVersion: nop.example.org/v1alpha1
kind: XNopConditional
metadata:
name: test-resource
spec:
env: dev
render: true
deployment:
blue: true
green: false
You can use the Crossplane CLI to run any function locally and see what composed resources it would create. This only works with functions - not native P&T.
For example, using the files in the examples directory:
cd examples/conditional-rendering
crossplane beta render xr.yaml composition.yaml functions.yaml
Produces the following output, showing what resources Crossplane would compose:
---
apiVersion: nop.example.org/v1alpha1
kind: XNopResource
metadata:
name: test-resource
---
apiVersion: nop.crossplane.io/v1alpha1
kind: NopResource
metadata:
annotations:
crossplane.io/composition-resource-name: test-resource
generateName: test-resource-
labels:
crossplane.io/composite: test-resource
ownerReferences:
- apiVersion: nop.example.org/v1alpha1
blockOwnerDeletion: true
controller: true
kind: XNopResource
name: test-resource
uid: ""
spec:
forProvider:
conditionAfter:
- conditionStatus: "True"
conditionType: Ready
time: 5s
connectionDetails:
- name: username
value: fakeuser
- name: password
value: verysecurepassword
- name: endpoint
value: 127.0.0.1
fields:
arrayField:
- stringField: array
integerField: 42
objectField:
stringField: object
stringField: string
See the composition functions documentation to learn how to
use crossplane beta render
.
This function uses Go, Docker, and the Crossplane CLI to build functions.
# Run code generation - see input/generate.go
$ go generate ./...
# Run tests - see fn_test.go
$ go test ./...
# Build the function's runtime image - see Dockerfile
$ docker build . --tag=runtime
# Build a function package - see package/crossplane.yaml
$ crossplane xpkg build -f package --embed-runtime-image=runtime