Dev Notes for Composition Functions

Read from Desired vs Observed

It may not be easy to determine when to read from the desired or observed resources in the composition function.

On the very first run of the composition functions, the observe array will always be empty. To ensure that you always get a valid object in that case, you can first try to read from observed, and if that fails, read from desired.

Desired

Contains the list of resource that will be applied after the function has run. They are the sum of the P+T composition and the composition functions.

Read from this if:

  • you manipulate the same resources as a previous step, otherwise you could overwrite resources

  • you don’t need to know how the resource currently looks like but how it should look like after the function has run

Observed

The observed array contains resources as they are on the cluster right before the composition function triggered.

Read from this if:

  • you need access to the status

  • you want to read secrets

  • an outside actor changes values of the resource (for example maintenance jobs)

How to read unmanaged secrets

There are cases where you need to read a secret that was created by an operator or helm chart, for example to add them to the connection details.

To read unmanaged secrets, you need to:

  • create an observe kube object that references the given secret

  • then get the secret through this observe kube object during the next reconcile

When doing it this way the secret values are available in plaintext and NOT in base64.

How to (not) delete resources in the composition function

For crossplane, if a given resource was in the desired map during the previous reconcile, but is missing in the current reconcile, then it will be removed. If, for any reason, the resource name in the map changes, even though it’s still the same object, crossplane will delete and re-create it. That’s because for crossplane it’s a new object in that case, as it uses the resource name to identify the resources. The resource name of important resources (releases, deployments, pvcs, etc.) should never change, or expect unhappy users.

If an object should not get deleted, then it has to be actively be added to the desired array on every reconcile. On the flip side, deleting an object is easily achieved by not adding it to the desired array.

When to use Composition functions, jobs and cronjobs

The general rule is to keep the composition functions as simple as possible. They should be used mainly to create and observe objects related to the instances.

If there’s a need for more complex one time operations, please consider putting them into a separate job that is deployed via the composition function. Example for such a job is the restore of a backup. Try to make those jobs idempotent if possible.

If there’s a need for more complex operations on a schedule, please consider putting them into a cronjob that is deployed via the composition function. Examples for such cronjobs are maintenance and backups.