Your control plane relies on an API to communicate with your external resources. You can create an API with a Composite Resource Definition (XRD). XRDs are API schemas that define the structure of your desired resources. You provide the fields and acceptable values and your control plane can communicate with your external systems based on that structure.
Generate an XRD from a XRC
Instead of creating an XRD from scratch, you can create an XRD that’s based on a
Claim (XRC). Claims are the primary interface through which users provision
resources. Claims define the minimal input parameters required from users, which
the up
CLI then interprets to generate a comprehensive resource
configuration schema.
Generate an example claim
In the root folder of your control plane project, run the up example generate command.
up example generate
What do you want to create?:
> Composite Resource Claim (XRC)
What is your Composite Resource Claim (XRC) named?: Bucket
What is the API group named?: platform.upbound.io
What is the API Version named?: v1alpha1
What is the metadata name?: example
What is the metadata namespace?: default
Successfully created resource and saved to examples/bucket/example.yaml
After following the interactive steps, you should have an empty claim generated
under examples/bucket/example.yaml
. Next, open the claim file you generated,
and paste in the content below.
apiVersion: platform.upbound.io/v1alpha1
kind: Bucket
metadata:
name: example
namespace: default
spec:
parameters:
versioning: true
encrypted: true
visibility: public
Claims contain configuration parameters in the spec
object rather than the top
level like XRDs. Crossplane adds its own fields to the spec when it processes the XRD
at installation time.
Generate the XRD
Next, run the up xrd generate
command with the path to your example claim.
up xrd generate examples/bucket/example.yaml
The up
CLI automatically generates the XRD and places it in
apis/xbuckets/definition.yaml
in your directory. Open the XRD to examine the structure.
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xbuckets.platform.upbound.io
spec:
claimNames:
kind: Bucket
plural: buckets
group: platform.upbound.io
names:
categories:
- crossplane
kind: XBucket
plural: xbuckets
versions:
- name: v1alpha1
referenceable: true
schema:
openAPIV3Schema:
description: Bucket is the Schema for the Bucket API.
properties:
spec:
description: BucketSpec defines the desired state of Bucket.
properties:
parameters:
properties:
encrypted:
type: boolean
versioning:
type: boolean
visibility:
type: string
type: object
status:
description: BucketStatus defines the observed state of Bucket.
type: object
required:
- spec
type: object
served: true
status:
controllers:
compositeResourceClaimType:
apiVersion: ""
kind: ""
compositeResourceType:
apiVersion: ""
kind: ""
XRD construction
Generating XRDs from basic claims is the most efficient way to build your schemas. In this section, you’ll review an XRD to understand the parts of the schema and how they relate back to your claims and compositions.
For the full example XRD, expand the XRD below.
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xbuckets.platform.upbound.io
spec:
claimNames:
kind: Bucket
plural: buckets
group: platform.upbound.io
names:
categories:
- crossplane
kind: XBucket
plural: xbuckets
versions:
- name: v1alpha1
referenceable: true
schema:
openAPIV3Schema:
description: Bucket is the Schema for the Bucket API.
properties:
spec:
description: BucketSpec defines the desired state of Bucket.
properties:
parameters:
properties:
encrypted:
type: boolean
versioning:
type: boolean
visibility:
type: string
type: object
status:
description: BucketStatus defines the observed state of Bucket.
type: object
required:
- spec
type: object
served: true
status:
controllers:
compositeResourceClaimType:
apiVersion: ""
kind: ""
compositeResourceType:
apiVersion: ""
kind: ""
API versioning and kind
XRDs use Kubernetes-style API versioning for objects. Crossplane owns and maintains the XRD objects’ API version and kind.
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata
The metadata
section contains the identifying information for the XRD. This
example has a name
that corresponds with the group. The control plane
registers this metadata when compositions or composite resources are requested.
name
metadata: name: xbuckets.platform.upbound.io
The x
naming convention isn’t a strict requirement, but helps
distinguish this as an XRD instead of the requested object itself.
You must pluralize the resource type in this section. The schema and rules of this XRD apply to all buckets created with it, not a specific instance of the resource.
The .platform.upbound.io
is the group this XRD applies to. Group definition
conventions are covered in the spec
section of this document.
spec
The spec
section defines the actual schema and behavior for your composite
resources. The spec
can vary based on the kinds of resources and providers you
are using.
group
You can set the group
field in a way that best meets your organization’s needs.
In this example, platform
describes the project name with upbound.io
being
the organization’s domain. This field is required.
group: platform.upbound.io
Your group
name must be lowercase and follow DNS-style subdomain naming.
You can create your group names by function data.upbound.io
, owner
dba.engineering.upbound.io
, or cloud environment aws-dbs.upbound.io
.
This group name is appended in the metadata.name
field. Creating group names
allows your resources to be unique across domains.
names
This field is required.
names:
categories:
- crossplane
kind: XBucket
plural: xbuckets
versions
The versions
section of an XRD defines the API version and schema of the set
of resources. This field is required.
versions.name
The versions.name
is a required field that defines the API version of the composite resource. You
can explicitly declare the version of your API schema to capture changes to your
XRDs. You must manually add a new version when your API changes.
As your XRD changes you should format your versions as
v<major><stability><revision>
. This XRD is the first created for these
resources and is named v1alpha1
. As your API schema changes or matures, you
can update to v1beta1
, v1beta2
, and v1
for production-ready APIs.
versions:
- name: v1alpha1
spec.versions.referenceable
A referenceable
schema means Compositions can reference this XRD in
their compositeTypeRef
. This field is required.
referenceable: true
spec.versions.schema.openAPIV3Schema
The schema.openAPIV3Schema
standardizes the API schema in a format Crossplane
can parse.
schema:
openAPIV3Schema:
spec.versions.schema.openAPIV3Schema.description
The description
field is a string to document what this schema does.
description: Bucket is the Schema for the Bucket API.
spec.versions.schema.openAPIV3Schema.properties.spec
The properties.spec
fields define the desired state of the resources in your
Composition. This field includes all the required parameters to provision and
manage the resource. In the example below, you must include if the bucket
encryption status, if the bucket supports versioning, and public visibility.
These fields aren’t declaring the values. The Composition includes and declares these values.
The properties of your resources vary based on the resource type.
properties:
spec:
description: BucketSpec defines the desired state of Bucket.
properties:
parameters:
properties:
encrypted:
type: boolean
versioning:
type: boolean
visibility:
type: string
type: object
spec.versions.schema.openAPIV3Schema.properties.status
The properties.status
field of the XRD allows you to assign a description for
the observed state of this resource.
status:
description: BucketStatus defines the observed state of Bucket.
type: object
spec.versions.required
The required
field captures the requirements for your Composition to declare.
required:
- spec
type: object
spec.versions.served
served
indicates that this version of the API is the current one to use. This field is required.
served: true
status
Your control plane uses the status
field to track the observed state of the
controllers that manage this composite resource.
status:
controllers:
compositeResourceClaimType:
apiVersion: ""
kind: ""
compositeResourceType:
apiVersion: ""
kind: ""
Because this XRD hasn’t been referenced and called by a Composition, the status fields are empty. Your control plane automatically updates these with values when it creates a controller to assign to this resource.
XRD design
To create an XRD based on your organization’s needs, consider what resources and services your users need provisioned.
- First, identify your goals:
- What resources do you need to manage?
- What teams or users need these resources?
- What level of abstraction can you provide in the XRD to help your users self-serve these resources?
- Plan your API design:
- What parameters should your users have control over?
- What are sensible defaults for other parameters?
- What settings should be explicitly denied?
With these questions answered, you can review your resource needs and find information on the individual managed resources you require in the Upbound Marketplace.
Example
A team in your organization requires an RDS instance, an S3 instance for backups,
CloudWatch Alarms for monitoring, an SNS
alert topic, and a Security Group with
ingress rules, you could create a claim including the resource parameters
that team needs:
apiVersion: db.example.org/v1alpha1
kind: ProductionDatabase
metadata:
name: customer-db
spec:
parameters:
size: large
engine: postgresql
backupRetentionDays: 30
alertEmail: dba@company.com
cpuUtilizationThreshold: 75
allowedCIDRs:
- "10.0.0.0/16"
- "172.16.0.0/12"
Then generate an XRD from that claim with up xrd generate claim.yaml
:
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xproductiondatabases.db.example.org
spec:
group: db.example.org
names:
categories:
- crossplane
kind: ProductionDatabase
plural: productiondatabases
versions:
- name: v1alpha1
referenceable: true
schema:
openAPIV3Schema:
description: ProductionDatabase is the Schema for the ProductionDatabase API.
properties:
spec:
description: ProductionDatabaseSpec defines the desired state of ProductionDatabase.
properties:
parameters:
properties:
alertEmail:
type: string
allowedCIDRs:
items:
type: string
type: array
backupRetentionDays:
type: number
cpuUtilizationThreshold:
type: number
engine:
type: string
size:
type: string
type: object
type: object
status:
description: ProductionDatabaseStatus defines the observed state of ProductionDatabase.
type: object
required:
- spec
type: object
served: true
Defining requirements and defaults
From this generated XRD, you can add more validation and requirements. For
example, to explicitly declare the allowed sizes and defaults of the database,
update the properties.size
field in the spec
.
size:
type: string
enum: ["small", "medium", "large"]
default: "small"
description: "Size of the database instance"