Skip to content

CRD-Generated Classes

The k8s lexicon generates typed classes from the core Kubernetes OpenAPI spec plus a curated list of third-party CRDs. Each CRD in the list becomes a first-class K8s::* resource — with the serializer, LSP hover, type-checking, and MCP — the same as a built-in Deployment. No hand-written YAML, no as any.

CRD sources live in lexicons/k8s/src/crd/crd-sources.ts. At generation time (npm run generate) the CRD YAML is fetched from a pinned upstream URL, parsed, and baked into the lexicon output. The group’s first segment maps to a TypeScript namespace via the first-segment rule in crd/parser.ts — e.g. gateway.networking.k8s.ioGateway, cert-manager.ioCertManager.

group namespace example class
───────────────────────────── ─────────────── ─────────────────────────
ray.io Ray K8s::Ray::RayCluster
argoproj.io Argo K8s::Argo::Application
gateway.networking.k8s.io Gateway K8s::Gateway::HTTPRoute
crdb.cockroachlabs.com Crdb K8s::Crdb::CrdbCluster
cert-manager.io CertManager K8s::CertManager::Certificate
acme.cert-manager.io Acme K8s::Acme::Challenge
*.toolkit.fluxcd.io Flux K8s::Flux::Kustomization
fluxcd.controlplane.io Flux K8s::Flux::FluxInstance

The Flux rows show the override at work: six distinct groups all map to one Flux namespace (see Flux), rather than each group’s first segment.

gateway.networking.k8s.io, pinned to v1.2.1 (standard channel). The modern, portable replacement for IngressGRPCRoute in particular is the native way to express a gRPC route, instead of ingress-controller annotations.

TypeapiVersion / kind
GatewayClassgateway.networking.k8s.io/v1 / GatewayClass
Gatewaygateway.networking.k8s.io/v1 / Gateway
HTTPRoutegateway.networking.k8s.io/v1 / HTTPRoute
GRPCRoutegateway.networking.k8s.io/v1 / GRPCRoute
ReferenceGrantgateway.networking.k8s.io/v1beta1 / ReferenceGrant
Terminal window
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
import { Gateway, HTTPRoute } from "@intentius/chant-lexicon-k8s";
export const gw = new Gateway({
metadata: { name: "edge", namespace: "infra" },
spec: {
gatewayClassName: "istio",
listeners: [{ name: "http", protocol: "HTTP", port: 80 }],
},
});
export const route = new HTTPRoute({
metadata: { name: "api", namespace: "infra" },
spec: {
parentRefs: [{ name: "edge" }],
rules: [{ backendRefs: [{ name: "api", port: 8080 }] }],
},
});

cert-manager.io + acme.cert-manager.io, pinned to v1.16.2. The de-facto controller for issuing and rotating TLS certificates. The bundle is a single multi-doc YAML.

TypeapiVersion
Certificatecert-manager.io/v1
CertificateRequestcert-manager.io/v1
Issuercert-manager.io/v1
ClusterIssuercert-manager.io/v1
Challengeacme.cert-manager.io/v1
Orderacme.cert-manager.io/v1
Terminal window
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml
import { ClusterIssuer, Certificate } from "@intentius/chant-lexicon-k8s";
export const issuer = new ClusterIssuer({
metadata: { name: "letsencrypt-prod" },
spec: {
acme: {
server: "https://acme-v02.api.letsencrypt.org/directory",
email: "ops@acme.io",
privateKeySecretRef: { name: "letsencrypt-prod" },
solvers: [{ http01: { ingress: { class: "nginx" } } }],
},
},
});
export const cert = new Certificate({
metadata: { name: "api-tls", namespace: "api" },
spec: {
secretName: "api-tls",
issuerRef: { name: "letsencrypt-prod", kind: "ClusterIssuer" },
dnsNames: ["api.acme.io"],
},
});

When you set clusterIssuer on the SecureIngress composite, it now emits a genuine K8s::CertManager::Certificate (wired to the named issuer) alongside the ingress-shim annotation — no placeholder.

import { SecureIngress } from "@intentius/chant-lexicon-k8s";
export const ingress = SecureIngress("api", {
host: "api.acme.io",
serviceName: "api",
servicePort: 8080,
clusterIssuer: "letsencrypt-prod", // → annotation + a real Certificate
});

crdb.cockroachlabs.com, pinned to v2.17.0. The operator-managed path for a CockroachDB cluster — the operator handles version upgrades, scale-down decommissioning, and cert rotation.

TypeapiVersion / kind
CrdbClustercrdb.cockroachlabs.com/v1alpha1 / CrdbCluster
Terminal window
kubectl apply -f https://github.com/cockroachdb/cockroach-operator/releases/download/v2.17.0/install/operator.yaml
import { CrdbCluster } from "@intentius/chant-lexicon-k8s";
export const db = new CrdbCluster({
metadata: { name: "cockroachdb", namespace: "crdb" },
spec: {
dataStore: { pvc: { spec: { resources: { requests: { storage: "60Gi" } } } } },
tlsEnabled: true,
image: { name: "cockroachdb/cockroach:v24.1.0" },
nodes: 3,
},
});

The first two CRD sources. KubeRay (ray.io, v1.3.0) produces RayCluster, RayJob, and RayService. Argo CD (argoproj.io, v2.13.3) produces Application, ApplicationSet, and AppProject. Both ship value-add composites — see Argo CD Composites and the Ray + KubeRay on GKE tutorial.

The Flux GitOps Toolkit (pinned to flux2 v2.9.1) and the Flux Operator (v0.54.1). The toolkit spreads across five *.toolkit.fluxcd.io groups and the operator adds fluxcd.controlplane.io; all six collapse to a single Flux namespace, so a GitRepository and a Kustomization read as K8s::Flux::* siblings rather than scattering across Source, Kustomize, Helm, Notification, and Image.

Both sources are the release install.yaml — a multi-doc bundle of controllers, RBAC, and CRDs. The parser keeps only the CRD documents, and a kinds allowlist on each CRD_SOURCES entry narrows those to the supported set (the bundle also carries the experimental ExternalArtifact and ArtifactGenerator, left out for now).

TypeapiVersion / kind
GitRepositorysource.toolkit.fluxcd.io/v1
OCIRepositorysource.toolkit.fluxcd.io/v1
HelmRepositorysource.toolkit.fluxcd.io/v1
HelmChartsource.toolkit.fluxcd.io/v1
Bucketsource.toolkit.fluxcd.io/v1
Kustomizationkustomize.toolkit.fluxcd.io/v1
HelmReleasehelm.toolkit.fluxcd.io/v2
Providernotification.toolkit.fluxcd.io/v1beta3
Alertnotification.toolkit.fluxcd.io/v1beta3
Receivernotification.toolkit.fluxcd.io/v1
ImagePolicyimage.toolkit.fluxcd.io/v1
ImageRepositoryimage.toolkit.fluxcd.io/v1
ImageUpdateAutomationimage.toolkit.fluxcd.io/v1
FluxInstancefluxcd.controlplane.io/v1
FluxReportfluxcd.controlplane.io/v1
ResourceSetfluxcd.controlplane.io/v1
ResourceSetInputProviderfluxcd.controlplane.io/v1

Install the toolkit and, optionally, the operator:

Terminal window
# GitOps Toolkit controllers (source, kustomize, helm, notification, image)
kubectl apply -f https://github.com/fluxcd/flux2/releases/download/v2.9.1/install.yaml
# Flux Operator (manages a Flux instance declaratively)
kubectl apply -f https://github.com/controlplaneio-fluxcd/flux-operator/releases/download/v0.54.1/install.yaml
import { GitRepository, Kustomization } from "@intentius/chant-lexicon-k8s";
export const podinfo = new GitRepository({
metadata: { name: "podinfo", namespace: "flux-system" },
spec: {
interval: "1m",
url: "https://github.com/stefanprodan/podinfo",
ref: { branch: "master" },
},
});
export const apps = new Kustomization({
metadata: { name: "apps", namespace: "flux-system" },
spec: {
interval: "10m",
path: "./kustomize",
prune: true,
sourceRef: { kind: "GitRepository", name: "podinfo" },
},
});

Generated CRD classes expose a read-only status accessor alongside name, namespace, and uid. It carries the resource’s server-owned runtime state — never part of the writable constructor.

import { Certificate } from "@intentius/chant-lexicon-k8s";
const cert = new Certificate({
metadata: { name: "web-tls", namespace: "prod" },
spec: { secretName: "web-tls", issuerRef: { name: "letsencrypt" } },
});
// Read-only — populated at apply time, typed from the CRD's status schema.
cert.status; // Certificate_Status — notAfter, notBefore, renewalTime, revision, conditions

The per-field status shape is generated from the CRD’s openAPIV3Schema the same way spec field typing is — surfaced through LSP hover, validation, and MCP. Scalar leaves (notAfter, revision, a RayCluster’s head.serviceIP) are typed; deeply nested or x-kubernetes-preserve-unknown-fields status degrades to an opaque record. CRDs without a status schema (config-only kinds like a Prometheus ServiceMonitor) get no status accessor.

Append an entry to CRD_SOURCES in lexicons/k8s/src/crd/crd-sources.ts and re-run codegen:

export const CRD_SOURCES: CRDSource[] = [
// ...existing entries
{ type: "url", url: "https://raw.githubusercontent.com/acme/operator/v1.0.0/config/crd/bases/acme.io_widgets.yaml" },
];
Terminal window
cd lexicons/k8s && npm run generate

Guidelines:

  • Pin the version in the URL (a vX.Y.Z tag or release asset), never main. Codegen is deterministic only if the source is.
  • One URL per CRD, or a single multi-doc bundle URL (the parser uses loadAll, as with cert-manager).
  • The group’s first segment becomes the namespace. Add a GROUP_NAMESPACE_OVERRIDES entry in crd/parser.ts if the default mapping reads poorly.
  • Document the produced classes and the operator install command in a comment block next to the entry — match the existing entries.