Function Patch and Transform
Function Patch and Transform allows you to write a Composition that specifies managed resource (MR) templates, and uses “patch and transform” operations to fill them out. Crossplane fills the templates out with values copied from a claim or composite resource (XR).
A patch copies a value from one resource and patches it onto another resource. A transform modifies the values before applying the patch.
All Compositions used Patch and Transform before Crossplane added support for composition functions.
Function Patch and Transform works like legacy mode: Resources
Compositions,
which Crossplane deprecated in v1.17. The difference is that it uses a
mode: Pipeline
Composition and a function instead of a mode: Resources
Composition.
Here’s an example Composition that uses Function Patch and Transform. When you
create an AcmeBucket
XR that uses this Composition, Crossplane uses the
template to create the Amazon S3 Bucket
MR.
Crossplane copies the value from the AcmeBucket
XR’s spec.desiredRegion
field and patch it onto the Bucket
managed resource’s
spec.forProvider.region
field.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3metadata:
4 name: example
5spec:
6 compositeTypeRef:
7 apiVersion: custom-api.example.org/v1alpha1
8 kind: AcmeBucket
9 mode: Pipeline
10 pipeline:
11 - step: patch-and-transform
12 functionRef:
13 name: function-patch-and-transform
14 input:
15 apiVersion: pt.fn.crossplane.io/v1beta1
16 kind: Resources
17 resources:
18 - name: storage-bucket
19 base:
20 apiVersion: s3.aws.upbound.io/v1beta1
21 kind: Bucket
22 spec:
23 forProvider:
24 region: "us-east-2"
25 patches:
26 - type: FromCompositeFieldPath
27 fromFieldPath: spec.desiredRegion
28 toFieldPath: spec.forProvider.region
Crossplane has four core components that users commonly mix up:
- Composition - A template to define how to create resources.
- composite resource Definition
(
XRD
) - A custom API specification. - composite resource (
XR
) - Created by using the custom API defined in a composite resource Definition. XRs use the Composition template to create new managed resources. - Claim (
XRC
) - Like a composite resource, but with namespace scoping.
Install the function
You must install Function Patch and Transform before you can use it in a Composition. Apply this manifest to install Function Patch and Transform:
1apiVersion: pkg.crossplane.io/v1
2kind: Function
3metadata:
4 name: function-patch-and-transform
5spec:
6 package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
Resource templates
The resources
field the function’s input defines the set of things that a
composite resource creates when it uses this function.
For example, the input can define a template to create a virtual machine and an associated storage bucket at the same time.
The resources
field lists the individual resources with a name
. This name
identifies the resource inside the Composition. It isn’t related to the external
name used with the Provider.
The contents of the base
are identical to creating a standalone
managed resource.
This example uses
provider-upjet-aws
to define a S3 storage Bucket
and EC2 compute Instance
.
After defining the apiVersion
and kind
, define the spec.forProvider
fields
defining the settings of the resource.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: storage-bucket
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: "us-east-2"
11- name: vm
12 base:
13 apiVersion: ec2.aws.upbound.io/v1beta1
14 kind: Instance
15 spec:
16 forProvider:
17 ami: ami-0d9858aa3c6322f73
18 instanceType: t2.micro
19 region: "us-east-2"
When a composite resource uses
this function, the composite resource creates two new managed resources with all
the provided spec.forProvider
settings.
The spec
supports any settings used in a managed resource, including applying
annotations
and labels
or using a specific providerConfigRef
.
crossplane.io/external-name
annotation on the resource to set
the resource’s name in the external system (like AWS).You can use Function Patch and Transform to template other kinds of Crossplane resources, like ProviderConfigs.
You can also template other kinds of composite resource (XR).
You can’t template namespaced resources.
Create a patch
Each entry in the resources
list can include a list of patches. The patches
field takes a list of patches to apply to the individual resource.
Each patch has a type
, which defines what kind of patch action Crossplane
applies.
Patches reference fields inside different resources depending on the patch type,
but all patches reference a fromFieldPath
and toFieldPath
.
The fromFieldPath
is the path to the patch’s input values. The toFieldPath
is the path the patch applies to.
Here’s an example of a patch that copies a value from the composite resource’s
spec.field1
field to the composed Bucket’s labels.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: storage-bucket
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: "us-east-2"
11 patches:
12 - type: FromCompositeFieldPath
13 fromFieldPath: spec.field1
14 toFieldPath: metadata.labels["patchLabel"]
Selecting fields
Crossplane selects fields in a composite resource or managed resource with a subset of JSONPath selectors, called “field paths.”
Field paths can select any field in a composite resource or managed resource
object, including the metadata
, spec
or status
fields.
Field paths can be a string matching a field name or an array index, in
brackets. Field names may use a .
character to select child elements.
Example field paths
Here are some example selectors from a composite resource object.
Selector | Selected element |
---|---|
kind | kind |
metadata.labels['crossplane.io/claim-name'] | my-example-claim |
spec.desiredRegion | eu-north-1 |
spec.resourceRefs[0].name | my-example-claim-978mh-r6z64 |
1$ kubectl get composite -o yaml
2apiVersion: example.org/v1alpha1
3kind: XExample
4metadata:
5 # Removed for brevity
6 labels:
7 crossplane.io/claim-name: my-example-claim
8 crossplane.io/claim-namespace: default
9 crossplane.io/composite: my-example-claim-978mh
10spec:
11 desiredRegion: eu-north-1
12 field1: field1-text
13 resourceRefs:
14 - apiVersion: s3.aws.upbound.io/v1beta1
15 kind: Bucket
16 name: my-example-claim-978mh-r6z64
17 - apiVersion: s3.aws.upbound.io/v1beta1
18 kind: Bucket
19 name: my-example-claim-978mh-cnlhj
20 - apiVersion: s3.aws.upbound.io/v1beta1
21 kind: Bucket
22 name: my-example-claim-978mh-rv5nm
Reuse a patch
You can reuse a patch object on multiple resources by using a PatchSet.
To create a PatchSet, define a patchSets
object in the function’s input.
Each patch inside a PatchSet has a name
and a list of patches
.
Apply the PatchSet to a resource with a patch type: PatchSet
. Set the
patchSetName
to the name
of the PatchSet.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3patchSets:
4- name: my-patchset
5 patches:
6 - type: FromCompositeFieldPath
7 fromFieldPath: spec.desiredRegion
8 toFieldPath: spec.forProvider.region
9resources:
10- name: bucket1
11 base:
12 # Removed for brevity
13 patches:
14 - type: PatchSet
15 patchSetName: my-patchset
16- name: bucket2
17 base:
18 # Removed for brevity
19 patches:
20 - type: PatchSet
21 patchSetName: my-patchset
A PatchSet can’t contain other PatchSets.
Crossplane ignores any transforms or policies in a PatchSet.
Patching between resources
Function Patch and Transform can’t directly patch between two composed resources. For example, generating a network resource and patching the resource name to a compute resource.
A resource can patch to a user-defined status
field in the composite resource.
Another resource can then read from that Status
field to patch a field.
First, define a custom status
in the composite resource Definition and a
custom field, for example secondResource
1kind: CompositeResourceDefinition
2# Removed for brevity.
3spec:
4 # Removed for brevity.
5 versions:
6 - name: v1alpha1
7 schema:
8 openAPIV3Schema:
9 type: object
10 properties:
11 spec:
12 # Removed for brevity.
13 status:
14 type: object
15 properties:
16 secondResource:
17 type: string
Inside the function input the resource with the source data uses a
ToCompositeFieldPath
patch to write data to the status.secondResource
field
in the composite resource.
The destination resource uses a FromCompositeFieldPath
patch to read data from
the composite resource status.secondResource
field in the composite resource
and write it to a label named secondResource
in the managed resource.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 # Removed for brevity
9 patches:
10 - type: ToCompositeFieldPath
11 fromFieldPath: metadata.name
12 toFieldPath: status.secondResource
13- name: bucket2
14 base:
15 apiVersion: s3.aws.upbound.io/v1beta1
16 kind: Bucket
17 # Removed for brevity
18 patches:
19 - type: FromCompositeFieldPath
20 fromFieldPath: status.secondResource
21 toFieldPath: metadata.labels['secondResource']
Describe the composite resource to view the resources
and the
status.secondResource
value.
1$ kubectl describe composite
2Name: my-example-claim-jp7rx
3Spec:
4 # Removed for brevity
5 Resource Refs:
6 Name: my-example-claim-jp7rx-gfg4m
7 # Removed for brevity
8 Name: my-example-claim-jp7rx-fttpj
9Status:
10 # Removed for brevity
11 Second Resource: my-example-claim-jp7rx-gfg4m
Describe the destination managed resource to see the label secondResource
.
1$ kubectl describe bucket
2kubectl describe bucket my-example-claim-jp7rx-fttpj
3Name: my-example-claim-jp7rx-fttpj
4Labels: crossplane.io/composite=my-example-claim-jp7rx
5 secondResource=my-example-claim-jp7rx-gfg4m
Patch with EnvironmentConfigs
Crossplane uses EnvironmentConfigs to create in-memory data stores. Compositions can read and write from this data store as part of the patch process.
EnvironmentConfigs can predefine data that Compositions can use or a composite resource can write data to their in-memory environment for other resources to read.
Read the EnvironmentConfigs page for more information on using EnvironmentConfigs.
To apply a patch using EnvironmentConfigs, first define which EnvironmentConfigs
to use with
environment.environmentConfigs
.
Use either a reference or a selector to identify the EnvironmentConfigs to use.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3# Removed for Brevity
4spec:
5 environment:
6 environmentConfigs:
7 - ref:
8 name: example-environment
9 # Removed for Brevity
Patch a composite resource
To patch between the composite resource and the in-memory environment use
patches
inside of the environment
.
Use the ToCompositeFieldPath
to copy data from the in-memory environment to
the composite resource.
Use the FromCompositeFieldPath
to copy data from the composite resource to the
in-memory environment.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3environment:
4 patches:
5 - type: ToCompositeFieldPath
6 fromFieldPath: tags
7 toFieldPath: metadata.labels[envTag]
8 - type: FromCompositeFieldPath
9 fromFieldPath: metadata.name
10 toFieldPath: newEnvironmentKey
Individual resources can use any data written to their in-memory environment.
Patch an individual resource
To patch an individual resource, inside the patches
of the resource, use
ToEnvironmentFieldPath
to copy data from the resource to the in-memory
environment.
Use FromEnvironmentFieldPath
to copy data to the resource from the in-memory
environment.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: vpc
5 base:
6 apiVersion: ec2.aws.upbound.io/v1beta1
7 kind: VPC
8 spec:
9 forProvider:
10 cidrBlock: 172.16.0.0/16
11 patches:
12 - type: ToEnvironmentFieldPath
13 fromFieldPath: status.atProvider.id
14 toFieldPath: vpcId
15 - type: FromEnvironmentFieldPath
16 fromFieldPath: tags
17 toFieldPath: spec.forProvider.tags
The EnvironmentConfigs page has more information on EnvironmentConfigs options and usage.
Types of patches
Function Patch and Transform supports multiple patch types, each using a different source for data and applying the patch to a different location.
Summary of Crossplane patches
Patch Type | Data Source | Data Destination |
---|---|---|
FromCompositeFieldPath | A field in the composite resource. | A field in the composed resource. |
ToCompositeFieldPath | A field in the composed resource. | A field in the composite resource. |
CombineFromComposite | Multiple fields in the composite resource. | A field in the composed resource. |
CombineToComposite | Multiple fields in the composed resource. | A field in the composite resource. |
FromEnvironmentFieldPath | Data in the in-memory environment | A field in the composed resource. |
ToEnvironmentFieldPath | A field in the composed resource. | The in-memory environment. |
CombineFromEnvironment | Multiple fields in the in-memory environment. | A field in the composed resource. |
CombineToEnvironment | Multiple fields in the composed resource. | A field in the in-memory environment. |
All the following examples use the same set of Compositions, CompositeResourceDefinitions, Claims and EnvironmentConfigs. Only the applied patches change between examples.
All examples rely on provider-aws-s3 to create resources.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3metadata:
4 name: example-composition
5spec:
6 compositeTypeRef:
7 apiVersion: example.org/v1alpha1
8 kind: xExample
9 environment:
10 environmentConfigs:
11 - ref:
12 name: example-environment
13 mode: Pipeline
14 pipeline:
15 - step: patch-and-transform
16 functionRef:
17 name: function-patch-and-transform
18 input:
19 apiVersion: pt.fn.crossplane.io/v1beta1
20 kind: Resources
21 resources:
22 - name: bucket1
23 base:
24 apiVersion: s3.aws.upbound.io/v1beta1
25 kind: Bucket
26 spec:
27 forProvider:
28 region: us-east-2
29 - name: bucket2
30 base:
31 apiVersion: s3.aws.upbound.io/v1beta1
32 kind: Bucket
33 spec:
34 forProvider:
35 region: us-east-2
1apiVersion: apiextensions.crossplane.io/v1
2kind: CompositeResourceDefinition
3metadata:
4 name: xexamples.example.org
5spec:
6 group: example.org
7 names:
8 kind: xExample
9 plural: xexamples
10 claimNames:
11 kind: ExampleClaim
12 plural: exampleclaims
13 versions:
14 - name: v1alpha1
15 served: true
16 referenceable: true
17 schema:
18 openAPIV3Schema:
19 type: object
20 properties:
21 spec:
22 type: object
23 properties:
24 field1:
25 type: string
26 field2:
27 type: string
28 field3:
29 type: string
30 desiredRegion:
31 type: string
32 boolField:
33 type: boolean
34 numberField:
35 type: integer
36 status:
37 type: object
38 properties:
39 url:
40 type: string
FromCompositeFieldPath
The FromCompositeFieldPath
patch takes a value in a composite resource and
applies it to a field in the composed resource.
FromCompositeFieldPath
patch to apply options from users in their
Claims to settings in managed resource forProvider
settings.For example, to use the value desiredRegion
provided by a user in a composite
resource to a managed resource’s region
.
The fromFieldPath
value is a field in the composite resource.
The toFieldPath
value is the field in the composed resource to change.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: FromCompositeFieldPath
13 fromFieldPath: spec.desiredRegion
14 toFieldPath: spec.forProvider.region
View the managed resource to see the updated region
1$ kubectl describe bucket
2Name: my-example-claim-qlr68-29nqf
3# Removed for brevity
4Spec:
5 For Provider:
6 Region: eu-north-1
ToCompositeFieldPath
The ToCompositeFieldPath
writes data from an individual composed resource to
the composite resource that created it.
ToCompositeFieldPath
patches to take data from one composed resource in a
Composition and use it in a second composed resource in the same Composition.For example, after Crossplane creates a new managed resource, take the value
hostedZoneID
and apply it as a label
in the composite resource.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: ToCompositeFieldPath
13 fromFieldPath: status.atProvider.hostedZoneId
14 toFieldPath: metadata.labels['ZoneID']
View the created managed resource to see the
Hosted Zone Id
field.
1$ kubectl describe bucket
2Name: my-example-claim-p5pxf-5vnp8
3# Removed for brevity
4Status:
5 At Provider:
6 Hosted Zone Id: Z2O1EMRO9K5GLX
7 # Removed for brevity
Next view the composite resource and confirm the patch applied the label
CombineFromComposite
The CombineFromComposite
patch takes values from the composite resource,
combines them and applies them to the composed resource.
CombineFromComposite
patch to create complex strings, like security
policies and apply them to a composed resource.For example, use the Claim value desiredRegion
and field2
to generate the
managed resource’s name
The CombineFromComposite
patch only supports the combine
option.
The variables
are the list of fromFieldPath
values from the composite
resource to combine.
The only supported strategy
is strategy: string
.
Optionally you can apply a string.fmt
, based on
Go string formatting to specify how to combine the
strings.
The toFieldPath
is the field in the composed resource to apply the new string
to.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: CombineFromComposite
13 combine:
14 variables:
15 - fromFieldPath: spec.desiredRegion
16 - fromFieldPath: spec.field2
17 strategy: string
18 string:
19 fmt: "my-resource-%s-%s"
20 toFieldPath: metadata.name
Describe the managed resource to see the applied patch.
CombineToComposite
The CombineToComposite
patch takes values from the composed resource, combines
them and applies them to the composite resource.
CombineToComposite
patches to create a single field like a URL from
multiple fields in a managed resource.For example, use the managed resource name
and region
to generate a custom
url
field.
The CombineToComposite
patch only supports the combine
option.
The variables
are the list of fromFieldPath
the managed resource to combine.
The only supported strategy
is strategy: string
.
Optionally you can apply a string.fmt
, based on
Go string formatting to specify how to combine the
strings.
The toFieldPath
is the field in the composite resource to apply the new string
to.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: CombineToComposite
13 combine:
14 variables:
15 - fromFieldPath: metadata.name
16 - fromFieldPath: spec.forProvider.region
17 strategy: string
18 string:
19 fmt: "https://%s.%s.com"
20 toFieldPath: status.url
View the composite resource to verify the applied patch.
1$ kubectl describe composite
2Name: my-example-claim-bjdjw
3API Version: example.org/v1alpha1
4Kind: xExample
5# Removed for brevity
6Status:
7 # Removed for brevity
8 URL: https://my-example-claim-bjdjw-r6ncd.us-east-2.com
FromEnvironmentFieldPath
EnvironmentConfigs are an alpha feature. They aren’t enabled by default.
For more information about using an EnvironmentConfig, read the EnvironmentConfigs documentation.
The FromEnvironmentFieldPath
patch takes values from the in-memory environment
and applies them to the composed resource.
FromEnvironmentFieldPath
to apply custom managed resource settings based
on the current environment.For example, use the environment’s locations.eu
value and apply it as the
region
.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: FromEnvironmentFieldPath
13 fromFieldPath: locations.eu
14 toFieldPath: spec.forProvider.region
Verify managed resource to confirm the applied patch.
1kubectl describe bucket
2Name: my-example-claim-8vrvc-xx5sr
3Labels: crossplane.io/claim-name=my-example-claim
4# Removed for brevity
5Spec:
6 For Provider:
7 Region: eu-north-1
8 # Removed for brevity
ToEnvironmentFieldPath
The ToEnvironmentFieldPath
patch takes a value from the composed resource and
applies it to the in-memory environment.
ToEnvironmentFieldPath
to write data to the environment that any
FromEnvironmentFieldPath patch can access.For example, use the desired region
value and apply it as the environment’s
key1
.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: ToEnvironmentFieldPath
13 fromFieldPath: spec.forProvider.region
14 toFieldPath: key1
Because the environment is in-memory, there is no command to confirm the patch wrote the value to the environment.
CombineFromEnvironment
The CombineFromEnvironment
patch combines multiple values from the in-memory
environment and applies them to the composed resource.
CombineFromEnvironment
patch to create complex strings, like security
policies and apply them to a managed resource.For example, combine multiple fields in the environment to create a unique
annotation
.
The CombineFromEnvironment
patch only supports the combine
option.
The only supported strategy
is strategy: string
.
The variables
are the list of fromFieldPath
values from the in-memory
environment to combine.
Optionally you can apply a string.fmt
, based on
Go string formatting to specify how to combine the
strings.
The toFieldPath
is the field in the composed resource to apply the new string
to.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: CombineFromEnvironment
13 combine:
14 strategy: string
15 variables:
16 - fromFieldPath: key1
17 - fromFieldPath: key2
18 string:
19 fmt: "%s-%s"
20 toFieldPath: metadata.annotations[EnvironmentPatch]
Describe the managed resource to see new
annotation
.
1$ kubectl describe bucket
2Name: my-example-claim-zmxdg-grl6p
3# Removed for brevity
4Annotations: EnvironmentPatch: value1-value2
5# Removed for brevity
CombineToEnvironment
The CombineToEnvironment
patch combines multiple values from the composed
resource and applies them to the in-memory EnvironmentConfig environment.
CombineToEnvironment
patch to create complex strings, like security
policies to use in other managed resources.For example, combine multiple fields in the managed resource to create a unique
string and store it in the environment’s key2
value.
The string combines the managed resource Kind
and region
.
The CombineToEnvironment
patch only supports the combine
option.
The only supported strategy
is strategy: string
.
The variables
are the list of fromFieldPath
values in the managed resource
to combine.
Optionally you can apply a string.fmt
, based on
Go string formatting to specify how to combine the
strings.
The toFieldPath
is the key in the environment to write the new string to.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: CombineToEnvironment
13 combine:
14 strategy: string
15 variables:
16 - fromFieldPath: kind
17 - fromFieldPath: spec.forProvider.region
18 string:
19 fmt: "%s.%s"
20 toFieldPath: key2
Because the environment is in-memory, there is no command to confirm the patch wrote the value to the environment.
Transform a patch
When applying a patch, Crossplane supports modifying the data before applying it as a patch. Crossplane calls this a “transform” operation.
Summary of Crossplane transforms.
Transform Type | Action |
---|---|
convert | Converts an input data type to a different type. Also called “casting.” |
map | Selects a specific output based on a specific input. |
match | Selects a specific output based on a string or regular expression. |
math | Applies a mathematical operation on the input. |
string | Change the input string using Go string formatting. |
Apply a transform directly to an individual patch with the transforms
field.
A transform
requires a type
, indicating the transform action to take.
The other transform field is the same as the type
, in this example, map
.
The other fields depend on the patch type used.
This example uses a type: map
transform, taking the input
spec.desiredRegion
, matching it to either us
or eu
and returning the
corresponding AWS region for the spec.forProvider.region
value.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: bucket1
5 base:
6 apiVersion: s3.aws.upbound.io/v1beta1
7 kind: Bucket
8 spec:
9 forProvider:
10 region: us-east-2
11 patches:
12 - type: FromCompositeFieldPath
13 fromFieldPath: spec.desiredRegion
14 toFieldPath: spec.forProvider.region
15 transforms:
16 - type: map
17 map:
18 us: us-east-2
19 eu: eu-north-1
Convert transforms
The convert
transform type changes the input data type to a different data
type.
convert
type to
change any boolean or integer fields to strings.A convert
transform requires a toType
, defining the output data type.
1patches:
2- type: FromCompositeFieldPath
3 fromFieldPath: spec.numberField
4 toFieldPath: metadata.label["numberToString"]
5 transforms:
6 - type: convert
7 convert:
8 toType: string
Supported toType
values:
toType value | Description |
---|---|
bool | A boolean value of true or false . |
float64 | A 64-bit float value. |
int | A 32-bit integer value. |
int64 | A 64-bit integer value. |
string | A string value. |
object | An object. |
array | An array. |
Converting strings to booleans
When converting from a string to a bool
Crossplane considers the string values
1
, t
, T
, TRUE
, True
and true
equal to the boolean value True
.
The strings 0
, f
, F
, FALSE
, False
and false
are equal to the boolean
value False
.
Converting numbers to booleans
Crossplane considers the integer 1
and float 1.0
equal to the boolean value
True
. Any other integer or float value is False
.
Converting booleans to numbers
Crossplane converts the boolean value True
to the integer 1
or float64
1.0
.
The value False
converts to the integer 0
or float64 0.0
Converting strings to float64
When converting from a string
to a float64
Crossplane supports an optional
format: quantity
field.
Using format: quantity
translates size suffixes like M
for megabyte or Mi
for megabit into the correct float64 value.
Add format: quantity
to the convert
object to enable quantity suffix
support.
Converting strings to objects
Crossplane converts JSON strings to objects.
Add format: json
to the convert
object which is the only supported string
format for this conversion.
The following example adds a tag to a resource with a
customized key
:
1 - type: FromCompositeFieldPath
2 fromFieldPath: spec.clusterName
3 toFieldPath: spec.forProvider.tags
4 transforms:
5 - type: string
6 string:
7 type: Format
8 fmt: '{"kubernetes.io/cluster/%s": "true"}'
9 - type: convert
10 convert:
11 toType: object
12 format: json
Converting strings to arrays
Crossplane converts JSON strings to arrays.
Add format: json
to the convert
object which is the only supported string
format for this conversion.
Map transforms
The map
transform type maps an input value to an output value.
map
transform is useful for translating generic region names like US
or
EU
to provider specific region names.The map
transform compares the value from the fromFieldPath
to the options
listed in the map
.
If Crossplane finds the value, Crossplane puts the mapped value in the
toFieldPath
.
spec.field1
is the string "field1-text"
then Crossplane uses the string
firstField
for the annotation
.
If spec.field1
is the string "field2-text"
then Crossplane uses the string
secondField
for the annotation
.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["myAnnotation"]
5 transforms:
6 - type: map
7 map:
8 "field1-text": "firstField"
9 "field2-text": "secondField"
In this example, the value of spec.field1
is field1-text
.
1$ kubectl describe composite
2Name: my-example-claim-twx7n
3Spec:
4 # Removed for brevity
5 field1: field1-text
The annotation applied to the managed resource is firstField
.
1$ kubectl describe bucket
2Name: my-example-claim-twx7n-ndb2f
3Annotations: crossplane.io/composition-resource-name: bucket1
4 myAnnotation: firstField
5# Removed for brevity.
Match transform
The match
transform is like the map
transform.
The match
transform adds support for regular expressions along with exact
strings and can provide default values if there isn’t a match.
A match
object requires a patterns
object.
The patterns
is a list of one or more patterns to attempt to match the input
value against.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["myAnnotation"]
5 transforms:
6 - type: match
7 match:
8 patterns:
9 - type: literal
10 # Removed for brevity
11 - type: regexp
12 # Removed for brevity
Match patterns
can be either type: literal
to match an exact string or
type: regexp
to match a regular expression.
Match an exact string
Use a pattern
with
type: literal
to match an
exact string.
On a successful match Crossplane provides the
result:
to
the patch toFieldPath
.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["myAnnotation"]
5 transforms:
6 - type: match
7 match:
8 patterns:
9 - type: literal
10 literal: "field1-text"
11 result: "matchedLiteral"
Match a regular expression
Use a pattern
with type: regexp
to match a regular expression.
Define a regexp
key with the value of the regular expression to match.
On a successful match Crossplane provides the result:
to the patch
toFieldPath
.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["myAnnotation"]
5 transforms:
6 - type: match
7 match:
8 patterns:
9 - type: regexp
10 regexp: '^field1.*'
11 result: "foundField1"
Using default values
Optionally you can provide a default value to use if there is no matching pattern.
The default value can either be the original input value or a defined default value.
Use fallbackTo: Value
to provide a default value if a match isn’t found.
For example if the string unknownString
isn’t matched, Crossplane provides the
Value
StringNotFound
to the toFieldPath
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["myAnnotation"]
5 transforms:
6 - type: match
7 match:
8 patterns:
9 - type: literal
10 literal: "UnknownString"
11 result: "foundField1"
12 fallbackTo: Value
13 fallbackValue: "StringNotFound"
To use the original input as the fallback value use fallbackTo: Input
.
Crossplane uses the original fromFieldPath
input for the toFieldPath
value.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["myAnnotation"]
5 transforms:
6 - type: match
7 match:
8 patterns:
9 - type: literal
10 literal: "UnknownString"
11 result: "foundField1"
12 fallbackTo: Input
Math transforms
Use the math
transform to multiply an input or apply a minimum or maximum
value.
math
transform only supports integer inputs.1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.numberField
4 toFieldPath: metadata.annotations["mathAnnotation"]
5 transforms:
6 - type: math
7 math:
8 ...
clampMin
The type: clampMin
uses a defined minimum value if an input is larger than the
type: clampMin
value.
For example, this type: clampMin
requires an input to be greater than 20
.
If an input is lower than 20
, Crossplane uses the clampMin
value for the
toFieldPath
.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.numberField
4 toFieldPath: metadata.annotations["mathAnnotation"]
5 transforms:
6 - type: math
7 math:
8 type: clampMin
9 clampMin: 20
clampMax
The type: clampMax
uses a defined minimum value if an input is larger than the
type: clampMax
value.
For example, this type: clampMax
requires an input to be less than 5
.
If an input is higher than 5
, Crossplane uses the clampMax
value for the
toFieldPath
.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.numberField
4 toFieldPath: metadata.annotations["mathAnnotation"]
5 transforms:
6 - type: math
7 math:
8 type: clampMax
9 clampMax: 5
Multiply
The type: multiply
multiplies the input by the multiply
value.
For example, this type: multiply
multiplies the value from the fromFieldPath
value by 2
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.numberField
4 toFieldPath: metadata.annotations["mathAnnotation"]
5 transforms:
6 - type: math
7 math:
8 type: multiply
9 multiply: 2
multiply
value only supports integers.String transforms
The string
transform applies string formatting or manipulation to string
inputs.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["stringAnnotation"]
5 transforms:
6 - type: string
7 string:
8 type: ...
String transforms support the following
types
String convert
The type: convert
converts the input based on one of the following conversion types:
ToUpper
- Change the string to all upper case letters.ToLower
- Change the string to all lower case letters.ToBase64
- Create a new base64 string from the input.FromBase64
- Create a new text string from a base64 input.ToJson
- Convert the input string to valid JSON.ToSha1
- Create a SHA-1 hash of the input string.ToSha256
- Create a SHA-256 hash of the input string.ToSha512
- Create a SHA-512 hash of the input string.ToAdler32
- Create an Adler32 hash of the input string.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["FIELD1-TEXT"]
5 transforms:
6 - type: string
7 string:
8 type: Convert
9 convert: "ToUpper"
String format
The type: format
applies Go string formatting to the
input.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.field1
4 toFieldPath: metadata.annotations["stringAnnotation"]
5 transforms:
6 - type: string
7 string:
8 type: Format
9 fmt: "the-field-%s"
Join
The type: Join
joins all values in the input array into a string using the
given separator.
This transform only works with array inputs.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.parameters.inputList
4 toFieldPath: spec.targetJoined
5 transforms:
6 - type: string
7 string:
8 type: Join
9 join:
10 separator: ","
Regular expression type
The type: Regexp
extracts the part of the input matching a regular expression.
Optionally use a group
to match a regular expression capture group.
By default Crossplane matches the entire regular expression.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.desiredRegion
4 toFieldPath: metadata.annotations["euRegion"]
5 transforms:
6 - type: string
7 string:
8 type: Regexp
9 regexp:
10 match: '^eu-(.*)-'
11 group: 1
Trim prefix
The type: TrimPrefix
uses
Go’s TrimPrefix and removes characters
from the beginning of a line.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.desiredRegion
4 toFieldPath: metadata.annotations["north-1"]
5 transforms:
6 - type: string
7 string:
8 type: TrimPrefix
9 trim: `eu-
Trim suffix
The type: TrimSuffix
uses
Go’s TrimSuffix and removes characters
from the end of a line.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.desiredRegion
4 toFieldPath: metadata.annotations["eu"]
5 transforms:
6 - type: string
7 string:
8 type: TrimSuffix
9 trim: `-north-1'
Patch policies
Crossplane supports two types of patch policies:
fromFieldPath
toFieldPath
fromFieldPath policy
Using a fromFieldPath: Required
policy on a patch requires the fromFieldPath
to exist in the data source resource.
fromFieldPath: Required
policy
may produce an error in the composite resource to help troubleshoot.By default, Crossplane applies the policy fromFieldPath: Optional
. With
fromFieldPath: Optional
Crossplane ignores a patch if the fromFieldPath
doesn’t exist.
With fromFieldPath: Required
the composite resource produces an error if the
fromFieldPath
doesn’t exist.
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.desiredRegion
4 toFieldPath: metadata.annotations["eu"]
5 policy:
6 fromFieldPath: Required
toFieldPath policy
By default when applying a patch the function replaces the destination data. Use
toFieldPath
to allow patches to merge arrays and objects without overwriting
them.
The toFieldPath
policy supports these options:
Policy | Action |
---|---|
Replace (default) | Replace the value at toFieldPath . |
MergeObjects | Recursively merge into the value at toFieldPath . Keep any conflicting object keys. |
ForceMergeObjects | Recursively merge into the value at toFieldPath . Replace any conflicting object keys. |
MergeObjectsAppendArrays | Like MergeObjects , but append values to arrays instead of replacing them. |
ForceMergeObjectsAppendArrays | Like ForceMergeObjects , but append values to arrays instead of replacing them. |
1patches:
2 - type: FromCompositeFieldPath
3 fromFieldPath: spec.desiredRegion
4 toFieldPath: metadata.annotations["eu"]
5 policy:
6 toFieldPath: MergeObjectsAppendArrays
Composite resource connection details
Function patch and Transform must define the specific secret keys a resource
creates with the connectionDetails
object.
Secret Type | Description |
---|---|
FromConnectionSecretKey | Create a secret key matching the key of a secret generated by the resource. |
FromFieldPath | Create a secret key matching a field path of the resource. |
FromValue | Create a secret key with a predefined value. |
The value
type must use a string value.
The value
isn’t added to the individual resource secret object. The value
only appears in the combined composite resource secret.
1kind: Composition
2spec:
3 writeConnectionSecretsToNamespace: other-namespace
4 mode: Pipeline
5 pipeline:
6 - step: patch-and-transform
7 functionRef:
8 name: function-patch-and-transform
9 input:
10 apiVersion: pt.fn.crossplane.io/v1beta1
11 kind: Resources
12 resources:
13 - name: key
14 base:
15 # Removed for brevity
16 spec:
17 forProvider:
18 # Removed for brevity
19 writeConnectionSecretToRef:
20 namespace: docs
21 name: key1
22 connectionDetails:
23 - name: my-username
24 type: FromConnectionSecretKey
25 fromConnectionSecretKey: username
26 - name: my-field-secret
27 type: FromFieldPath
28 fromFieldPath: spec.forProvider.user
29 - name: my-status-secret
30 type: FromValue
31 value: "docs.crossplane.io"
The connectionDetails
in a resource can reference a secret from a resource
with FromConnectionSecretKey
, from another field in the resource with
FromFieldPath
or a statically defined value with FromValue
.
Crossplane sets the secret key to the name
value.
Describe the secret to view the secret keys inside the secret object.
If more than one resource generates secrets with the same secret key name, Crossplane only saves one value.
Use a custom name
to create unique secret keys.
Crossplane only adds connection details listed in the connectionDetails
to the
combined secret object.
Any connection secrets in a managed resource, not defined in the
connectionDetails
aren’t added to the combined secret object.
1kubectl describe secret
2Name: my-access-key-secret
3Namespace: default
4Labels: <none>
5Annotations: <none>
6
7Type: connection.crossplane.io/v1alpha1
8
9Data
10====
11myUsername: 20 bytes
12myFieldSecret: 24 bytes
13myStaticSecret: 18 bytes
The CompositeResourceDefinition can also limit which keys Crossplane stores from the composite resources.
By default an XRD writes all secret keys listed in the composed resources
connectionDetails
to the combined secret object.
Read the CompositeResourceDefinition documentation for more information on restricting secret keys.
For more information on connection secrets read the Connection Secrets concepts age.
Resource readiness checks
By default Crossplane considers a composite resource or Claim as READY
when
the status of all created resource are Type: Ready
and Status: True
Some resources, for example, a ProviderConfig, don’t have a Kubernetes status
and are never considered Ready
.
Custom readiness checks allow Compositions to define what custom conditions to
meet for a resource to be Ready
.
Ready
.Define a custom readiness check with the readinessChecks
field on a resource.
Checks have a type
defining how to match the resource and a fieldPath
of
which field in the resource to compare.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: <match type>
9 fieldPath: <resource field>
Compositions support matching resource fields by:
Match a string
MatchString
considers the composed resource to be ready when the value of a
field in that resource matches a specified string.
Crossplane only supports exact string matches. Substrings and regular expressions aren’t supported in a readiness check.
For example, matching the string Online
in the resource’s
status.atProvider.state
field.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: MatchString
9 fieldPath: status.atProvider.state
10 matchString: "Online"
Match an integer
MatchInteger
considers the composed resource to be ready when the value of a
field in that resource matches a specified integer.
Crossplane doesn’t support matching 0
.
For example, matching the number 4
in the resource’s status.atProvider.state
field.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: MatchInteger
9 fieldPath: status.atProvider.state
10 matchInteger: 4
Match that a field exists
NonEmpty
considers the composed resource to be ready when a field exists with
a value.
Crossplane considers a value of 0
or an empty string as empty.
For example, to check that a resource’s status.atProvider.state
field isn’t
empty.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: NonEmpty
9 fieldPath: status.atProvider.state
NonEmpty
doesn’t
require setting any other fields.Always consider a resource ready
None
considers the composed resource to be ready as soon as it’s created.
Crossplane doesn’t wait for any other conditions before declaring the resource
ready.
For example, consider my-resource
ready as soon as it’s created.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: None
Match a condition
Condition
considers the composed resource to be ready when it finds the
expected condition type, with the expected status for it in its
status.conditions
.
For example, consider my-resource
, which is ready if there is a condition of
type MyType
with a status of Success
.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: MatchCondition
9 matchCondition:
10 type: MyType
11 status: Success
Match a boolean
Two types of checks exist for matching boolean fields:
MatchTrue
MatchFalse
MatchTrue
considers the composed resource to be ready when the value of a
field inside that resource is true
.
MatchFalse
considers the composed resource to be ready when the value of a
field inside that resource is false
.
For example, consider
my-resource
, which is
ready if
status.atProvider.manifest.status.ready
is true
.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: MatchTrue
9 fieldPath: status.atProvider.manifest.status.ready
MatchTrue
doesn’t
require setting any other fields.MatchFalse
matches fields that express readiness with the value false
.
For example, consider my-resource
, is ready if status.atProvider.manifest.status.pending
is false
.
1apiVersion: pt.fn.crossplane.io/v1beta1
2kind: Resources
3resources:
4- name: my-resource
5 base:
6 # Removed for brevity
7 readinessChecks:
8 - type: MatchFalse
9 fieldPath: status.atProvider.manifest.status.pending
MatchFalse
doesn’t require setting any other fields.