Skip to content

crossplane-contrib/function-auto-ready

Repository files navigation

function-auto-ready

CI GitHub release (latest SemVer)

This composition function automatically detects composed resources that are ready. It considers a composed resource ready if:

  • Another function added the composed resource to the desired state.
  • The composed resource appears in the observed state (i.e. it exists).
  • For standard Kubernetes resources with health check implementations (see list below), the resource passes resource-specific health checks.
  • For all other resources (Crossplane managed resources, custom resources, etc.), the composed resource has the status condition type: Ready, status: True.

Crossplane considers a composite resource (XR) to be ready when all of its desired composed resources are ready.

Health Checks

This function implements resource-specific health checks for standard Kubernetes resources. The following table shows the current implementation status:

Core (core/v1)

  • Pod - Succeeded, or Running with Ready condition (RestartPolicy: Always)
  • Service - ClusterIP/NodePort: immediately ready; LoadBalancer: requires ingress assignment
  • Namespace - Always ready if it exists
  • Node
  • ConfigMap - Always ready if it exists
  • Secret - Always ready if it exists
  • ServiceAccount - Always ready if it exists
  • Endpoints
  • PersistentVolume
  • PersistentVolumeClaim - Phase is Bound
  • ReplicationController
  • ResourceQuota
  • LimitRange
  • Event

Apps (apps/v1)

  • Deployment - spec.replicas == status.availableReplicas, all replicas updated, Available condition is True
  • StatefulSet - spec.replicas == status.readyReplicas, all replicas at current revision
  • DaemonSet - All desired pods are scheduled, ready, updated, and available
  • ReplicaSet - Observed generation matches, available replicas match desired, no replica failures

Batch (batch/v1)

  • Job - Complete condition is True (not Failed or Suspended)
  • CronJob - Suspended, has active jobs, or last execution succeeded

Autoscaling (autoscaling/v2)

  • HorizontalPodAutoscaler - ScalingActive or ScalingLimited, no failed conditions

Networking (networking.k8s.io/v1)

  • Ingress - Load balancer ingress is assigned
  • IngressClass
  • NetworkPolicy

RBAC (rbac.authorization.k8s.io/v1)

  • Role
  • ClusterRole
  • RoleBinding
  • ClusterRoleBinding

Storage (storage.k8s.io/v1)

  • StorageClass
  • VolumeAttachment
  • CSIDriver
  • CSINode

Policy (policy/v1)

  • PodDisruptionBudget

For all other resource types (Crossplane managed resources, custom resources, etc.), the function falls back to checking the standard Ready status condition.

CEL-based health checks (alpha)

Some resource types — notably Crossplane Configuration and Provider packages, Cluster API Cluster and many more — do not surface a Ready status condition, so the default fallback never considers them ready. To handle these cases the function supports user-defined readiness expressions written in CEL, gated behind the CELHealthcheckCustomizations alpha feature gate.

Enable the feature gate when running the function:

function-auto-ready --feature-gates=CELHealthcheckCustomizations=true

Customizations are supplied as a map keyed by <group>_<version>_<kind> (the group's dots replaced with underscores; the core group is the empty string). Each value is a CEL expression evaluated against the observed composed resource, bound to the variable object. The expression must return a boolean — any other result, or an evaluation error, is treated as not ready and surfaces a Warning on the response. When a customization exists for a given GVK it takes precedence over the built-in health check.

There are two ways to supply customizations, and they can be combined:

Inline CEL rules (celHealthCheckCustomization)

Define rules directly in the function input. This is the simplest option when the rules are static and do not need to vary across environments:

- step: automatically-detect-ready-composed-resources
  functionRef:
    name: function-auto-ready
  input:
    apiVersion: autoready.fn.crossplane.io/v1alpha1
    kind: Input
    celHealthCheckCustomization:
      pkg.crossplane.io_v1_Configuration: >-
        object.status.conditions.exists(c, c.type == 'Installed' && c.status == 'True') &&
        object.status.conditions.exists(c, c.type == 'Healthy'   && c.status == 'True')
      cluster.cluster.x-k8s.io_v1beta1_Cluster: >-
        object.status.conditions.exists(c, c.type == 'Ready' && c.status == 'True')

CEL rules from the function context (celHealthCheckCustomizationFrom)

Read the map from the function's request context by providing a field path. This is useful when rules need to vary per environment or be shared across multiple compositions:

- step: automatically-detect-ready-composed-resources
  functionRef:
    name: function-auto-ready
  input:
    apiVersion: autoready.fn.crossplane.io/v1alpha1
    kind: Input
    celHealthCheckCustomizationFrom: "[apiextensions.crossplane.io/environment].celHealthCheckCustomizations"

Any source that populates the function context can supply the map — typically function-environment-configs reading an EnvironmentConfig, but an earlier pipeline step works just as well.

Combining both sources

Both fields can be set at the same time. Context-provided rules are loaded first; inline rules are then merged on top of them. Inline entries take precedence, so they can selectively override context-provided rules for specific GVKs without replacing the entire map.

See example/cel-healthcheck for a runnable example that checks the Installed and Healthy conditions on a Crossplane Configuration.

In this example, the Go Templating function is used to add a desired composed resource - an Amazon Web Services S3 Bucket. Once Crossplane has created the Bucket, the Auto Ready function will let Crossplane know when it is ready. Because this XR only has one composed resource, the XR will become ready when the Bucket becomes ready.

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: example
spec:
  compositeTypeRef:
    apiVersion: example.crossplane.io/v1beta1
    kind: XR
  mode: Pipeline
  pipeline:
  - step: create-a-bucket
    functionRef:
      name: function-go-templating
    input:
      apiVersion: gotemplating.fn.crossplane.io/v1beta1
      kind: GoTemplate
      source: Inline
      inline:
        template: |
          apiVersion: s3.aws.upbound.io/v1beta1
          kind: Bucket
          metadata:
            annotations:
              gotemplating.fn.crossplane.io/composition-resource-name: bucket
          spec:
            forProvider:
              region: {{ .observed.composite.resource.spec.region }}
  - step: automatically-detect-ready-composed-resources
    functionRef:
      name: function-auto-ready

See the example directory for an example you can run locally using the Crossplane CLI:

$ crossplane render xr.yaml composition.yaml functions.yaml

To test with observed resources (simulating resources that already exist):

$ crossplane render xr.yaml composition-k8s.yaml functions.yaml -o observed-k8s.yaml

See the composition functions documentation to learn more about crossplane render.

Function Response Caching

You can set the ttl input to control the Function response cache time-to-live. This is useful for tuning reconciliation behavior in large compositions.

  - step: auto-detect-ready-resources
    functionRef:
      name: function-auto-ready
    input:
      apiVersion: autoready.fn.crossplane.io/v1beta1
      kind: Input
      ttl: 5m

There is also a --ttl input parameter to the function that can be used to set the default TTL used when it is not set in the composition function input. Use a DeploymentRuntimeConfig to set this parameter.

apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
  name: function-auto-ready
spec:
  deploymentTemplate:
    spec:
      selector: {}
      template:
        spec:
          containers:
          - name: package-runtime
            args:
            - --debug
            - --ttl="5m"

Developing this function

This function uses Go, Docker, and the Crossplane CLI to build functions.

# Run code generation - see input/generate.go
$ go generate ./...

# Run tests - see fn_test.go
$ go test ./...

# Build the function's runtime image - see Dockerfile
$ docker build . --tag=runtime

# Build a function package - see package/crossplane.yaml
$ crossplane xpkg build -f package --embed-runtime-image=runtime

About

A composition function that automatically detects when resources are ready

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors