Patch and Transforms

Crossplane Compositions allow for “patch and transform” operations. With patches a Composition can apply changes to the resources defined by the Composition.

When users create Claims, Crossplane passes the settings in the Claim to the associated composite resource. Patches can use these settings to change the associated composite resource or managed resources.

Examples of using patch and transforms include:

  • changing the name of the external resource
  • mapping generic terms like “east” or “west” to specific provider locations
  • appending custom labels or strings to resource fields
Note

Crossplane expects patch and transform operations to be simple changes.
Use Composition Functions for more complex or programmatic modifications.

A Composition patch is the action of changing a field.
A Composition transform modifies the values before applying the patch.

Create a patch

Patches are part of an individual resource inside a Composition.

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 a composite resource or Composition differently depending on the patch type, but all patches reference a fromFieldPath and toFieldPath.

The fromFieldPath defines the patch’s input values. The toFieldPath defines the data to change with a patch.

Here is an example patch applied to a resource in a Composition.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3spec:
 4  resources:
 5    - name: my-composed-resource
 6      base:
 7        # Removed for brevity
 8      patches:
 9        - type: FromCompositeFieldPath
10          fromFieldPath: spec.field1
11          toFieldPath: metadata.labels["patchLabel"]

Selecting fields

Crossplane selects fields in a composite resource or managed resource with a subset of JSONPath selectors, called “field selectors.”

Field selectors can select any field in a composite resource or managed resource object, including the metadata, spec or status fields.

Field selectors 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 selectors

Here are some example selectors from a composite resource object.

SelectorSelected element
kindkind
metadata.labels['crossplane.io/claim-name']my-example-claim
spec.desiredRegioneu-north-1
spec.resourceRefs[0].namemy-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
23  # Removed for brevity

Reuse a patch

A Composition can reuse a patch object on multiple resources with a PatchSet.

To create a PatchSet, define a PatchSets object inside the Composition’s spec.

Each patch inside a PatchSet has a name and a list of patches.

Note

For multiple PatchSets only use a single PatchSets object.

Identify each unique PatchSet with a unique name.

Apply the PatchSet to a resource with a patch type: PatchSet.
Set the patchSetName to the name of the PatchSet.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 4spec:
 5  patchSets:
 6  - name: my-patchset
 7    patches:
 8    - type: FromCompositeFieldPath
 9      fromFieldPath: spec.desiredRegion
10      toFieldPath: spec.forProvider.region
11  resources:
12    - name: bucket1
13      base:
14        # Removed for brevity
15      patches:
16        - type: PatchSet
17          patchSetName: my-patchset
18    - name: bucket2
19      base:
20        # Removed for brevity
21      patches:
22        - type: PatchSet
23          patchSetName: my-patchset  
Important

A PatchSet can’t contain other PatchSets.

Crossplane ignores any transforms or policies in a PatchSet.

Patching between resources

Compositions can’t directly patch between resources in the same Composition.
For example, generating a network resource and patching the resource name to a compute resource.

Important
The ToEnvironmentFieldPath patch can’t read from a Status field.

A resource can patch to a user-defined Status field in the composite resource.

A 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 Composition 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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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

Types of patches

Crossplane supports multiple patch types, each using a different source for data and applying the patch to a different location.

Important

This section describes patches applied to individual resources inside a Composition.

For information about applying patches to an entire composite resource with a Composition’s environment.patches read the Environment Configurations documentation.

Summary of Crossplane patches

Patch TypeData SourceData Destination
FromCompositeFieldPathA field in the composite resource.A field in the patched managed resource.
ToCompositeFieldPathA field in the patched managed resource.A field in the composite resource.
CombineFromCompositeMultiple fields in the composite resource.A field in the patched managed resource.
CombineToCompositeMultiple fields in the patched managed resource.A field in the composite resource.
FromEnvironmentFieldPathData in the in-memory EnvironmentConfig EnvironmentA field in the patched managed resource.
ToEnvironmentFieldPathA field in the patched managed resource.The in-memory EnvironmentConfig Environment.
CombineFromEnvironmentMultiple fields in the in-memory EnvironmentConfig Environment.A field in the patched managed resource.
CombineToEnvironmentMultiple fields in the patched managed resource.A field in the in-memory EnvironmentConfig Environment.

Note

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 Upbound 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  resources:
14    - name: bucket1
15      base:
16        apiVersion: s3.aws.upbound.io/v1beta1
17        kind: Bucket
18        spec:
19          forProvider:
20            region: us-east-2
21    - name: bucket2
22      base:
23        apiVersion: s3.aws.upbound.io/v1beta1
24        kind: Bucket
25        spec:
26          forProvider:
27            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

 1apiVersion: example.org/v1alpha1
 2kind: ExampleClaim
 3metadata:
 4  name: my-example-claim
 5spec:
 6  field1: "field1-text"
 7  field2: "field2-text"
 8  desiredRegion: "eu-north-1"
 9  boolField: false
10  numberField: 10

 1apiVersion: apiextensions.crossplane.io/v1alpha1
 2kind: EnvironmentConfig
 3metadata:
 4  name: example-environment
 5data:
 6  locations:
 7    us: us-east-2
 8    eu: eu-north-1
 9  key1: value1
10  key2: value2

FromCompositeFieldPath

The FromCompositeFieldPath patch takes a value in a composite resource and applies it to a field in the managed resource.

Tip
Use the 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 managed resource to change.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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 managed resource to the composite resource that created it.

Tip
Use ToCompositeFieldPath patches to take data from one managed resource in a Composition and use it in a second managed 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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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

1$ kubectl describe composite
2Name:         my-example-claim-p5pxf
3Labels:       ZoneID=Z2O1EMRO9K5GLX
Important
Crossplane doesn’t apply the patch to the composite resource until the next reconcile loop, after creating the managed resource. This creates a delay between a managed resource being Ready and applying the patch.

CombineFromComposite

The CombineFromComposite patch takes values from the composite resource, combines them and applies them to the managed resource.

Tip
Use the CombineFromComposite patch to create complex strings, like security policies and apply them to a managed 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 managed resource to apply the new string to.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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.

1$ kubectl describe bucket
2Name:         my-resource-eu-north-1-field2-text

CombineToComposite

The CombineToComposite patch takes values from the managed resource, combines them and applies them to the composite resource.

Tip
Use 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.

Important
Writing custom fields in the Status field of a composite resource requires defining the custom fields in the CompositeResourceDefinition first.

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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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

Important

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 EnvironmentConfig environment and applies them to the managed resource.

Tip
Use 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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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

Important

EnvironmentConfigs are an alpha feature. They aren’t enabled by default.

For more information about using an EnvironmentConfig, read the EnvironmentConfigs documentation.

The ToEnvironmentFieldPath patch takes values the managed resource and applies them to the in-memory EnvironmentConfig environment.

Tip
Use ToEnvironmentFieldPath 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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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

Important

EnvironmentConfigs are an alpha feature. They aren’t enabled by default.

For more information about using an EnvironmentConfig, read the EnvironmentConfigs documentation.

The CombineFromEnvironment patch combines multiple values from the in-memory EnvironmentConfig environment and applies them to the managed resource.

Tip
Use 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 managed resource to apply the new string to.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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

Important

EnvironmentConfigs are an alpha feature. They aren’t enabled by default.

For more information about using an EnvironmentConfig, read the EnvironmentConfigs documentation.

The CombineToEnvironment patch combines multiple values from the managed resource and applies them to the in-memory EnvironmentConfig environment.

Tip
Use 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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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 TypeAction
convertConverts an input data type to a different type. Also called “casting.”
mapSelects a specific output based on a specific input.
matchSelects a specific output based on a string or regular expression.
mathApplies a mathematical operation on the input.
stringChange 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: apiextensions.crossplane.io/v1
 2kind: Composition
 3# Removed for brevity
 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.

Tip
Some provider APIs require a field to be a string. Use a 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 valueDescription
boolA boolean value of true or false.
float64A 64-bit float value.
intA 32-bit integer value.
int64A 64-bit integer value.
stringA string value.
objectAn object.
arrayAn 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.

Note
Refer to the Go language docs for a full list of supported suffixes.

Add format: quantity to the convert object to enable quantity suffix support.

1- type: convert
2  convert:
3   toType: float64
4   format: quantity

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.

1- type: convert
2  convert:
3   toType: object
4   format: json
Tip
This conversion is useful for patching keys in an object.

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.

1- type: convert
2  convert:
3   toType: array
4   format: json

Map transforms

The map transform type maps an input value to an output value.

Tip
The 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.

Note
Crossplane throws an error for the patch if the value isn’t found.

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.

Note
Crossplane stops processing matches after the first pattern match.

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.

Important
A 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
Note
The 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
  • mergeOptions

fromFieldPath policy

Using a fromFieldPath: Required policy on a patch requires the fromFieldPath to exist in the composite resource.

Tip
If a resource patch isn’t working applying the 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

Merge options

By default when applying a patch the destination data is overridden. Use mergeOptions to allow patches to merge arrays and objects without overwriting them.

With an array input, use appendSlice: true to append the array data to the end of the existing array.

With an object, use keepMapValues: true to leave existing object keys in tact. The patch updates any matching keys between the input and destination data.

1patches:
2  - type: FromCompositeFieldPath
3    fromFieldPath: spec.desiredRegion
4    toFieldPath: metadata.annotations["eu"]
5    policy:
6      mergeOptions:
7        appendSlice: true
8        keepMapValues: true