Skip to content
kix /docs
Install the CLI

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.

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:

FieldMeaning
labels, annotationsMetadata added to the CRD.
ownership.cedeCRD fields that another manager may own, commonly spec.versions or conversion-webhook fields. It has the same behavior as on mkResource.
readinessReadiness rule stamped on every custom resource made from this declaration. Use either { path; equals; } or { condition = { type; status; }; }.
factBehaviorWhether 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.

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";
};
};
FieldDefaultMeaning
group, kind, pluralrequiredIdentity of the custom API.
versionrequiredThe 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.
crdScopeNamespacedNamespaced or Cluster, as the CRD’s spec.scope says; selects the resource builder.
installedBynullResource, or list of resources, that installs the CRD. The CRD marker waits for them.
readinessnullDefault readiness rule for custom resources.
factBehaviornullEndpoint 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.

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.