--- 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. {{}} Crossplane has four core components that users commonly mix up: * Compositions - This page. A template to define how to create resources. * [Composite Resource Definition]({{}}) (`XRD`) - A custom API specification. * [Composite Resource]({{}}) (`XR`) - Created by using the custom API defined in a Composite Resource Definition. XRs use the Composition template to create new managed resources. * [Claims]({{}}) (`XRC`) - Like a Composite Resource, but with namespace scoping. {{}} ## 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. 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](#composition-functions) to allow custom programs to run alongside the Composition. * Creating a [custom check of when a resource is ready](#resource-readiness-checks) to use. ### Resource templates The {{}}resources{{}} field of a Composition's {{}}spec{{}} defines the set of things that a Composite Resource creates. {{}} Read more about Composite Resources in the [Composite Resources page]({{}}). {{< /hint >}} For example, a Composition can define a template to create a virtual machine and an associated storage bucket at the same time. The {{}}resources{{}} field lists the individual resources with a {{}}name{{}}. This name identifies the resource inside the Composition and isn't related to the external name used with the Provider. #### Template a managed resource The contents of the {{}}base{{}} are identical to creating a standalone [managed resource]({{}}). This example uses [Upbound's Provider AWS](https://marketplace.upbound.io/providers/upbound/provider-aws/v0.35.0) 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: 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]({{}}) uses this Composition template, 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`. {{}} Compositions allow applying a `metadata.name` to a resource's {{}}spec{{}} 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 {{}}VPC{{}}, {{}}InternetGateway{{}} and {{}}Subnet{{}}. ```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 {{}}compositeTypeRef{{}} gives this Composition an {{}}apiVersion{{}} and {{}}kind{{}} to reference in another Composition. {{}} The [Enabling a Composite Resource](#enabling-composite-resources) section describes the {{}}compositeTypeRef{{}} field. {{< /hint >}} A second Composition, defining other resources, in this example, an AWS Elastic Kubernetes Cluster, can reference the previous {{}}XNetwork{{}} ```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 {{}}XNetwork{{}} get created along with the EKS {{}}cluster{{}}. {{}} 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/package/cluster/composition.yaml). {{}} #### 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_. {{}} 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 {{}}label{{}} to the resource to match and use {{}}matchLabels{{}} in the second resource. This example creates a AWS {{}}Role{{}} and applies a {{}}label{{}}. The second resource is a {{}}RolePolicyAttachment{{}}, which requires attaching to an existing `Role`. Using the resource's {{}}roleSelector.matchLabels{{}} ensures this {{}}RolePolicyAttachment{{}} references the matching {{}}Role{{}}, 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 {{}}InternetGateway{{}} requires a {{}}VPC{{}}. The {{}}InternetGateway{{}} could match a label, but every VPC created by this Composition share the same label. Using {{}}matchControllerRef{{}} matches only the VPC created in the same composite resource that created the {{}}InternetGateway{{}}. ```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 {{}}VPC{{}} resources, but the {{}}InternetGateway{{}} must match only one. Applying a {{}}label{{}} to the second {{}}VPC{{}} allows the {{}}InternetGateway{{}} to match the label {{}}type: internet{{}} and only match objects in the same composite resource with {{}}matchControllerRef{{}}. ```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 {{}}compositeTypeRef{{}} defines which Composite Resource type can use this Composition. {{}} Read more about Composite Resources in the [Composite Resources page]({{}}). {{< /hint >}} Inside a Composition's {{}}spec{{}} define the Composite Resource {{}}apiVersion{{}} and {{}}kind{{}} 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]({{}}). Patch and transforms allow matching specific input fields, modifying them and applying them to the managed resource. {{}} The details of creating patch and transforms and their options are in the [Patch and Transform page]({{}}). This section describes applying patches and transforms to Compositions. {{< /hint >}} Apply patches to individual `resources` with the {{}}patches{{}} field. For example, taking the {{}}location{{}} provided in a Claim and applying it to the {{}}region{{}} 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 {{}}fromFieldPath{{}} to match the {{}}location{{}} field in the Claim and the {{}}toFieldPath{{}} 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 {{}}patchSet{{}} with a {{}}name{{}} and {{}}patch{{}} operations. Then apply the {{}}patchSet{{}} to each resource with {{}}type: patchSet{{< /hover >}}, referencing the {{}}name{{< /hover >}} in the {{}}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 as an in-memory data store. Compositions can read and write from this data store as part of the patch process. {{}} 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 the EnvironmentConfig for other resources to read. {{< hint "note" >}} Read the [EnvironmentConfigs]({{}}) page for more information on using EnvironmentConfigs. {{< /hint >}} To apply a patch using EnvironmentConfigs, first define which EnvironmentConfig to use with {{}}environment.environmentConfigs{{}}. Use either a [reference]({{}}) or a [selector]({{}}) to identify the EnvironmentConfig to use. ```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 ``` Inside the {{}}patches{{}} of the resource, use {{}}ToEnvironmentFieldPath{{}} to copy data from the resource to the EnvironmentConfig. Use {{}}FromEnvironmentFieldPath{{}} to copy data to the resource from the EnvironmentConfig. ```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]({{}}) page has more information on EnvironmentConfigs options and usage. ### Composition functions Composition functions (`XFNs`) are containers executing any code you define. Composition functions can read and write to any resource in the Composition they're attached to. This allows composition functions to perform complex operations to patch fields, determine if a resource is ready for use or notify an external system about the details of resource. {{}} Composition functions are an alpha feature. Alpha features aren't enabled by default. {{< /hint >}} To attach a composition function to a Composition define a {{}}function{{}} inside the Composition {{}}spec{{}}. Provide a {{}}name{{}} for the function. The {{}}type{{}} is always `Container`. The {{}}container.image{{}} is the location of the composition function container image. ```yaml {label="xfn",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition # Removed for Brevity spec: resources: # Removed for Brevity functions: - name: rds-instance-password type: Container container: image: xpkg.upbound.io/provider-aws-xfns/random-rds-password:v0.1.0 ``` Read the [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. {{}} 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]({{}}) for more information on using Crossplane with an external secret store. {{}} #### 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]({{}}). Set the value of {{}}writeConnectionSecretsToNamespace{{}} 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 {{}}spec{{}} of each resource producing connection details, define the {{}}writeConnectionSecretToRef{{}}, with a {{}}namespace{{}} and {{}}name{{}} of the secret object for the resource. If a {{}}writeConnectionSecretToRef{{}} 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 {{}}name{{}} in the {{}}namespace{{}} provided. ```shell {label="viewComposedSec"} kubectl get secrets -n docs NAME TYPE DATA AGE key1 connection.crossplane.io/v1alpha1 4 4m30s ``` {{}} Crossplane recommends using a [Patch]({{}}) to create a unique name for each secret. For example, a {{}}patch{{}} 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 {{}}connectionDetails{{}} object. {{}} | Secret Type | Description | | --- | --- | | {{}}fromConnectionSecretKey{{}} | Create a secret key matching the key of a secret generated by the resource. | | {{}}fromFieldPath{{}} | Create a secret key matching a field path of the resource. | | {{}}value{{}} | Create a secret key with a predefined value. | {{< /table >}} {{}} 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: 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 {{}}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 {{}}value{{}}. Crossplane sets the secret key to the {{}}name{{}} value. Describe the secret to view the secret keys inside the secret object. {{}} If more than one resource generates secrets with the same secret key name, Crossplane only saves one value. Use a custom {{}}name{{}} to create unique secret keys. {{< /hint >}} {{}} 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: Annotations: Type: connection.crossplane.io/v1alpha1 Data ==== myUsername: 20 bytes myFieldSecret: 24 bytes myStaticSecret: 18 bytes ``` {{}} The CompositeResourceDefinition can also limit which keys Crossplane stores from the composite resources. By default an XRD writes all secret keys listed in the composed resources `connectionDetails` to the combined secret object. Read the [CompositeResourceDefinition documentation]({{}}) for more information on restricting secret keys. {{< /hint >}} For more information on connection secrets read the [Connection Secrets knowledge base article]({{}}). {{}} You can't change the {{}}connectionDetails{{}} of a Composition. You must delete and recreate the Composition to change the {{}}connectionDetails{{}} . {{}} #### Save connection details to an external secret store Crossplane [External Secret Stores]({{}}) write secrets and connection details to external secret stores like HashiCorp Vault. {{}} External Secret Stores are an alpha feature. They're not recommended for production use. Crossplane disables External Secret Stores by default. {{< /hint >}} Use {{}}publishConnectionDetailsWithStoreConfigRef{{}} in place of `writeConnectionSecretsToNamespace` to define the {{}}StoreConfig{{}} to save connection details to. For example, using a {{}}StoreConfig{{}} with the {{}}name{{}} "vault," use {{}}publishConnectionDetailsWithStoreConfigRef.name{{}} matching the {{}}StoreConfig.name{{}}, 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]({{}}) 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 >}} Define a custom readiness check with the {{}}readinessChecks{{}} field on a resource. Checks have a {{}}type{{}} defining how to match the resource and a {{}}fieldPath{{}} of which field in the resource to compare. ```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: fieldPath: ``` 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) #### Match a string {{}}MatchString{{}} considers the composed resource to be ready when the value of a field within that resource matches a specified string. {{}} Crossplane only supports exact string matches. Substrings and regular expressions aren't supported in a readiness check. {{}} For example, matching the string {{}}Online{{}} in the resource's {{}}status.atProvider.state{{}} field. ```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 {{}}MatchInteger{{}} considers the composed resource to be ready when the value of a field within that resource matches a specified integer. {{}} Crossplane doesn't support matching `0`. {{}} For example, matching the number {{}}4{{}} in the resource's {{}}status.atProvider.state{{}} field. ```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 {{}}NonEmpty{{}} considers the composed resource to be ready when a field exists with a value. {{}} Crossplane considers a value of `0` or an empty string as empty. {{}} For example, to check that a resource's {{}}status.atProvider.state{{}} field isn't empty. ```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 ``` {{}} Checking {{}}NonEmpty{{}} doesn't require a `match` field. {{< /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: apiextensions.crossplane.io/v1 kind: Composition # Removed for Brevity spec: resources: # Removed for Brevity - name: my-resource base: # Removed for brevity readinessChecks: - type: None ``` ## 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. {{}} 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 specific parameters in the Composition. * 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 composition functions, all resources must have names. * Composition function container field isn't empty. * Composition function `type` is `container`. * Composition function names are unique. ### Resource schema validation Optionally, Crossplane can also validate the schema of the resources defined inside a Composition. This verifies that the resource `apiVersion` and `kinds` are valid. Enable "schema validation" with the `--enable-composition-webhook-schema-validation` flag on the Crossplane pod. The [Crossplane Pods]({{}}) page has more information on enabling Crossplane flags. {{}} Schema validation only checks the `apiVersion` and `kind` are valid. Schema validation doesn't validate the fields of a specific resource. {{< /hint >}} The default validations are still checked with schema validation enabled. #### Validation modes Schema validation supports two modes: * `loose` (default) - Sends an warning for each schema error and installs the Composition if the default validations pass. * `strict` - Send an error for every schema validation error and rejects the Composition. Change the validation mode for a Composition with the {{}}crossplane.io/composition-validation-mode{{}} annotation. For example, to enable `strict` mode checking: ```yaml {copy-lines="none",label="mode"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: annotations: crossplane.io/composition-validation-mode: strict # Removed for brevity spec: # Removed for brevity ```