Composition Revision Example

This tutorial discusses how CompositionRevisions work and how they manage Composite Resource (XR) updates. This starts with a Composition and CompositeResourceDefinition (XRD) that defines a MyVPC resource and continues with creating multiple XRs to observe different upgrade paths. Crossplane will assign different CompositionRevisions to the created composite resources each time the composition is updated.

Preparation

Install Crossplane

Install Crossplane v1.11.0 or later and wait until the Crossplane pods are running.

1kubectl create namespace crossplane-system
2helm repo add crossplane-master https://charts.crossplane.io/master/
3helm repo update
4helm install crossplane --namespace crossplane-system crossplane-master/crossplane --devel --version 1.11.0-rc.0.108.g0521c32e
5kubectl get pods -n crossplane-system

Expected Output:

1NAME                                       READY   STATUS    RESTARTS   AGE
2crossplane-7f75ddcc46-f4d2z                1/1     Running   0          9s
3crossplane-rbac-manager-78bd597746-sdv6w   1/1     Running   0          9s

Deploy Composition and XRD Examples

Apply the example Composition.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3metadata:
 4  labels:
 5    channel: dev
 6  name: myvpcs.aws.example.upbound.io
 7spec:
 8  writeConnectionSecretsToNamespace: crossplane-system
 9  compositeTypeRef:
10    apiVersion: aws.example.upbound.io/v1alpha1
11    kind: MyVPC
12  resources:
13  - base:
14      apiVersion: ec2.aws.upbound.io/v1beta1
15      kind: VPC
16      spec:
17        forProvider:
18          region: us-west-1
19          cidrBlock: 192.168.0.0/16
20          enableDnsSupport: true
21          enableDnsHostnames: true
22    name: my-vcp

Apply the example XRD.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: myvpcs.aws.example.upbound.io
 5spec:
 6  group: aws.example.upbound.io
 7  names:
 8    kind: MyVPC
 9    plural: myvpcs
10  versions:
11  - name: v1alpha1
12    served: true 
13    referenceable: true 
14    schema:
15      openAPIV3Schema:
16        type: object 
17        properties:
18          spec:
19            type: object 
20            properties:
21              id:
22                type: string 
23                description: ID of this VPC that other objects will use to refer to it. 
24            required:
25            - id

Verify that Crossplane created the Composition revision

1kubectl get compositionrevisions -o="custom-columns=NAME:.metadata.name,REVISION:.spec.revision,CHANNEL:.metadata.labels.channel"

Expected Output:

1NAME                                    REVISION   CHANNEL
2myvpcs.aws.example.upbound.io-ad265bc   1          dev
Note
The label dev is automatically created from the Composition.

Create Composite Resources

This tutorial has four composite resources to cover different update policies and composition selection options. The default behavior is updating XRs to the latest revision of the Composition. However, this can be changed by setting compositionUpdatePolicy: Manual in the XR. It is also possible to select the latest revision with a specific label with compositionRevisionSelector.matchLabels together with compositionUpdatePolicy: Automatic.

Default update policy

Create an XR without a compositionUpdatePolicy defined. The update policy is Automatic by default:

1apiVersion: aws.example.upbound.io/v1alpha1
2kind: MyVPC
3metadata:
4  name: vpc-auto
5spec:
6  id: vpc-auto

Expected Output:

1myvpc.aws.example.upbound.io/vpc-auto created

Manual update policy

Create a Composite Resource with compositionUpdatePolicy: Manual and compositionRevisionRef.

1apiVersion: aws.example.upbound.io/v1alpha1
2kind: MyVPC
3metadata:
4  name: vpc-man
5spec:
6  id: vpc-man
7  compositionUpdatePolicy: Manual
8  compositionRevisionRef:
9    name: myvpcs.aws.example.upbound.io-ad265bc

Expected Output:

1myvpc.aws.example.upbound.io/vpc-man created

Using a selector

Create an XR with a compositionRevisionSelector of channel: dev:

1apiVersion: aws.example.upbound.io/v1alpha1
2kind:  MyVPC
3metadata:
4  name: vpc-dev
5spec:
6  id: vpc-dev
7  compositionRevisionSelector:
8    matchLabels:
9      channel: dev

Expected Output:

1myvpc.aws.example.upbound.io/vpc-dev created

Create an XR with a compositionRevisionSelector of channel: staging:

1apiVersion: aws.example.upbound.io/v1alpha1
2kind: MyVPC
3metadata:
4  name: vpc-staging
5spec:
6  id: vpc-staging
7  compositionRevisionSelector:
8    matchLabels:
9      channel: staging

Expected Output:

1myvpc.aws.example.upbound.io/vpc-staging created

Verify the Composite Resource with the label channel: staging doesn’t have a REVISION.
All other XRs have a REVISION matching the created Composition Revision.

1kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.compositionRevisionRef.name,POLICY:.spec.compositionUpdatePolicy,MATCHLABEL:.spec.compositionRevisionSelector.matchLabels"

Expected Output:

1NAME          SYNCED   REVISION                                POLICY      MATCHLABEL
2vpc-auto      True     myvpcs.aws.example.upbound.io-ad265bc   Automatic   <none>
3vpc-dev       True     myvpcs.aws.example.upbound.io-ad265bc   Automatic   map[channel:dev]
4vpc-man       True     myvpcs.aws.example.upbound.io-ad265bc   Manual      <none>
5vpc-staging   False    <none>                                  Automatic   map[channel:staging]
Note
The vpc-staging XR label doesn’t match any existing Composition Revisions.

Create new Composition revisions

Crossplane creates a new CompositionRevision when a Composition is created or updated. Label and annotation changes will also trigger a new CompositionRevision.

Update the Composition label

Update the Composition label to channel: staging:

1kubectl label composition myvpcs.aws.example.upbound.io channel=staging --overwrite

Expected Output:

1composition.apiextensions.crossplane.io/myvpcs.aws.example.upbound.io labeled

Verify that Crossplane creates a new Composition revision:

1kubectl get compositionrevisions -o="custom-columns=NAME:.metadata.name,REVISION:.spec.revision,CHANNEL:.metadata.labels.channel"

Expected Output:

1NAME                                    REVISION   CHANNEL
2myvpcs.aws.example.upbound.io-727b3c8   2          staging
3myvpcs.aws.example.upbound.io-ad265bc   1          dev

Verify that Crossplane assigns the Composite Resources vpc-auto and vpc-staging to Composite revision:2.
XRs vpc-man and vpc-dev are still assigned to the original revision:1:

1kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.compositionRevisionRef.name,POLICY:.spec.compositionUpdatePolicy,MATCHLABEL:.spec.compositionRevisionSelector.matchLabels"

Expected Output:

1NAME          SYNCED   REVISION                                POLICY      MATCHLABEL
2vpc-auto      True     myvpcs.aws.example.upbound.io-727b3c8   Automatic   <none>
3vpc-dev       True     myvpcs.aws.example.upbound.io-ad265bc   Automatic   map[channel:dev]
4vpc-man       True     myvpcs.aws.example.upbound.io-ad265bc   Manual      <none>
5vpc-staging   True     myvpcs.aws.example.upbound.io-727b3c8   Automatic   map[channel:staging]
Note
vpc-auto always use the latest Revision.
vpc-staging now matches the label applied to Revision revision:2.

Update Composition Spec and Label

Update the Composition to disable DNS support in the VPC and change the label from staging back to dev.

Apply the following changes to update the Composition spec and label:

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3metadata:
 4  labels:
 5    channel: dev
 6  name: myvpcs.aws.example.upbound.io
 7spec:
 8  writeConnectionSecretsToNamespace: crossplane-system
 9  compositeTypeRef:
10    apiVersion: aws.example.upbound.io/v1alpha1
11    kind: MyVPC
12  resources:
13  - base:
14      apiVersion: ec2.aws.upbound.io/v1beta1
15      kind: VPC
16      spec:
17        forProvider:
18          region: us-west-1
19          cidrBlock: 192.168.0.0/16
20          enableDnsSupport: false
21          enableDnsHostnames: true
22    name: my-vcp

Expected Output:

1composition.apiextensions.crossplane.io/myvpcs.aws.example.upbound.io configured

Verify that Crossplane creates a new Composition revision:

1kubectl get compositionrevisions -o="custom-columns=NAME:.metadata.name,REVISION:.spec.revision,CHANNEL:.metadata.labels.channel"

Expected Output:

1NAME                                    REVISION   CHANNEL
2myvpcs.aws.example.upbound.io-727b3c8   2          staging
3myvpcs.aws.example.upbound.io-ad265bc   1          dev
4myvpcs.aws.example.upbound.io-f81c553   3          dev
Note
Changing the label and the spec values simultaneously is critical for deploying new changes to the dev channel.

Verify Crossplane assigns the Composite Resources vpc-auto and vpc-dev to Composite revision:3.
vpc-staging is assigned to revision:2, and vpc-man is still assigned to the original revision:1:

1kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.compositionRevisionRef.name,POLICY:.spec.compositionUpdatePolicy,MATCHLABEL:.spec.compositionRevisionSelector.matchLabels"

Expected Output:

1NAME          SYNCED   REVISION                                POLICY      MATCHLABEL
2vpc-auto      True     myvpcs.aws.example.upbound.io-f81c553   Automatic   <none>
3vpc-dev       True     myvpcs.aws.example.upbound.io-f81c553   Automatic   map[channel:dev]
4vpc-man       True     myvpcs.aws.example.upbound.io-ad265bc   Manual      <none>
5vpc-staging   True     myvpcs.aws.example.upbound.io-727b3c8   Automatic   map[channel:staging]
Note
vpc-dev matches the updated label applied to Revision revision:3. vpc-staging matches the label applied to Revision revision:2.