docs/content/master/guides/function-patch-and-transfor...

2043 lines
56 KiB
Markdown

---
title: Function Patch and Transform
weight: 70
description: "A function that use patches and transforms to change inputs from composite resources before creating managed resources"
---
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
composite resource (XR).
A [patch](#create-a-patch) copies a value from one resource and _patches_ it
onto another resource. A [transform](#transform-a-patch) modifies the values
before applying the patch.
{{<hint "tip" >}}
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.
{{< /hint >}}
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.
```yaml {label="intro"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example
spec:
compositeTypeRef:
apiVersion: custom-api.example.org/v1alpha1
kind: AcmeBucket
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: spec.forProvider.region
```
{{<hint "note" >}}
Patch and transform is best for simpler compositions. It intentionally doesn't
support features like loops and conditionals.
{{</hint >}}
## 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:
```yaml
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: function-patch-and-transform
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
```
{{<hint "tip" >}}
Read the [Composition page]({{<ref "../composition/compositions">}}) to learn more
about Compositions and composition functions.
{{< /hint >}}
## 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.
{{<hint "tip" >}}
Crossplane calls the resources a composite resource creates
_composed resources_.
{{< /hint >}}
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]({{<ref "../managed-resources/managed-resources">}}).
This example uses
[provider-upjet-aws](https://github.com/crossplane-contrib/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.
```yaml {copy-lines="none",label="resources"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
- name: vm
base:
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
ami: ami-0d9858aa3c6322f73
instanceType: t2.micro
region: "us-east-2"
```
When a [composite resource]({{<ref "../composition/composite-resources" >}}) 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`.
{{<hint "note" >}}
Use the `crossplane.io/external-name` annotation on the resource to set
the resource's name in the external system (like AWS).
{{< /hint >}}
{{<hint "tip" >}}
You can use Function Patch and Transform to template any kind of Kubernetes
resource.
{{< /hint >}}
## 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.
```yaml {label="createComp",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.labels["patchLabel"]
```
### Selecting fields
Crossplane selects fields in a composite resource or managed resource with a
subset of [JSONPath selectors](https://kubernetes.io/docs/reference/kubectl/jsonpath/),
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.
{{<table "table" >}}
| Selector | Selected element |
| --- | --- |
| `kind` | `kind` |
| `spec.desiredRegion` | `eu-north-1` |
| `spec.resourceRefs[0].name` | `my-example-978mh-r6z64` |
{{</table >}}
```yaml {label="select",copy-lines="none"}
$ kubectl get composite -o yaml
apiVersion: example.org/v1alpha1
kind: Example
metadata:
# Removed for brevity
labels:
crossplane.io/composite: my-example-978mh
spec:
desiredRegion: eu-north-1
field1: field1-text
crossplane:
resourceRefs:
- apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
name: my-example-978mh-r6z64
- apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
name: my-example-978mh-cnlhj
- apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
name: my-example-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.
```yaml {label="patchset"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
patchSets:
- name: my-patchset
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: spec.forProvider.region
resources:
- name: bucket1
base:
# Removed for brevity
patches:
- type: PatchSet
patchSetName: my-patchset
- name: bucket2
base:
# Removed for brevity
patches:
- type: PatchSet
patchSetName: my-patchset
```
{{<hint "important" >}}
A PatchSet can't contain other PatchSets.
Crossplane ignores any [transforms](#transform-a-patch) or
[policies](#patch-policies) in a PatchSet.
{{< /hint >}}
## 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`
```yaml {label="xrdPatch",copy-lines="13-17"}
kind: CompositeResourceDefinition
# Removed for brevity.
spec:
# Removed for brevity.
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
type: object
properties:
spec:
# Removed for brevity.
status:
type: object
properties:
secondResource:
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.
```yaml {label="patchBetween",copy-lines="9-11"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
# Removed for brevity
patches:
- type: ToCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: status.secondResource
- name: bucket2
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
# Removed for brevity
patches:
- type: FromCompositeFieldPath
fromFieldPath: status.secondResource
toFieldPath: metadata.labels['secondResource']
```
Describe the composite resource to view the `resources` and the
`status.secondResource` value.
```yaml {label="descCompPatch",copy-lines="none"}
$ kubectl describe composite
Name: my-example-jp7rx
Spec:
# Removed for brevity
Resource Refs:
Name: my-example-jp7rx-gfg4m
# Removed for brevity
Name: my-example-jp7rx-fttpj
Status:
# Removed for brevity
Second Resource: my-example-jp7rx-gfg4m
```
Describe the destination managed resource to see the label `secondResource`.
```yaml {label="bucketlabel",copy-lines="none"}
$ kubectl describe bucket
kubectl describe bucket my-example-jp7rx-fttpj
Name: my-example-jp7rx-fttpj
Labels: crossplane.io/composite=my-example-jp7rx
secondResource=my-example-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.
<!-- vale off -->
{{< hint "note" >}}
<!-- vale on -->
Read the [EnvironmentConfigs]({{<ref "../composition/environment-configs" >}}) page
for more information on using EnvironmentConfigs.
{{< /hint >}}
To apply a patch using EnvironmentConfigs, first define which EnvironmentConfigs
to use with
`environment.environmentConfigs`.
<!-- vale Google.Quotes = NO -->
<!-- vale gitlab.SentenceLength = NO -->
<!-- ignore false positive -->
Use either a
[reference]({{<ref "../managed-resources/managed-resources#matching-by-name-reference" >}})
or a [selector]({{<ref "../managed-resources/managed-resources#matching-by-selector" >}}) to
identify the EnvironmentConfigs to use.
<!-- vale Google.Quotes = YES -->
```yaml {label="envselect",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
environment:
environmentConfigs:
- ref:
name: example-environment
# 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.
```yaml {label="xrpatch",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
environment:
patches:
- type: ToCompositeFieldPath
fromFieldPath: tags
toFieldPath: metadata.labels[envTag]
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
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.
```yaml {label="envpatch",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: vpc
base:
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: VPC
spec:
forProvider:
cidrBlock: 172.16.0.0/16
patches:
- type: ToEnvironmentFieldPath
fromFieldPath: status.atProvider.id
toFieldPath: vpcId
- type: FromEnvironmentFieldPath
fromFieldPath: tags
toFieldPath: spec.forProvider.tags
```
The [EnvironmentConfigs]({{<ref "../composition/environment-configs" >}}) 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
{{< table "table table-hover" >}}
| Patch Type | Data Source | Data Destination |
| --- | --- | --- |
| [FromCompositeFieldPath](#fromcompositefieldpath) | A field in the composite resource. | A field in the composed resource. |
| [ToCompositeFieldPath](#tocompositefieldpath) | A field in the composed resource. | A field in the composite resource. |
| [CombineFromComposite](#combinefromcomposite) | Multiple fields in the composite resource. | A field in the composed resource. |
| [CombineToComposite](#combinetocomposite) | Multiple fields in the composed resource. | A field in the composite resource. |
| [FromEnvironmentFieldPath](#fromenvironmentfieldpath) | Data in the in-memory environment | A field in the composed resource. |
| [ToEnvironmentFieldPath](#toenvironmentfieldpath) | A field in the composed resource. | The in-memory environment. |
| [CombineFromEnvironment](#combinefromenvironment) | Multiple fields in the in-memory environment. | A field in the composed resource. |
| [CombineToEnvironment](#combinetoenvironment) | Multiple fields in the composed resource. | A field in the in-memory environment. |
{{< /table >}}
{{<hint "note" >}}
All the following examples use the same set of Compositions,
CompositeResourceDefinitions and EnvironmentConfigs.
Only the applied patches change between examples.
All examples rely on
[provider-aws-s3](https://github.com/crossplane-contrib/provider-upjet-aws)
to create resources.
{{< expand "Reference Composition" >}}
```yaml {copy-lines="all"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example-composition
spec:
compositeTypeRef:
apiVersion: example.org/v1alpha1
kind: Example
environment:
environmentConfigs:
- ref:
name: example-environment
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
- name: bucket2
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
```
{{< /expand >}}
{{<expand "Reference CompositeResourceDefinition" >}}
```yaml {copy-lines="all"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: examples.example.org
spec:
group: example.org
names:
kind: Example
plural: examples
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
field1:
type: string
field2:
type: string
field3:
type: string
desiredRegion:
type: string
boolField:
type: boolean
numberField:
type: integer
status:
type: object
properties:
url:
type: string
```
{{< /expand >}}
{{< expand "Reference XR" >}}
```yaml {copy-lines="all"}
apiVersion: example.org/v1alpha1
kind: Example
metadata:
namespace: default
name: my-example
spec:
field1: "field1-text"
field2: "field2-text"
desiredRegion: "eu-north-1"
boolField: false
numberField: 10
```
{{< /expand >}}
{{< expand "Reference EnvironmentConfig" >}}
```yaml {copy-lines="all"}
apiVersion: apiextensions.crossplane.io/v1beta1
kind: EnvironmentConfig
metadata:
name: example-environment
data:
locations:
us: us-east-2
eu: eu-north-1
key1: value1
key2: value2
```
{{< /expand >}}
{{< /hint >}}
<!-- vale Google.Headings = NO -->
### FromCompositeFieldPath
<!-- vale Google.Headings = YES -->
The `FromCompositeFieldPath` patch takes a value in a composite resource and
applies it to a field in the composed resource.
{{< hint "tip" >}}
Use the `FromCompositeFieldPath` patch to apply options from users in their XRs
to settings in managed resource `forProvider` settings.
{{< /hint >}}
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.
```yaml {label="fromComposite",copy-lines="9-11"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: spec.forProvider.region
```
View the managed resource to see the updated `region`
```yaml {label="fromCompMR",copy-lines="1"}
$ kubectl describe bucket
Name: my-example-qlr68-29nqf
# Removed for brevity
Spec:
For Provider:
Region: eu-north-1
```
<!-- vale Google.Headings = NO -->
### ToCompositeFieldPath
<!-- vale Google.Headings = YES -->
The `ToCompositeFieldPath` writes data from an individual composed resource to
the composite resource that created it.
{{< hint "tip" >}}
Use `ToCompositeFieldPath` patches to take data from one composed resource in a
Composition and use it in a second composed resource in the same Composition.
{{< /hint >}}
For example, after Crossplane creates a new managed resource, take the value
`hostedZoneID` and apply it as a `label` in the composite resource.
```yaml {label="toComposite",copy-lines="9-11"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: ToCompositeFieldPath
fromFieldPath: status.atProvider.hostedZoneId
toFieldPath: metadata.labels['ZoneID']
```
View the created managed resource to see the
`Hosted Zone Id` field.
```yaml {label="toCompMR",copy-lines="none"}
$ kubectl describe bucket
Name: my-example-p5pxf-5vnp8
# Removed for brevity
Status:
At Provider:
Hosted Zone Id: Z2O1EMRO9K5GLX
# Removed for brevity
```
Next view the composite resource and confirm the patch applied the `label`
```yaml {label="toCompositeXR",copy-lines="none"}
$ kubectl describe composite
Name: my-example-p5pxf
Labels: ZoneID=Z2O1EMRO9K5GLX
```
<!-- vale Google.Headings = NO -->
### CombineFromComposite
<!-- vale Google.Headings = YES -->
The `CombineFromComposite` patch takes values from the composite resource,
combines them and applies them to the composed resource.
{{< hint "tip" >}}
Use the `CombineFromComposite` patch to create complex strings, like security
policies and apply them to a composed resource.
{{< /hint >}}
For example, use the XR 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](https://pkg.go.dev/fmt) to specify how to combine the
strings.
The `toFieldPath` is the field in the composed resource to apply the new string
to.
```yaml {label="combineFromComp",copy-lines="11-20"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: CombineFromComposite
combine:
variables:
- fromFieldPath: spec.desiredRegion
- fromFieldPath: spec.field2
strategy: string
string:
fmt: "my-resource-%s-%s"
toFieldPath: metadata.name
```
Describe the managed resource to see the applied patch.
```yaml {label="describeCombineFromComp",copy-lines="none"}
$ kubectl describe bucket
Name: my-resource-eu-north-1-field2-text
```
<!-- vale Google.Headings = NO -->
### CombineToComposite
<!-- vale Google.Headings = YES -->
The `CombineToComposite` patch takes values from the composed resource, combines
them and applies them to the composite resource.
{{<hint "tip" >}}
Use `CombineToComposite` patches to create a single field like a URL from
multiple fields in a managed resource.
{{< /hint >}}
For example, use the managed resource `name` and `region` to generate a custom
`url` field.
{{< hint "important" >}}
Writing custom fields in the status field of a composite resource requires
defining the custom fields in the CompositeResourceDefinition first.
{{< /hint >}}
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](https://pkg.go.dev/fmt) to specify how to combine the
strings.
The `toFieldPath` is the field in the composite resource to apply the new string
to.
```yaml {label="combineToComposite",copy-lines="9-11"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: CombineToComposite
combine:
variables:
- fromFieldPath: metadata.name
- fromFieldPath: spec.forProvider.region
strategy: string
string:
fmt: "https://%s.%s.com"
toFieldPath: status.url
```
View the composite resource to verify the applied patch.
```yaml {copy-lines="none"}
$ kubectl describe composite
Name: my-example-bjdjw
API Version: example.org/v1alpha1
Kind: Example
# Removed for brevity
Status:
# Removed for brevity
URL: https://my-example-bjdjw-r6ncd.us-east-2.com
```
<!-- vale Google.Headings = NO -->
### FromEnvironmentFieldPath
<!-- vale Google.Headings = YES -->
The `FromEnvironmentFieldPath` patch takes values from the in-memory environment
and applies them to the composed resource.
{{<hint "tip" >}}
Use `FromEnvironmentFieldPath` to apply custom managed resource settings based
on the current environment.
{{< /hint >}}
For example, use the environment's `locations.eu` value and apply it as the
`region`.
```yaml {label="fromEnvField",copy-lines="9-11"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: FromEnvironmentFieldPath
fromFieldPath: locations.eu
toFieldPath: spec.forProvider.region
```
Verify managed resource to confirm the applied patch.
```yaml {copy-lines="none"}
kubectl describe bucket
Name: my-example-8vrvc-xx5sr
# Removed for brevity
Spec:
For Provider:
Region: eu-north-1
# Removed for brevity
```
<!-- vale Google.Headings = NO -->
### ToEnvironmentFieldPath
<!-- vale Google.Headings = YES -->
{{<hint "important" >}}
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../composition/environment-configs">}}).
{{< /hint >}}
The `ToEnvironmentFieldPath` patch takes a value from the composed resource and
applies it to the in-memory environment.
{{<hint "tip" >}}
Use `ToEnvironmentFieldPath` to write data to the environment that any
FromEnvironmentFieldPath patch can access.
{{< /hint >}}
For example, use the desired `region` value and apply it as the environment's
`key1`.
```yaml {label="toEnvField",copy-lines="9-11"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: ToEnvironmentFieldPath
fromFieldPath: spec.forProvider.region
toFieldPath: key1
```
Because the environment is in-memory, there is no command to confirm the patch
wrote the value to the environment.
<!-- vale Google.Headings = NO -->
### CombineFromEnvironment
<!-- vale Google.Headings = YES -->
{{<hint "important" >}}
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../composition/environment-configs">}}).
{{< /hint >}}
The `CombineFromEnvironment` patch combines multiple values from the in-memory
environment and applies them to the composed resource.
{{<hint "tip" >}}
Use `CombineFromEnvironment` patch to create complex strings, like security
policies and apply them to a managed resource.
{{< /hint >}}
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](https://pkg.go.dev/fmt) to specify how to combine the
strings.
The `toFieldPath` is the field in the composed resource to apply the new string
to.
```yaml {label="combineFromEnv",copy-lines="11-20"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: CombineFromEnvironment
combine:
strategy: string
variables:
- fromFieldPath: key1
- fromFieldPath: key2
string:
fmt: "%s-%s"
toFieldPath: metadata.annotations[EnvironmentPatch]
```
Describe the managed resource to see new
`annotation`.
```yaml {copy-lines="none",label="combineFromEnvDesc"}
$ kubectl describe bucket
Name: my-example-zmxdg-grl6p
# Removed for brevity
Annotations: EnvironmentPatch: value1-value2
# Removed for brevity
```
<!-- vale Google.Headings = NO -->
### CombineToEnvironment
<!-- vale Google.Headings = YES -->
{{<hint "important" >}}
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../composition/environment-configs">}}).
{{< /hint >}}
The `CombineToEnvironment` patch combines multiple values from the composed
resource and applies them to the in-memory EnvironmentConfig environment.
{{<hint "tip" >}}
Use `CombineToEnvironment` patch to create complex strings, like security
policies to use in other managed resources.
{{< /hint >}}
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](https://pkg.go.dev/fmt) to specify how to combine the
strings.
The `toFieldPath` is the key in the environment to write the new string to.
```yaml {label="combineToEnv",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: CombineToEnvironment
combine:
strategy: string
variables:
- fromFieldPath: kind
- fromFieldPath: spec.forProvider.region
string:
fmt: "%s.%s"
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.
{{< table "table table-hover" >}}
| Transform Type | Action |
| --- | --- |
| [convert](#convert-transforms) | Converts an input data type to a different type. Also called "casting." |
| [map](#map-transforms) | Selects a specific output based on a specific input. |
| [match](#match-transform) | Selects a specific output based on a string or regular expression. |
| [math](#math-transforms) | Applies a mathematical operation on the input. |
| [string](#string-transforms) | Change the input string using [Go string formatting](https://pkg.go.dev/fmt). |
{{< /table >}}
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.
```yaml {label="transform1",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: spec.forProvider.region
transforms:
- type: map
map:
us: us-east-2
eu: eu-north-1
```
### Convert transforms
The `convert` transform type changes the input data type to a different data
type.
{{< hint "tip" >}}
Some provider APIs require a field to be a string. Use a `convert` type to
change any boolean or integer fields to strings.
{{< /hint >}}
A `convert` transform requires a `toType`, defining the output data type.
```yaml {label="convert",copy-lines="none"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.numberField
toFieldPath: metadata.label["numberToString"]
transforms:
- type: convert
convert:
toType: string
```
Supported `toType` values:
{{< table "table table-sm table-hover" >}}
| `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. |
{{< /table >}}
#### 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.
{{<hint "note" >}}
Refer to the [Go language docs](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity)
for a full list of supported suffixes.
{{</hint >}}
Add `format: quantity` to the `convert` object to enable quantity suffix
support.
```yaml {label="format",copy-lines="all"}
- type: convert
convert:
toType: float64
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.
```yaml {label="object",copy-lines="all"}
- type: convert
convert:
toType: object
format: json
```
{{< hint "tip" >}}
This conversion is useful for patching keys in an object.
{{< /hint >}}
The following example adds a tag to a resource with a
`customized key`:
```yaml {label="patch-key",copy-lines="all"}
- type: FromCompositeFieldPath
fromFieldPath: spec.clusterName
toFieldPath: spec.forProvider.tags
transforms:
- type: string
string:
type: Format
fmt: '{"kubernetes.io/cluster/%s": "true"}'
- type: convert
convert:
toType: object
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.
```yaml {label="array",copy-lines="all"}
- type: convert
convert:
toType: array
format: json
```
### Map transforms
The `map` transform type _maps_ an input value to an output value.
{{< hint "tip" >}}
The `map` transform is useful for translating generic region names like `US` or
`EU` to provider specific region names.
{{< /hint >}}
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`.
{{<hint "note" >}}
Crossplane throws an error for the patch if the value isn't found.
{{< /hint >}}
`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`.
```yaml {label="map",copy-lines="none"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["myAnnotation"]
transforms:
- type: map
map:
"field1-text": "firstField"
"field2-text": "secondField"
```
In this example, the value of `spec.field1` is `field1-text`.
```yaml {label="comositeMap",copy-lines="none"}
$ kubectl describe composite
Name: my-example-twx7n
Spec:
# Removed for brevity
field1: field1-text
```
The annotation applied to the managed resource is `firstField`.
```yaml {label="mrMap",copy-lines="none"}
$ kubectl describe bucket
Name: my-example-twx7n-ndb2f
Annotations: crossplane.io/composition-resource-name: bucket1
myAnnotation: firstField
# 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.
```yaml {label="match",copy-lines="1-8"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["myAnnotation"]
transforms:
- type: match
match:
patterns:
- type: literal
# Removed for brevity
- type: regexp
# Removed for brevity
```
Match `patterns` can be either `type: literal` to match an exact string or
`type: regexp` to match a regular expression.
{{<hint "note" >}}
Crossplane stops processing matches after the first pattern match.
{{< /hint >}}
#### 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`.
```yaml {label="matchLiteral"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["myAnnotation"]
transforms:
- type: match
match:
patterns:
- type: literal
literal: "field1-text"
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`.
```yaml {label="matchRegex"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["myAnnotation"]
transforms:
- type: match
match:
patterns:
- type: regexp
regexp: '^field1.*'
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`
```yaml {label="defaultValue"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["myAnnotation"]
transforms:
- type: match
match:
patterns:
- type: literal
literal: "UnknownString"
result: "foundField1"
fallbackTo: Value
fallbackValue: "StringNotFound"
```
To use the original input as the fallback value use `fallbackTo: Input`.
Crossplane uses the original `fromFieldPath` input for the `toFieldPath` value.
```yaml {label="defaultInput"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["myAnnotation"]
transforms:
- type: match
match:
patterns:
- type: literal
literal: "UnknownString"
result: "foundField1"
fallbackTo: Input
```
### Math transforms
Use the `math` transform to multiply an input or apply a minimum or maximum
value.
{{<hint "important">}}
A `math` transform only supports integer inputs.
{{< /hint >}}
```yaml {label="math",copy-lines="1-7"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.numberField
toFieldPath: metadata.annotations["mathAnnotation"]
transforms:
- type: math
math:
...
```
<!-- vale Google.Headings = NO -->
#### clampMin
<!-- vale Google.Headings = YES -->
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`.
```yaml {label="clampMin"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.numberField
toFieldPath: metadata.annotations["mathAnnotation"]
transforms:
- type: math
math:
type: clampMin
clampMin: 20
```
<!-- vale Google.Headings = NO -->
#### clampMax
<!-- vale Google.Headings = YES -->
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`.
```yaml {label="clampMax"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.numberField
toFieldPath: metadata.annotations["mathAnnotation"]
transforms:
- type: math
math:
type: clampMax
clampMax: 5
```
<!-- vale Google.Headings = NO -->
#### Multiply
<!-- vale Google.Headings = YES -->
The `type: multiply` multiplies the input by the `multiply` value.
For example, this `type: multiply` multiplies the value from the `fromFieldPath`
value by `2`
```yaml {label="multiply"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.numberField
toFieldPath: metadata.annotations["mathAnnotation"]
transforms:
- type: math
math:
type: multiply
multiply: 2
```
{{<hint "note" >}}
The `multiply` value only supports integers.
{{< /hint >}}
### String transforms
The `string` transform applies string formatting or manipulation to string
inputs.
```yaml {label="string"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["stringAnnotation"]
transforms:
- type: string
string:
type: ...
```
String transforms support the following
`types`
* [Convert](#string-convert)
* [Format](#string-format)
* [Join](#join)
* [Regexp](#regular-expression-type)
* [TrimPrefix](#trim-prefix)
* [TrimSuffix](#trim-suffix)
#### 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.
```yaml {label="stringConvert"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["FIELD1-TEXT"]
transforms:
- type: string
string:
type: Convert
convert: "ToUpper"
```
#### String format
The `type: format` applies [Go string formatting](https://pkg.go.dev/fmt) to the
input.
```yaml {label="typeFormat"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.field1
toFieldPath: metadata.annotations["stringAnnotation"]
transforms:
- type: string
string:
type: Format
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.
```yaml {label="typeJoin"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.inputList
toFieldPath: spec.targetJoined
transforms:
- type: string
string:
type: Join
join:
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.
```yaml {label="typeRegex"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: metadata.annotations["euRegion"]
transforms:
- type: string
string:
type: Regexp
regexp:
match: '^eu-(.*)-'
group: 1
```
#### Trim prefix
The `type: TrimPrefix` uses
Go's [TrimPrefix](https://pkg.go.dev/strings#TrimPrefix) and removes characters
from the beginning of a line.
```yaml {label="typeTrimP"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: metadata.annotations["north-1"]
transforms:
- type: string
string:
type: TrimPrefix
trim: `eu-
```
#### Trim suffix
The `type: TrimSuffix` uses
Go's [TrimSuffix](https://pkg.go.dev/strings#TrimSuffix) and removes characters
from the end of a line.
```yaml {label="typeTrimS"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: metadata.annotations["eu"]
transforms:
- type: string
string:
type: TrimSuffix
trim: `-north-1'
```
## Patch policies
Crossplane supports two types of patch policies:
* `fromFieldPath`
* `toFieldPath`
<!-- vale Google.Headings = NO -->
### fromFieldPath policy
<!-- vale Google.Headings = YES -->
Using a `fromFieldPath: Required` policy on a patch requires the `fromFieldPath`
to exist in the data source resource.
{{<hint "tip" >}}
If a resource patch isn't working applying the `fromFieldPath: Required` policy
may produce an error in the composite resource to help troubleshoot.
{{< /hint >}}
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.
```yaml {label="required"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: metadata.annotations["eu"]
policy:
fromFieldPath: Required
```
<!-- vale Google.Headings = NO -->
### toFieldPath policy
<!-- vale Google.Headings = YES -->
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:
{{< table "table table-hover" >}}
| 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. |
{{< /table >}}
```yaml {label="merge"}
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.desiredRegion
toFieldPath: metadata.annotations["eu"]
policy:
toFieldPath: MergeObjectsAppendArrays
```
## Composite resource connection details
Function patch and Transform must define the specific secret keys a resource
creates with the `connectionDetails` object.
{{<table "table table-sm" >}}
| 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. |
{{< /table >}}
{{<hint "note">}}
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.
{{< /hint >}}
```yaml {label="conDeet",copy-lines="none"}
kind: Composition
spec:
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
# Removed for brevity
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: my-username
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: my-field-secret
type: FromFieldPath
fromFieldPath: spec.forProvider.user
- name: my-status-secret
type: FromValue
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.
{{<hint "tip" >}}
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.
{{< /hint >}}
{{<hint "important">}}
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.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl describe secret
Name: my-access-key-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: connection.crossplane.io/v1alpha1
Data
====
myUsername: 20 bytes
myFieldSecret: 24 bytes
myStaticSecret: 18 bytes
```
{{<hint "note" >}}
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.
For more information on connection secrets read about
[managed resources]({{<ref "../managed-resources/managed-resources">}}).
{{</hint>}}
## Resource readiness checks
By default function-patch-and-transform considers a composite resource 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`.
{{< hint "tip" >}}
Use multiple readiness checks if a resource must meet multiple conditions for it
to be `Ready`.
{{< /hint >}}
<!-- vale Google.WordList = NO -->
Define a custom readiness check with the `readinessChecks` field on a resource.
<!-- vale Google.WordList = YES -->
Checks have a `type` defining how to match the resource and a `fieldPath` of
which field in the resource to compare.
```yaml {label="check",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: <match type>
fieldPath: <resource field>
```
Compositions support matching resource fields by:
* [string match](#match-a-string)
* [integer match](#match-an-integer)
* [non-empty match](#match-that-a-field-exists)
* [always ready](#always-consider-a-resource-ready)
* [condition match](#match-a-condition)
* [boolean match](#match-a-boolean)
### Match a string
`MatchString` considers the composed resource to be ready when the value of a
field in that resource matches a specified string.
{{<hint "note" >}}
<!-- vale Google.WordList = NO -->
Crossplane only supports exact string matches. Substrings and regular
expressions aren't supported in a readiness check.
<!-- vale Google.WordList = YES -->
{{</hint >}}
For example, matching the string `Online` in the resource's
`status.atProvider.state` field.
```yaml {label="matchstring",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: MatchString
fieldPath: status.atProvider.state
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.
{{<hint "note" >}}
<!-- vale Google.WordList = NO -->
Crossplane doesn't support matching `0`.
<!-- vale Google.WordList = YES -->
{{</hint >}}
For example, matching the number `4` in the resource's `status.atProvider.state`
field.
```yaml {label="matchint",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: MatchInteger
fieldPath: status.atProvider.state
matchInteger: 4
```
### Match that a field exists
`NonEmpty` considers the composed resource to be ready when a field exists with
a value.
{{<hint "note" >}}
<!-- vale Google.WordList = NO -->
Crossplane considers a value of `0` or an empty string as empty.
{{</hint >}}
For example, to check that a resource's `status.atProvider.state` field isn't
empty.
<!-- vale Google.WordList = YES -->
```yaml {label="NonEmpty",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: NonEmpty
fieldPath: status.atProvider.state
```
{{<hint "tip" >}}
Checking `NonEmpty` doesn't
require setting any other fields.
{{< /hint >}}
### 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.
```yaml {label="none",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- 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`.
```yaml {label="condition",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: MatchCondition
matchCondition:
type: MyType
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`.
```yaml {label="matchTrue",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: MatchTrue
fieldPath: status.atProvider.manifest.status.ready
```
{{<hint "tip" >}}
Checking `MatchTrue` doesn't
require setting any other fields.
{{< /hint >}}
`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`.
```yaml {label="matchFalse",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-resource
base:
# Removed for brevity
readinessChecks:
- type: MatchFalse
fieldPath: status.atProvider.manifest.status.pending
```
{{<hint "tip" >}}
Checking `MatchFalse` doesn't require setting any other fields.
{{< /hint >}}