Usages

This is an alpha feature. Crossplane may change or drop this feature at any time.

This feature was introduced in v1.14.

For more information read the Crossplane feature lifecycle.

A Usage is a Crossplane resource that defines a usage relationship for a Managed Resource or a Composite Resource. Two main use cases for the Usages are as follows:

  1. Protecting a resource from accidental deletion.
  2. Deletion ordering by ensuring that a resource isn’t deleted before the deletion of its dependent resources.

See the section Usage for Deletion Protection for the first use case and the section Usage for Deletion Ordering for the second one.

Enable usages

Usages are an alpha feature. Alpha features aren’t enabled by default.

Enable Usage support by changing the Crossplane pod setting and enabling
--enable-usages argument.

 1$ kubectl edit deployment crossplane --namespace crossplane-system
 2apiVersion: apps/v1
 3kind: Deployment
 4spec:
 5# Removed for brevity
 6  template:
 7    spec:
 8      containers:
 9      - args:
10        - core
11        - start
12        - --enable-usages
Tip
The Crossplane install guide describes enabling feature flags like --enable-usages with Helm.

Create a usage

A Usage spec has a mandatory of field for defining the resource in use or protected. The reason field defines the reason for protection and the by field defines the using resource. Both fields are optional, but at least one of them must be provided.

Important

Usage relationships can be defined between Managed Resources and Composites.

However, a Composite as the using resource (spec.by) would be ineffective unless the compositeDeletePolicy Foreground is used because it wouldn’t block deletion of its child resources before its own deletion with the default deletion policy Background.

Usage for deletion protection

The following example prevents the deletion of the my-database resource by rejecting any deletion request with the reason defined.

 1apiVersion: apiextensions.crossplane.io/v1alpha1
 2kind: Usage
 3metadata:
 4  name: protect-production-database
 5spec:
 6  of:
 7    apiVersion: rds.aws.upbound.io/v1beta1
 8    kind: Instance
 9    resourceRef:
10      name: my-database
11  reason: "Production Database - should never be deleted!"

Usage for deletion ordering

The following example prevents the deletion of my-cluster resource by rejecting any deletion request before the deletion of my-prometheus-chart resource.

 1apiVersion: apiextensions.crossplane.io/v1alpha1
 2kind: Usage
 3metadata:
 4  name: release-uses-cluster
 5spec:
 6  of:
 7    apiVersion: eks.upbound.io/v1beta1
 8    kind: Cluster
 9    resourceRef:
10      name: my-cluster
11  by:
12    apiVersion: helm.crossplane.io/v1beta1
13    kind: Release
14    resourceRef:
15      name: my-prometheus-chart

Using selectors with usages

Usages can use selectors to define the resource in use or the using one. This enables using labels or matching controller references to define resource instead of providing the resource name.

 1apiVersion: apiextensions.crossplane.io/v1alpha1
 2kind: Usage
 3metadata:
 4  name: release-uses-cluster
 5spec:
 6  of:
 7    apiVersion: eks.upbound.io/v1beta1
 8    kind: Cluster
 9    resourceSelector:
10      matchControllerRef: false # default, and could be omitted
11      matchLabels:
12        foo: bar
13  by:
14    apiVersion: helm.crossplane.io/v1beta1
15    kind: Release
16    resourceSelector:
17       matchLabels:
18          baz: qux

After the Usage controller resolves the selectors, it persists the resource name in the resourceRef.name field. The following example shows the Usage resource after the resolution of selectors.

Important

The selectors are resolved only once. If there are more than one matches, a random resource is selected from the list of matched resources.

 1apiVersion: apiextensions.crossplane.io/v1alpha1
 2kind: Usage
 3metadata:
 4  name: release-uses-cluster
 5spec:
 6  of:
 7    apiVersion: eks.upbound.io/v1beta1
 8    kind: Cluster
 9    resourceRef:
10       name: my-cluster
11    resourceSelector:
12      matchLabels:
13        foo: bar
14  by:
15    apiVersion: helm.crossplane.io/v1beta1
16    kind: Release
17    resourceRef:
18       name: my-cluster
19    resourceSelector:
20       matchLabels:
21          baz: qux

Replay blocked deletion attempt

By default, the deletion of a Usage resource doesn’t trigger the deletion of the resource in use even if there were deletion attempts blocked by the Usage. Replaying the blocked deletion is possible by setting the replayDeletion field to true.

 1apiVersion: apiextensions.crossplane.io/v1alpha1
 2kind: Usage
 3metadata:
 4  name: release-uses-cluster
 5spec:
 6  replayDeletion: true
 7  of:
 8    apiVersion: eks.upbound.io/v1beta1
 9    kind: Cluster
10    resourceRef:
11      name: my-cluster
12  by:
13    apiVersion: helm.crossplane.io/v1beta1
14    kind: Release
15    resourceRef:
16      name: my-prometheus-chart
Tip
Replay deletion is useful when the used resource is part of a composition. This configuration radically decreases time for the deletion of the used resource, hence the composite owning it, by replaying the deletion of the used resource right after the using resource disappears instead of waiting for the long exponential backoff durations of the Kubernetes garbage collector.

Usage in a Composition

A typical use case for Usages is to define a deletion ordering between the resources in a Composition. The Usages support matching controller reference in selectors to ensures that the matching resource is in the same composite resource in the same way as cross-resource referencing.

The following example shows a Composition that defines a deletion ordering between a Cluster and a Release resource. The Usage blocks deletion of the Cluster resource until the Release resource is successfully deleted.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3spec:
 4  resources:
 5    - name: cluster
 6      base:
 7        apiVersion: container.gcp.upbound.io/v1beta1
 8        kind: Cluster
 9        # Removed for brevity
10    - name: release
11      base:
12        apiVersion: helm.crossplane.io/v1beta1
13        kind: Release
14        # Removed for brevity
15    - name: release-uses-cluster
16      base:
17        apiVersion: apiextensions.crossplane.io/v1alpha1
18        kind: Usage
19        spec:
20          replayDeletion: true
21          of:
22            apiVersion: container.gcp.upbound.io/v1beta1
23            kind: Cluster
24            resourceSelector:
25              matchControllerRef: true
26          by:
27            apiVersion: helm.crossplane.io/v1beta1
28            kind: Release
29            resourceSelector:
30              matchControllerRef: true
Tip

When there are multiple resources of same type in a Composition, the Usage resource must uniquely identify the resource in use or the using one. This could be accomplished by using extra labels and combining matchControllerRef with a matchLabels selector. Another alternative is patching resourceRef.name directly with the help of ToCompositeFieldPath and FromCompositeFieldPath or ToEnvironmentFieldPath and FromEnvironmentFieldPath type patches.