---
title: Compositions
weight: 30
aliases: 
  - composition
description: "Compositions are a template for creating Crossplane resources"
---

Compositions are a template for creating multiple managed resources as a single
object. 

A Composition _composes_ individual managed resources together into a larger,
reusable, solution.

An example Composition may combine a virtual machine, storage resources and
networking policies. A Composition template links all these individual
resources together. 

{{<expand "Confused about Compositions, XRDs, XRs and Claims?" >}}
Crossplane has four core components that users commonly mix up:

* Compositions - This page. A template to define how to create resources.
* [Composite Resource Definition]({{<ref "./composite-resource-definitions">}})
  (`XRD`) - A custom API specification. 
* [Composite Resource]({{<ref "./composite-resources">}}) (`XR`) - Created by
  using the custom API defined in a Composite Resource Definition. XRs use the
  Composition template to create new managed resources. 
* [Claims]({{<ref "./claims" >}}) (`XRC`) - Like a Composite Resource, but
  with namespace scoping. 
{{</expand >}}

## Creating Compositions

Creating Compositions consists of:
* [Resource templates](#resource-templates) defining the resources to create.
* [Enabling Composite Resources](#enabling-composite-resources) to use this
  Composition template.

<!-- vale Google.WordList = NO -->
Optionally, Compositions also support:
* [Modifying and patching](#changing-resource-fields) resource settings.
* [Storing connection details](#storing-connection-details) and secrets
  generated by the managed resources.
* Using [Composition Functions](#use-composition-functions) to template
  resources using custom programs. 
* Creating a 
  [custom check of when a resource is ready](#resource-readiness-checks) 
  to use. 
<!-- vale Google.WordList = YES -->
 
###  Resource templates
The 
{{<hover label="resources" line="4">}}resources{{</hover>}} field of a 
Composition's 
{{<hover label="resources" line="3">}}spec{{</hover>}} 
defines the set of things that a Composite Resource creates.

{{<hint "note" >}}
Read more about Composite Resources in the 
[Composite Resources page]({{<ref "./composite-resources" >}}). 
{{< /hint >}}
  

For example, a Composition can define a template to create a virtual machine 
and an associated storage bucket at the same time. 

The {{<hover label="resources" line="4">}}resources{{</hover>}} field lists the 
individual resources with a 
{{<hover label="resources" line="5">}}name{{</hover>}}.  
This name identifies the
resource inside the Composition and isn't related to the external name used with
the Provider.

#### Template a managed resource
The contents of the 
{{<hover label="resources" line="6">}}base{{</hover>}} are identical to
creating a standalone [managed resource]({{<ref "./managed-resources">}}).

This example uses 
[Upbound's Provider AWS](https://marketplace.upbound.io/providers/upbound/provider-aws/v0.35.0)
to define a 
S3 storage {{<hover label="resources" line="8">}}Bucket{{</hover>}} and 
EC2 compute {{<hover label="resources" line="15">}}Instance{{</hover>}}.

After defining the 
{{<hover label="resources" line="7">}}apiVersion{{</hover>}} and 
{{<hover label="resources" line="8">}}kind{{</hover>}}, define the 
{{<hover label="resources" line="10">}}spec.forProvider{{</hover>}} fields
defining the settings of the resource.

```yaml {copy-lines="none",label="resources"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - name: StorageBucket
      base:
        apiVersion: s3.aws.upbound.io/v1beta1
        kind: Bucket
        spec:
          forProvider:
            region: "us-east-2"
    - name: VM
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: Instance
        spec:
          forProvider:
            ami: ami-0d9858aa3c6322f73
            instanceType: t2.micro
            region: "us-east-2"
```

When a [Composite Resource]({{<ref "./composite-resources" >}}) uses this
Composition template, the Composite Resource creates two new managed resources
with all the provided 
{{<hover label="resources" line="17">}}spec.forProvider{{</hover>}} settings.

The {{<hover label="resources" line="16">}}spec{{</hover>}}
supports any settings used in a managed resource including
applying `annotations` and `labels` or using a specific 
`providerConfigRef`.

{{<hint "note" >}}
Compositions allow applying a `metadata.name` to a resource's 
{{<hover label="resources" line="16">}}spec{{</hover>}} but ignores it. The
`metadata.name` field doesn't influence the name
of the managed resource in Crossplane or the external resource inside the 
Provider.

Use the `crossplane.io/external-name` annotation on the resource to influence
the external resource name.
{{< /hint >}}

#### Template a ProviderConfig

Compositions can define a ProviderConfig like it defines managed resources.
Generating a ProviderConfig may be useful in providing unique credentials to
each deployment.


```yaml {copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - name: my-aws-provider-config
      base:
        apiVersion: aws.upbound.io/v1beta1
        kind: ProviderConfig
        spec:
          source: Secret
          secretRef:
            namespace: crossplane-system
            name: aws-secret
            key: creds
```


#### Template another Composite Resource

Compositions can use other Composite Resources to define more complicated
templates. 

A common use case is a Composition that uses other
Compositions. For example, creating a Composition to create a standard set of 
networking resources that other Compositions reference. 

{{< hint "note" >}}
Both Compositions must have corresponding XRDs.
{{< /hint >}}

This example networking Composition defines the set of resources required to 
create a new AWS virtual network. This includes a 
{{<hover label="xnetwork" line="8">}}VPC{{</hover>}},
{{<hover label="xnetwork" line="13">}}InternetGateway{{</hover>}} and
{{<hover label="xnetwork" line="18">}}Subnet{{</hover>}}.

```yaml {copy-lines="none",label="xnetwork"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - name: vpc-resource
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        # Removed for Brevity
    - name: gateway-resource
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: InternetGateway
        # Removed for Brevity
    - name: subnet-resource
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: Subnet
        # Removed for Brevity
  compositeTypeRef:
    apiVersion: aws.platformref.upbound.io/v1alpha1
    kind: XNetwork
```

The {{<hover label="xnetwork" line="20">}}compositeTypeRef{{</hover>}} gives
this Composition an 
{{<hover label="xnetwork" line="21">}}apiVersion{{</hover>}} and
{{<hover label="xnetwork" line="22">}}kind{{</hover>}} to reference in another
Composition. 

{{<hint "note" >}}
The [Enabling a Composite Resource](#enabling-composite-resources) section 
describes the 
{{<hover label="xnetwork" line="20">}}compositeTypeRef{{</hover>}} field.
{{< /hint >}}

A second Composition, defining other resources, in this example, an AWS Elastic
Kubernetes Cluster, can reference the previous
{{<hover label="xnetwork" line="22">}}XNetwork{{</hover>}}

```yaml {copy-lines="none",label="xcluster"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - name: nested-network-composition
      base:
        apiVersion: aws.platformref.upbound.io/v1alpha1
        kind: XNetwork
        # Removed for brevity
    - name: eks-cluster-resource
      base:
        apiVersion: eks.aws.upbound.io/v1beta1
        kind: Cluster
        # Removed for brevity
```

When a Composite Resource creates all the managed resources from this 
Composition, the resources defined by the 
{{<hover label="xcluster" line="8">}}XNetwork{{</hover>}} get created along with
the EKS {{<hover label="xcluster" line="13">}}cluster{{</hover >}}. 

{{<hint "note" >}}
This abbreviated example is from the Upbound 
[AWS Reference Platform](https://github.com/upbound/platform-ref-aws).

View the complete Compositions in the reference platform's 
[package directory](https://github.com/upbound/platform-ref-aws/blob/main/apis/cluster/composition.yaml).
{{</hint >}}

#### Cross-resource references

Inside a Composition some resources use identifiers or names of other resources.
For example, creating a new `network` and applying the network identifier to a
virtual machine. 

Resources inside a Composition can cross-reference other resources by matching
a label or a _controller reference_.

{{<hint "note" >}}
Providers allow matching of labels and controller references on a
per-resource basis. Check the documentation for the specific Provider resource
to see what's supported.  

Matching labels and controllers isn't supported across different Providers.
{{< /hint >}}

##### Match resource labels

To match a resource label, first apply a 
{{<hover label="matchlabel" line="11">}}label{{</hover>}} to the resource to 
match and use
{{<hover label="matchlabel" line="19">}}matchLabels{{</hover>}} 
in the second resource.

This example creates a AWS 
{{<hover label="matchlabel" line="7">}}Role{{</hover>}} and applies a 
{{<hover label="matchlabel" line="11">}}label{{</hover>}}. The second resource
is a {{<hover label="matchlabel" line="14">}}RolePolicyAttachment{{</hover>}},
which requires attaching to an existing `Role`. 

Using the resource's 
{{<hover label="matchlabel" line="19">}}roleSelector.matchLabels{{</hover>}}
ensures this 
{{<hover label="matchlabel" line="14">}}RolePolicyAttachment{{</hover>}}
references the matching 
{{<hover label="matchlabel" line="7">}}Role{{</hover>}}, even if the unique role
identifier isn't known. 

```yaml {label="matchlabel",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - base:
        apiVersion: iam.aws.upbound.io/v1beta1
        kind: Role
        name: iamRole
        metadata:
          labels:
            role: controlplane
    - base:
        apiVersion: iam.aws.upbound.io/v1beta1
        kind: RolePolicyAttachment
        name: iamPolicy
        spec:
          forProvider:
            roleSelector:
              matchLabels:
                role: controlplane
  # Removed for brevity
```

##### Match a controller reference 

Matching a controller reference ensures that the matching resource is
in the same composite resource. 

Matching only a controller reference simplifies the matching process without
requiring labels or more information. 

For example, creating an AWS 
{{<hover label="controller1" line="14">}}InternetGateway{{</hover>}} requires a
{{<hover label="controller1" line="7">}}VPC{{</hover>}}.

The {{<hover label="controller1" line="14">}}InternetGateway{{</hover>}} could
match a label, but every VPC created by this Composition share the same label. 

Using {{<hover label="controller1" line="19">}}matchControllerRef{{</hover>}}
matches only the VPC created in the same composite resource that created the 
{{<hover label="controller1" line="14">}}InternetGateway{{</hover>}}. 

```yaml {label="controller1",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        name: my-vpc
        spec:
          forProvider:
          # Removed for brevity
    - base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: InternetGateway
        name: my-gateway
        spec:
          forProvider:
            vpcIdSelector:
              matchControllerRef: true
# Removed for brevity
```


Resources can match both labels and a controller reference to match a specific
resource in the larger composite resource. 

For example, this Composition creates two 
{{<hover label="controller2" line="17">}}VPC{{</hover>}}
resources, but the 
{{<hover label="controller2" line="27">}}InternetGateway{{</hover>}} 
must match only one. 

Applying a {{<hover label="controller2" line="21">}}label{{</hover>}} to the 
second {{<hover label="controller2" line="17">}}VPC{{</hover>}} allows the 
{{<hover label="controller2" line="27">}}InternetGateway{{</hover>}} to match
the label
{{<hover label="controller2" line="34">}}type: internet{{</hover>}} and only
match objects in the same composite resource with 
{{<hover label="controller2" line="32">}}matchControllerRef{{</hover>}}.

```yaml {label="controller2",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        name: my-first-vpc
        metadata:
          labels:
            type: backend
        spec:
          forProvider:
          # Removed for brevity
    - base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        name: my-second-vpc
        metadata:
          labels:
            type: internet
        spec:
          forProvider:
          # Removed for brevity
    - base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: InternetGateway
        name: my-gateway
        spec:
          forProvider:
            vpcIdSelector:
              matchControllerRef: true
              matchLabels:
                type: internet
# Removed for brevity
```
### Enabling Composite Resources

A Composition is only a template defining how to create managed 
resources. A Composition limits which Composite Resources can use this
template. 

A Composition's {{<hover label="typeref" line="6">}}compositeTypeRef{{</hover>}} 
defines which Composite Resource type can use this Composition. 

{{<hint "note" >}}
Read more about Composite Resources in the 
[Composite Resources page]({{<ref "./composite-resources" >}}). 
{{< /hint >}}

Inside a Composition's 
{{<hover label="typeref" line="5">}}spec{{</hover>}}
define the Composite Resource 
{{<hover label="typeref" line="7">}}apiVersion{{</hover>}} and 
{{<hover label="typeref" line="8">}}kind{{</hover>}}
that the Composition allows to use this template.

```yaml {label="typeref",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: dynamodb-with-bucket
spec:
  compositeTypeRef:
    apiVersion: custom-api.example.org/v1alpha1
    kind: database
  # Removed for brevity
```

### Changing resource fields

Most Compositions require customizing the fields of the resources. This can
include applying unique passwords, modifying where to deploy resources,
or applying labels or annotations. 

The primary method to change resources is using a resource 
[patch and transform]({{<ref "./patch-and-transform" >}}). Patch and transforms 
allow matching specific input fields, modifying them and applying them to the 
managed resource. 

{{<hint "important" >}}
The details of creating patch and transforms and their options are in the 
[Patch and Transform page]({{<ref "./patch-and-transform" >}}).

This section describes applying patches and transforms to Compositions.
{{< /hint >}}

Apply patches to individual `resources` with the 
{{<hover label="patch" line="13">}}patches{{</hover>}}
field. 

For example, taking the 
{{<hover label="patchClaim" line="6">}}location{{</hover>}} provided in a Claim 
and applying it to the 
{{<hover label="patch" line="12">}}region{{</hover>}} value in the managed 
resource.

```yaml {copy-lines="none",label="patchClaim"}
apiVersion: example.org/v1alpha1
kind: ExampleClaim
metadata:
  name: my-example-claim
spec:
  location: "eu-north-1"
```

The Composition patch uses the 
{{<hover label="patch" line="15">}}fromFieldPath{{</hover>}} to match the 
{{<hover label="patchClaim" line="6">}}location{{</hover>}}
field in the Claim and the 
{{<hover label="patch" line="16">}}toFieldPath{{</hover>}} to define which field
to change inside the Composition. 

```yaml {copy-lines="none",label="patch"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
    - name: s3Bucket
      base:
        apiVersion: s3.aws.upbound.io/v1beta1
        kind: Bucket
        spec:
          forProvider:
            region: "us-east-2"
      patches:
      - type: FromCompositeFieldPath
        fromFieldPath: "spec.location"
        toFieldPath: "spec.forProvider.region"
```

#### Patch sets

Some Compositions have resources which need identical patches applied. Instead
of repeating the same `patches` field, resources can reference a single 
`patchSet`. 

Define a {{<hover label="patchset" line="5">}}patchSet{{</hover>}} with a 
{{<hover label="patchset" line="6">}}name{{</hover>}}
and 
{{<hover label="patchset" line="7">}}patch{{</hover>}}
operations. 

Then apply the 
{{<hover label="patchset" line="5">}}patchSet{{</hover>}}
to each resource with 
{{<hover label="patchset" line="16">}}type: patchSet{{< /hover >}}, referencing
the {{<hover label="patchset" line="6">}}name{{< /hover >}} in the 
{{<hover label="patchset" line="17">}}patchSetName{{< /hover >}} field.

```yaml {copy-lines="none",label="patchset"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  patchSets:
    - name: reusable-patch
      patches:
      - type: FromCompositeFieldPath
        fromFieldPath: "location"
        toFieldPath: "spec.forProvider.region"
  resources:
    - name: first-resource
      base:
      # Removed for Brevity
      patches:
        - type: PatchSet
          patchSetName: reusable-patch
    - name: second-resource
      base:
      # Removed for Brevity
      patches:
        - type: PatchSet
          patchSetName: reusable-patch
```

#### 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. 

{{<hint "important" >}}
EnvironmentConfigs are an alpha feature. Alpha features aren't enabled by
default. 
{{< /hint >}}

 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 "./environment-configs" >}}) page for 
more information on using EnvironmentConfigs.
{{< /hint >}}

To apply a patch using EnvironmentConfigs, first define which EnvironmentConfigs
to use with 
{{<hover label="envselect" line="6">}}environment.environmentConfigs{{</hover>}}. 

<!-- vale Google.Quotes = NO -->
<!-- vale gitlab.SentenceLength = NO -->
<!-- ignore false positive -->
Use either a
[reference]({{<ref "./managed-resources#matching-by-name-reference" >}})
or a [selector]({{<ref "./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
  resources:
  # Removed for Brevity
```

<!-- these two sections are duplicated in the environment-configs doc --> 

##### Patch a composite resource
To patch between the composite resource and the in-memory environment use
{{< hover label="xrpatch" line="7">}}patches{{</hover>}} inside of the 
{{< hover label="xrpatch" line="5">}}environment{{</hover>}}.

Use the 
{{< hover label="xrpatch" line="5">}}ToCompositeFieldPath{{</hover>}} to copy
data from the in-memory environment to the composite resource.  
Use the 
{{< hover label="xrpatch" line="5">}}FromCompositeFieldPath{{</hover>}} to copy
data from the composite resource to the in-memory environment.

```yaml {label="xrpatch",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  environment:
  # Removed for Brevity
      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 
{{<hover label="envpatch" line="16">}}patches{{</hover>}} of the 
resource, use 
{{<hover label="envpatch" line="17">}}ToEnvironmentFieldPath{{</hover>}} to copy
data from the resource to the in-memory environment.  
Use {{<hover label="envpatch" line="20">}}FromEnvironmentFieldPath{{</hover>}}
to copy data to the resource from the in-memory environment.

```yaml {label="envpatch",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  environment:
  # Removed for Brevity
  resources:
  # Removed for Brevity
    - name: vpc
      base:
        apiVersion: ec2.aws.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 "./environment-configs" >}}) page has 
more information on EnvironmentConfigs options and usage.

### Use composition functions

Composition functions (or just functions, for short) are custom programs that
template Crossplane resources. You can write a function to template resources
using a general purpose programming language like Go or Python. Using a general
purpose programming language allows a function to use more advanced logic to
template resources, like loops and conditionals.

{{<hint "important" >}}
Composition functions is a beta feature. Crossplane enables beta functions by
default. The
[Composition Functions]({{<ref "./composition-functions#disable-composition-functions">}})
page explains how to disable composition functions.
{{< /hint >}}

To use composition functions set the Composition 
{{<hover label="xfn" line="6">}}mode{{</hover>}} to
{{<hover label="xfn" line="6">}}Pipeline{{</hover>}}.

Define a {{<hover label="xfn" line="7">}}pipeline{{</hover>}} of 
{{<hover label="xfn" line="8">}}steps{{</hover>}}. Each 
{{<hover label="xfn" line="8">}}step{{</hover>}} calls a Function.  

Each {{<hover label="xfn" line="8">}}step{{</hover>}} uses a 
{{<hover label="xfn" line="9">}}functionRef{{</hover>}} to reference the
{{<hover label="xfn" line="10">}}name{{</hover>}} of the Function to call. 

Some Functions also allow you to specify an 
{{<hover label="xfn" line="11">}}input{{</hover>}}.  
The function defines the
{{<hover label="xfn" line="13">}}kind{{</hover>}} of input.

{{<hint "important" >}}
Compositions using {{<hover label="xfn" line="6">}}mode: Pipeline{{</hover>}} 
can't specify resource templates with a `resources` field. 

Use function "Patch and Transform" to create resource templates.
{{< /hint >}}

This example uses Function Patch and Transform. Function Patch and Transform is
a function that implements Crossplane resource templates. You can use Function
Patch and Transform to specify resource templates in a pipeline with other
Functions.

```yaml {label="xfn",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  # Removed for Brevity
  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.upbound.io/v1beta1
          kind: Bucket
          spec:
            forProvider:
              region: "us-east-2"
```

Read the [composition functions]({{<ref "./composition-functions">}}) page for
details on building and using composition functions.

### Storing connection details

Some managed resources generate unique details like usernames, passwords, 
IP addresses, ports or other connection details. 

When resources inside a Composition create connection details Crossplane creates
a Kubernetes secret object for each managed resource generating connection 
details. 

{{<hint "note">}}
This section discusses creating Kubernetes secrets.  
Crossplane also supports using external secret stores like [HashiCorp Vault](https://www.vaultproject.io/). 

Read the [external secrets store guide]({{<ref "../guides/vault-as-secret-store">}}) for more information on using Crossplane
with an external secret store. 
{{</hint >}}

#### Composite resource combined secret
Crossplane can combine all the secrets generated by the resources inside a
Composition into a single Kubernetes secret and optionally copy the
secret object for [Claims]({{<ref "./claims#claim-connection-secrets">}}). 

Set the value of 
{{<hover label="writeConn" line="5">}}writeConnectionSecretsToNamespace{{</hover>}}
to the namespace where Crossplane should store the combined secret object.

```yaml {copy-lines="none",label="writeConn"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  writeConnectionSecretsToNamespace: my-namespace
  resources:
  # Removed for brevity
```

#### Composed resource secrets
Inside the 
{{<hover label="writeConnRes" line="10">}}spec{{</hover>}} of 
each resource producing connection details, define the 
{{<hover label="writeConnRes" line="13">}}writeConnectionSecretToRef{{</hover>}}, with
a 
{{<hover label="writeConnRes" line="14">}}namespace{{</hover>}} and 
{{<hover label="writeConnRes" line="15">}}name{{</hover>}} of the secret object for
the resource.  

If a 
{{<hover label="writeConnRes" line="13">}}writeConnectionSecretToRef{{</hover>}}
isn't defined, Crossplane doesn't write any keys to the secret.


```yaml {label="writeConnRes"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  writeConnectionSecretsToNamespace: other-namespace
  resources:
    - name: key
      base:
        apiVersion: iam.aws.upbound.io/v1beta1
        kind: AccessKey
        spec:
          forProvider:
          # Removed for brevity
          writeConnectionSecretToRef:
            namespace: docs
            name: key1
```

Crossplane saves a secret with the 
{{<hover label="viewComposedSec" line="3">}}name{{</hover>}}
in the 
{{<hover label="writeConnRes" line="14">}}namespace{{</hover>}} provided.

```shell {label="viewComposedSec"}
kubectl get secrets -n docs
NAME   TYPE                                DATA   AGE
key1   connection.crossplane.io/v1alpha1   4      4m30s
```

{{<hint "tip" >}}

Crossplane recommends using a [Patch]({{<ref "./patch-and-transform">}}) to
create a unique name for each secret. 

For example, a 
{{<hover label="tipPatch" line="15">}}patch{{</hover>}}
to add the unique identifier of the resource as the key
name.

```yaml {label="tipPatch",copy-lines="14-20"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  # Removed for brevity
  resources:
    - name: key
      base:
        apiVersion: iam.aws.upbound.io/v1beta1
        kind: AccessKey
        spec:
        # Removed for brevity
          writeConnectionSecretToRef:
            namespace: docs
            name: key1
      patches:
        - fromFieldPath: "metadata.uid"
          toFieldPath: "spec.writeConnectionSecretToRef.name"
          transforms:
            - type: string
              string:
                fmt: "%s-secret"
```
{{< /hint >}}

#### Define secret keys


A Composition must define the specific secret keys a resource creates with 
the 
{{<hover label="conDeet" line="14">}}connectionDetails{{</hover>}} object.

{{<table "table table-sm" >}}
| Secret Type | Description | 
| --- | --- | 
| {{<hover label="conDeet" line="16">}}fromConnectionSecretKey{{</hover>}} | Create a secret key matching the key of a secret generated by the resource. | 
| {{<hover label="conDeet" line="18">}}fromFieldPath{{</hover>}}  | Create a secret key matching a field path of the resource. |
| {{<hover label="conDeet" line="20">}}value{{</hover>}}  | Create a secret key with a predefined value. |
{{< /table >}}

{{<hint "note">}}
The {{<hover label="conDeet" line="20">}}value{{</hover>}} type must use a
string value.  

The {{<hover label="conDeet" line="20">}}value{{</hover>}} isn't added to the
individual resource secret object. The 
{{<hover label="conDeet" line="20">}}value{{</hover>}} only appears in the 
combined composite resource secret.
{{< /hint >}}

```yaml {label="conDeet",copy-lines="none"}
kind: Composition
spec:
  writeConnectionSecretsToNamespace: other-namespace
  resources:
    - name: key
      base:
        # Removed for brevity
        spec:
          forProvider:
          # Removed for brevity
          writeConnectionSecretToRef:
            namespace: docs
            name: key1
      connectionDetails:
        - name: myUsername
          fromConnectionSecretKey: username
        - name: myFieldSecret
          fromFieldPath: spec.forProvider.user
        - name: myStaticSecret
          value: "docs.crossplane.io"
```

The
{{<hover label="conDeet" line="14">}}connectionDetails{{</hover>}} 
in a resource can reference a secret from a resource with
{{<hover label="conDeet" line="16">}}fromConnectionSecretKey{{</hover>}},  
from another field in the resource with
{{<hover label="conDeet" line="18">}}fromFieldPath{{</hover>}}  
or a statically defined value with 
{{<hover label="conDeet" line="20">}}value{{</hover>}}.

Crossplane sets the secret key to the 
{{<hover label="conDeet" line="15">}}name{{</hover>}} 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 {{<hover label="conDeet" line="15">}}name{{</hover>}} to create
unique secret keys.
{{< /hint >}}

{{<hint "important">}}
Crossplane only adds connection details listed in the 
{{<hover label="conDeet" line="16">}}connectionDetails{{</hover>}} 
to the combined secret object.  
Any connection secrets in a managed resource, not defined in the 
{{<hover label="conDeet" line="16">}}connectionDetails{{</hover>}} 
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.

Read the 
[CompositeResourceDefinition documentation]({{<ref "composite-resource-definitions#manage-connection-secrets">}}) 
for more information on restricting secret keys.
{{< /hint >}}

For more information on connection secrets read the 
[Connection Secrets knowledge base article]({{<ref "connection-details">}}).

{{<hint "warning">}}
You can't change the 
{{<hover label="conDeet" line="16">}}connectionDetails{{</hover>}} 
of a Composition.  
You must delete and
recreate the Composition to change the 
{{<hover label="conDeet" line="16">}}connectionDetails{{</hover>}} .
{{</hint >}}


#### Save connection details to an external secret store

Crossplane 
[External Secret Stores]({{<ref "../guides/vault-as-secret-store" >}}) 
write secrets and connection details to external secret stores like HashiCorp
Vault. 

{{<hint "important" >}}
External Secret Stores are an alpha feature.

They're not recommended for production use. Crossplane disables External Secret
Stores by default.
{{< /hint >}}

Use 
{{<hover label="gcp-storeconfig"
line="11">}}publishConnectionDetailsWithStoreConfigRef{{</hover>}}
in place of 
`writeConnectionSecretsToNamespace` to define the 
{{<hover label="gcp-storeconfig" line="2">}}StoreConfig{{</hover>}} 
to save connection details to. 

For example, using a 
{{<hover label="gcp-storeconfig" line="2">}}StoreConfig{{</hover>}} with the 
{{<hover label="gcp-storeconfig" line="4">}}name{{</hover>}} "vault," 
use 
{{<hover label="gcp-storeconfig" line="12">}}publishConnectionDetailsWithStoreConfigRef.name{{</hover>}}
matching the {{<hover label="gcp-storeconfig" line="4">}}StoreConfig.name{{</hover>}}, 
in this example, "vault."


```yaml {label="gcp-storeconfig",copy-lines="none"}
apiVersion: gcp.crossplane.io/v1alpha1
kind: StoreConfig
metadata:
  name: vault
# Removed for brevity.
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  publishConnectionDetailsWithStoreConfigRef: 
    name: vault
  resources:
  # Removed for brevity
```

For more details read the [External Secret Stores]({{<ref "../guides/vault-as-secret-store" >}}) 
integration guide.

### 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`.

{{< 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 
{{<hover label="check" line="10" >}}readinessChecks{{</hover>}} field on a 
resource.
<!-- vale Google.WordList = YES -->

Checks have a 
{{<hover label="check" line="11" >}}type{{</hover>}} defining how to match the
resource and a {{<hover label="check" line="12" >}}fieldPath{{</hover>}} of
which field in the resource to compare.

```yaml {label="check",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - 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

{{<hover label="matchstring" line="11">}}MatchString{{</hover>}} 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 
{{<hover label="matchstring" line="13">}}Online{{</hover>}}
in the resource's 
{{<hover label="matchstring" line="12">}}status.atProvider.state{{</hover>}}
field. 

```yaml {label="matchstring",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - name: my-resource
      base:
        # Removed for brevity
      readinessChecks:
        - type: MatchString
          fieldPath: status.atProvider.state
          matchString: "Online"
```

#### Match an integer

{{<hover label="matchint" line="11">}}MatchInteger{{</hover>}} 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
{{<hover label="matchint" line="13">}}4{{</hover>}}
in the resource's 
{{<hover label="matchint" line="12">}}status.atProvider.state{{</hover>}}
field. 

```yaml {label="matchint",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - name: my-resource
      base:
        # Removed for brevity
      readinessChecks:
        - type: MatchInteger
          fieldPath: status.atProvider.state
          matchInteger: 4
```

#### Match that a field exists
{{<hover label="NonEmpty" line="11">}}NonEmpty{{</hover>}} 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 
{{<hover label="NonEmpty" line="12">}}status.atProvider.state{{</hover>}}
field isn't empty. 
<!-- vale Google.WordList = YES -->

```yaml {label="NonEmpty",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - name: my-resource
      base:
        # Removed for brevity
      readinessChecks:
        - type: NonEmpty
          fieldPath: status.atProvider.state
```

{{<hint "tip" >}}
Checking {{<hover label="NonEmpty" line="11">}}NonEmpty{{</hover>}} doesn't
require setting any other fields.
{{< /hint >}} 

#### Always consider a resource ready
{{<hover label="none" line="11">}}None{{</hover>}} 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 
{{<hover label="none" line="7">}}my-resource{{</hover>}}
ready as soon as it's created.


```yaml {label="none",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - name: my-resource
      base:
        # Removed for brevity
      readinessChecks:
        - type: None
```

#### Match a condition
{{<hover label="condition" line="11">}}Condition{{</hover>}} 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 
{{<hover label="condition" line="7">}}my-resource{{</hover>}}, which is
ready if there is a condition of type 
{{<hover label="condition" line="13">}}MyType{{</hover>}} with a status of
{{<hover label="condition" line="14">}}Success{{</hover>}}.

```yaml {label="condition",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - 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 
{{<hover label="matchTrue" line="7">}}my-resource{{</hover>}}, which is
ready if 
{{<hover label="matchTrue" line="12">}} status.atProvider.manifest.status.ready{{</hover>}}
is {{<hover label="matchTrue" line="11">}}true{{</hover>}}.

```yaml {label="matchTrue",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - name: my-resource
      base:
        # Removed for brevity
      readinessChecks:
        - type: MatchTrue
          fieldPath: status.atProvider.manifest.status.ready
```
{{<hint "tip" >}}
Checking {{<hover label="matchTrue" line="11">}}MatchTrue{{</hover>}} doesn't
require setting any other fields.
{{< /hint >}} 

`MatchFalse` matches fields that express readiness with the value `false`.

For example, consider 
{{<hover label="matchFalse" line="7">}}my-resource{{</hover>}}, is
ready if 
{{<hover label="matchFalse" line="12">}} status.atProvider.manifest.status.pending{{</hover>}}
is {{<hover label="matchFalse" line="11">}}false{{</hover>}}.

```yaml {label="matchFalse",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
  resources:
  # Removed for Brevity
    - name: my-resource
      base:
        # Removed for brevity
      readinessChecks:
        - type: MatchFalse
          fieldPath: status.atProvider.manifest.status.pending
```

{{<hint "tip" >}}
Checking {{<hover label="matchFalse" line="11">}}MatchFalse{{</hover>}} doesn't
require setting any other fields.
{{< /hint >}} 

## Verify a Composition

View all available Compositions with `kubectl get composition`.

```shell {copy-lines="1"}
kubectl get composition
NAME                                       XR-KIND        XR-APIVERSION                         AGE
xapps.aws.platformref.upbound.io           XApp           aws.platformref.upbound.io/v1alpha1   123m
xclusters.aws.platformref.upbound.io       XCluster       aws.platformref.upbound.io/v1alpha1   123m
xeks.aws.platformref.upbound.io            XEKS           aws.platformref.upbound.io/v1alpha1   123m
xnetworks.aws.platformref.upbound.io       XNetwork       aws.platformref.upbound.io/v1alpha1   123m
xservices.aws.platformref.upbound.io       XServices      aws.platformref.upbound.io/v1alpha1   123m
xsqlinstances.aws.platformref.upbound.io   XSQLInstance   aws.platformref.upbound.io/v1alpha1   123m
```

The `XR-KIND` lists the Composite Resource `kind` that's allowed to use the
Composition template.  
The `XR-APIVERSION` lists the Composite Resource API versions allowed to use the
Composition template. 

{{<hint "note" >}}
The output of `kubectl get composition` is different than `kubectl get
composite`. 

`kubectl get composition` lists all available Compositions.

`kubectl get composite` lists all created Composite Resources and their related
Composition. 
{{< /hint >}}

## Composition validation

When creating a Composition, Crossplane automatically validates its integrity,
checking that the Composition is well formed, for example:

If using `mode: Resources`:

* The `resources` field isn't empty.
* All resources either use a `name` or don't. Compositions can't use both named
  and unnamed resources.
* No duplicate resource names.
* Patch sets must have names.
* Patches that require a `fromFieldPath` value provide it.
* Patches that require a `toFieldPath` value provide it.
* Patches that require a `combine` field provide it.
* Readiness checks using `matchString` aren't empty.
* Readiness checks using `matchInteger` isn't `0`.
* Readiness checks requiring a `fieldPath` value provide it.

If using `mode: Pipeline` (Composition Functions):

* The `pipeline` field isn't empty.
* No duplicate step names.

### Composition schema aware validation

Crossplane also performs schema aware
validation of Compositions. Schema validation checks that `patches`, 
`readinessChecks` and `connectionDetails` are valid according to the resource 
schemas. For example, checking that the source and destination fields of a patch 
are valid according to the source and destination resource schema.

{{<hint "note" >}}
Composition schema aware validation is a beta feature. Crossplane enables
beta features by default. 

Disable schema aware validation by setting the
`--enable-composition-webhook-schema-validation=false` flag on the Crossplane
pod.  

The [Crossplane Pods]({{<ref "./pods#edit-the-deployment">}}) page has
more information on enabling Crossplane flags.
{{< /hint >}}

#### Schema aware validation modes

Crossplane always rejects Compositions in case of integrity errors.

Set the schema aware validation mode to configure how Crossplane handles both
missing resource schemas and schema aware validation errors.

{{<hint "note" >}}
If a resource schema is missing, Crossplane skips schema aware validation
but still returns an error for integrity errors and a warning or an error
for the missing schemas.
{{< /hint >}}

The following modes are available:

{{< table "table table-sm table-striped" >}}
| Mode     | Missing Schema | Schema Aware Error | Integrity Error |
| -------- | -------------- |--------------------|-----------------|
| `warn`   | Warning        | Warning            | Error           |
| `loose`  | Warning        | Error              | Error           |
| `strict` | Error          | Error              | Error           |
{{< /table >}}

Change the validation mode for a Composition with the
{{<hover label="mode" line="5">}}crossplane.io/composition-schema-aware-validation-mode{{</hover>}} 
annotation.

If not specified, the default mode is `warn`.

For example, to enable `loose` mode checking set the annotation value to 
{{<hover label="mode" line="5">}}loose{{</hover>}}.

```yaml {copy-lines="none",label="mode"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  annotations:
    crossplane.io/composition-schema-aware-validation-mode: loose
  # Removed for brevity
spec:
  # Removed for brevity
```

{{<hint "important" >}}
Validation modes also apply to Compositions defined by Configuration packages.

Depending on the mode configured in the Composition, schema aware validation
issues may result in warnings or the rejection of the Composition.

View the Crossplane logs for validation warnings.

Crossplane sets a Configuration as unhealthy if there are validation errors.
View the Configuration details with `kubectl describe configuration` to see the
specific errors.
{{< /hint >}}
