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.
Installing this Function
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
What this function does
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.
Conditionally Running the Function
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 to true
desired.composite.resource.spec.render == true,
evaluates to true
desired.composite.resource.spec.render == false"
evaluates to false
observed.composite.resource.status.ready == true"
evaluates to false
size(desired.resources) == 0
evaluates to false
"test" in desired.resources
evaluates to true
"bad-resource" in desired.resources
evaluates to false
Conditionally Rendering Managed Resources
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
Test this function locally using the Crossplane CLI
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
.
Developing this function
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