Crossplane Composition Functions in CUE let you define complex cloud infrastructure declaratively, but the real magic is how CUE’s constraint-based language lets you build self-healing, self-validating infrastructure blueprints.

Let’s see this in action. Imagine we want to provision a PostgreSQL instance on AWS RDS using Crossplane. We’ll define a CompositeResourceDefinition (XRD) for our desired PostgreSQL, and then a Composition that uses a CUE function to translate this into actual AWS RDS resources.

First, our XRD:

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresqlinstances.database.example.com
spec:
  group: database.example.com
  names:
    kind: XPostgreSQLInstance
    plural: xpostgresqlinstances
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  properties:
                    storageGB:
                      type: integer
                      default: 20
                    class:
                      type: string
                      default: "db.t3.micro"
                    dbName:
                      type: string
              required:
                - parameters

This defines a XPostgreSQLInstance custom resource that users can create, specifying storageGB, class, and dbName.

Now, the Composition. This is where CUE shines. We’ll create a Composition that references a CUE package.

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: postgresql-rds.database.example.com
  labels:
    provider: aws
spec:
  compositeTypeRef:
    apiVersion: database.example.com/v1alpha1
    kind: XPostgreSQLInstance
  pull:
    # This is a placeholder for a real OCI image containing our CUE function
    image: xpkg.upbound.io/crossplane/function-cue:v0.1.0
  patchSets:
    - name: common-labels
      patches:
        - fromFieldPath: metadata.labels
          toFieldPath: metadata.labels

The pull.image field points to a Docker image containing our CUE composition logic. Crossplane will pull this image and run it.

Inside that CUE image, we’d have a cue.mod/module.cue file like this:

package main

import (
	"crossplane.io/crossplane/apis/apiextensions/v1"
	"crossplane.io/crossplane/apis/apiextensions/v1beta1"
	rds "github.com/crossplane/provider-aws/apis/rds/v1beta1"
	"github.com/crossplane/provider-aws/apis/ec2/v1beta1"
	"github.com/crossplane/crossplane-runtime/apis/common/v1"
)

// This defines the desired state for our PostgreSQL instance.
// It maps directly to the XPostgreSQLInstance XRD.
#XPostgreSQLInstance: {
	apiVersion: "database.example.com/v1alpha1"
	kind:       "XPostgreSQLInstance"
	spec: {
		parameters: {
			storageGB: int
			class:     string
			dbName:    string
		}
	}
}

// This is the core of the composition. It takes the desired state
// and translates it into actual Crossplane resources.
#PostgreSQLRDS: {
	// This is the RDSInstance resource we want to create.
	rds.DBInstance: {
		metadata: {
			name:     "#XPostgreSQLInstance.spec.parameters.dbName"
			// We can inject labels from the composite resource.
			labels: "common-labels"
		}
		spec: {
			forProvider: {
				region: "us-east-1" // Hardcoded for simplicity, could be a parameter
				dbInstanceClass: "#XPostgreSQLInstance.spec.parameters.class"
				allocatedStorage: "#XPostgreSQLInstance.spec.parameters.storageGB"
				engine: "postgres"
				engineVersion: "13.7" // Specific version
				dbSubnetGroupName: "my-db-subnet-group" // Assumed to exist
				vpcSecurityGroupIDS: ["sg-0123456789abcdef0"] // Assumed to exist
				skipFinalSnapshot: true
			}
			writeConnectionSecretToRef: {
				name: "#XPostgreSQLInstance.spec.parameters.dbName" + "-connection"
				namespace: "default" // Or derived from the composite
			}
		}
	}

	// We also need a DBSubnetGroup if it doesn't exist.
	// In a real-world scenario, you'd likely manage this separately or
	// have a more complex logic to ensure its existence.
	// For this example, we'll assume it exists and just reference it.
	// If you wanted to manage it, you'd add something like:
	/*
	rds.DBSubnetGroup: {
		metadata: {
			name: "my-db-subnet-group"
		}
		spec: {
			forProvider: {
				region: "us-east-1"
				subnetIDs: ["subnet-0123456789abcdef0", "subnet-fedcba9876543210"]
			}
		}
	}
	*/
}

// This defines how the CUE function maps the composite resource to managed resources.
// The 'output' field specifies the list of managed resources to be created or updated.
#Output: {
	output: {
		apiVersion: "apiextensions.crossplane.io/v1"
		kind:       "Composition"
		resources: [
			#PostgreSQLRDS.rds.DBInstance,
			// If we were managing the DBSubnetGroup:
			// #PostgreSQLRDS.rds.DBSubnetGroup,
		]
	}
}

When a user creates an XPostgreSQLInstance like this:

apiVersion: database.example.com/v1alpha1
kind: XPostgreSQLInstance
metadata:
  name: my-pg-instance
spec:
  parameters:
    storageGB: 50
    class: "db.t3.medium"
    dbName: "myappdb"

Crossplane’s CUE function will execute. It takes the XPostgreSQLInstance as input, uses the CUE logic to generate the rds.DBInstance and potentially other AWS resources, and returns them. Crossplane then reconciles these generated resources against AWS.

The most surprising thing about CUE for infrastructure is that it’s not just a templating language; it’s a constraint language. You define what must be true, and CUE figures out how to satisfy those constraints, automatically filling in defaults and validating against schemas. This means your infrastructure definitions are not only declarative but also inherently validated and self-correcting within the bounds of your CUE constraints.

The #XPostgreSQLInstance.spec.parameters.dbName syntax in CUE is a powerful way to directly reference values from the input composite resource. CUE’s "dot notation" with # allows you to traverse and extract specific fields from your input schemas, making the mapping between your abstract composite resource and concrete managed resources incredibly direct and type-safe.

This allows you to build complex, reusable infrastructure components where the CUE function acts as a sophisticated translator, ensuring that the generated resources always conform to your defined policies and best practices. The patchSets in the Composition can also be referenced within CUE, providing a way to inject common configurations like labels or annotations without repeating them in every CUE definition.

The next frontier is managing dependencies and ensuring state consistency across multiple managed resources within a single composition, especially when those resources might be managed by different providers.

Want structured learning?

Take the full Crossplane course →