Improve Crossplane Compositions Authoring with go-templating-function
December 6, 2023
Read time: 7 mins
Introduction
Crossplane Compositions are a powerful abstraction layer that enables platform teams to create a custom API for their internal customers to simplify and standardize the infrastructure management process. The Composition authors wrestle with the complexity of cloud infrastructure and at the same time need to ensure a stable and user-friendly API surface for the platform consumers.
Historically, Compositions were intended to support only very simple resources’ manipulation to allow the API calls to patch and transform the information passed from a Claim or Composite Resource (XR) to the Composition engine. The lack of touring complete language supporting the required transformations resulted in a very verbose YAML files with lots of repetitions, increasing the toil of authoring Compositions.
With the addition of Compositions Functions in the Crossplane v.1.11 it is possible to use a programming language, like Go or Python (more to come) or in our case a capability of Go called Go-templating to enrich and transform the authoring of Compositions.
This blog will guide you through the process of rewriting a simple internal platform Composition in the Go templating style using the go-templating-function.
Use Case: Collapsing two Compositions into one
Since traditional Composition's engine does not allow using conditionals, there is no way to render one Composition or another using a parameter from a Claim. To illustrate this example, let’s look at the two Compositions that render a GCP Bucket:
Standard bucket
This very simple composition renders a single GCP bucket
1
Versioned Bucket
Another Composition needs to be created to accommodate for a versioning setting.
1
In this case, we have to have two Compositions and need to use a Composition selector in a claim just for this one field.
Using go-templating-function
The two Compositions can be transformed into just one using the go-templating-function. Follow these steps
1. Install go-templating-function and function-auto-ready from the marketplace.
1
2. Convert the Composition to use the go templating. The initial conversion gives us one to one translation between the standard “Patch and Transform” style Composition and the go-templating style. We are going to improve this design.
1
Using Composition Functions is very well documented in the Crossplane docs. Read the details to learn more about it.
The current implementation of our Composition renders the non-versioned Bucket. Next steps are to change the XRD and template to accommodate for the versioning field.
Using the new Crossplane beta trace command is helpful in checking the latest events on the composed resources from the Claim/XR:
Adding the versioning field
1. Modify the XRD to set the versioning field with a boolean flag:
1
2. Now let’s modify the Composition template to add the conditional for the versioning field.
1
3. Now we are ready to apply the Claim of the versioning enabled Bucket to the preconfigured GCP project.
1
The resource rendered correctly:
1
Default values
Not all the schema fields are required, and for those the Composition provides default values. location and storageClass are not required in the schema, and the Composition provides default values for those fields when omitted. Let’s add them to the template. Now supplying a Claim without the location and storageClass fields will result in the default values being rendered like so.
1
Bringing back PatchSets
This specific Composition is very simple, but there are multiple others where the same patch needs to be applied to multiple resources. In the original Composition we have the ownerAndServiceLabels that are applied to all resources that support labels.
1
With the go-templating-function, it’s easy to define the patchSet-like behavior
Here is the modified Composition template part with the labels:
1
Template Variables
One small quality of life improvement is to define variables in the template so there is no need to type .observed.composite.resource.spec.parameters all the time. Here is the final version of the Composition:
1
Conclusion
In conclusion, the use of the go-templating-function in Compositions authoring significantly simplifies the process of creating and managing resources with varying configurations and makes it easier to manage complex Compositions.
It allows for the creation of Compositions with conditional fields, reducing the need for multiple compositions for each variation of a resource. The re-introduction of PatchSets-like behavior makes the portability from “Patch and Transform” style Compositions easier. Adding variables scoped to Composite Resource paths makes it easier to reason about the template.
Additionally, using the new Crossplane CLI functionality to render the resources based on the Claim, Composition and functions and also trace the state of resources is a very helpful development tool. Here’s a tip: running the commands with watch makes the development loop even better.
1
If you are interested in technical details and design of the go-templating-function, check out the go-templating-function one-pager. Big thanks to @ezgidemirel for creating the function! It significantly improves the Compositions authoring process.
You can find various functions in our Marketplace and create your own to take the Crossplane Compositions to the next level.