Reference scope helpers
CRDs and CRD refs
Declare an installed or external CustomResourceDefinition and build typed custom resources that wait for API discovery and use the right scope.
Use scope.mkCRD when the package deploys a CustomResourceDefinition. Use
scope.mkCRDRef when the definition is already installed or another resource
creates it. Both return the same typed custom-resource builders.
The builders add an ordering dependency on the CRD marker. During deploy,
Kix waits for the CRD to be served and refreshes API discovery before applying
the custom resource. A plain requires edge to an operator Deployment cannot
provide that guarantee.
This page is hand-maintained. Check kix/lib/scope/builders.nix and
kix/lib/core/resource.nix when in doubt.
Install a CRD with the package
Section titled “Install a CRD with the package”Pass the upstream CRD’s spec to scope.mkCRD:
widgetCrd = scope.mkCRD { spec = builtins.fromJSON (builtins.readFile ./widgets.example.com.json); readiness.condition = { type = "Ready"; status = "True"; };};mkCRD derives the custom resource’s group, kind, plural, scope, and default
version from the spec. It chooses the version marked storage = true, or the
first version when none is marked. Every version not marked served = false
is a served version. The CRD itself is cluster-scoped.
Accepted optional fields are:
| Field | Meaning |
|---|---|
labels, annotations | Metadata added to the CRD. |
ownership.cede | CRD fields that another manager may own, commonly spec.versions or conversion-webhook fields. It has the same behavior as on mkResource. |
readiness | Readiness rule stamped on every custom resource made from this declaration. Use either { path; equals; } or { condition = { type; status; }; }. |
factBehavior | Whether custom resources of this kind conduct endpoint facts or terminate them in operator-created pods. |
readiness describes the custom resources, not the CRD. The deploy engine
handles the CRD’s own availability through the CRD barrier.
Refer to a CRD installed elsewhere
Section titled “Refer to a CRD installed elsewhere”Describe the API without rendering its definition:
widgetCrd = scope.mkCRDRef { group = "example.com"; kind = "Widget"; plural = "widgets"; version = "v1"; crdScope = "Namespaced"; installedBy = self.widgetOperator; readiness.condition = { type = "Ready"; status = "True"; };};| Field | Default | Meaning |
|---|---|---|
group, kind, plural | required | Identity of the custom API. |
version | required | The API version the CRD serves for this kind, such as v1 or v1beta1. Custom resources use it unless they set their own version. |
servedVersions | [ version ] | Every served version a custom resource of this kind may set, such as [ "v1" "v1beta1" ]. Must include version. A custom resource that sets any other version fails the build. |
crdScope | Namespaced | Namespaced or Cluster, as the CRD’s spec.scope says; selects the resource builder. |
installedBy | null | Resource, or list of resources, that installs the CRD. The CRD marker waits for them. |
readiness | null | Default readiness rule for custom resources. |
factBehavior | null | Endpoint fact behavior for this custom kind. |
Kix does not install the CRD, so it cannot read the served versions from a
spec. A missing version fails the build. Check the versions on a live
cluster with
kubectl get crd <plural>.<group> -o jsonpath='{.spec.versions[?(@.served==true)].name}'.
kix deploy checks the declared versions against the live CRD once it is
Established.
The reference renders a PackageInstance marker named
crd-ref-<instance>-<plural>-<group with dots as dashes> in the package’s
namespace, so two instances that reference one CRD get one marker each. The
marker carries the declared kind, version, and scope as kix.run/crd-kind,
kix.run/crd-version, and kix.run/crd-scope.
With no installedBy, the marker represents a CRD the platform has already
installed. Kix still verifies through discovery that the API is available
before applying dependent custom resources.
Build custom resources
Section titled “Build custom resources”Pass either declaration to scope.mkCR:
widget = scope.mkCR self.widgetCrd { name = scope.instanceName; spec = { size = 3; };};For a namespaced CRD, the resource lands in the consumer’s package namespace.
For a cluster-scoped CRD, it has no namespace. The helper supplies
apiVersion, kind, and the CRD dependency. Pass version = "v1beta1" on
one custom resource to select another served version. A version the
declaration does not serve fails the build: for mkCRD, one missing from
spec.versions or marked served = false; for mkCRDRef, any version not in
its servedVersions. The same check applies to the builders a Helm chart’s
CRDs provide.
scope.mkCR crd args is the convenient form of crd.out.mkCR scope args.
The declaration also exposes crd.out.cr args, which enriches the arguments
with apiVersion, kind, and requires but does not seal them in a scope.
See Declare readiness for custom resources for readiness behavior and validation.