Components
A component in AICR is a registry entry pointing to a Helm chart or
Kustomize source that recipes can pull. The catalog lives in
recipes/registry.yaml;
per-component default values live under
recipes/components/<name>/.
Overlays bind a component to a cluster shape; bundlers turn that
binding into a deployer-specific artifact.
Most components need no Go code. The declarative path is one
registry entry plus a values.yaml. The legacy
pkg/component/generic.go::ComponentConfig
is marked Deprecated — it is unused in production. The live schema
is pkg/recipe/components.go::ComponentConfig.
For the recipe data model — overlays, mixins, criteria, merge order — see /aicr/contributor-guide/recipes-overlays-and-mixins. This page is the contributor view for adding or changing components.
Where Does My Change Go?
Helm vs Kustomize
A component declares either helm: or kustomize: — never
both. ComponentRegistry.Validate rejects the mixed shape at load.
Kustomize limitations to know up front:
--set <key>:<path>=<value>flows through Helm value rendering only; Kustomize components silently ignore overrides.nodeScheduling.system/acceleratedpaths target Helm values; they do not apply to Kustomize sources.- The bundler runs
kustomize buildat bundle time and wraps the output astemplates/manifest.yamlinside the standard local-format folder (see /aicr/contributor-guide/architecture-overview for the classification rule).
Adding a Helm Component
1. Add the registry entry to recipes/registry.yaml:
2. Create recipes/components/my-operator/values.yaml with the
chart defaults you want every recipe to start from. Keep this file
minimal and widely applicable — cluster-specific tweaks belong in
values-<context>.yaml siblings referenced from an overlay.
3. Optional blocks on the registry entry:
validations:— bundle-time misconfiguration warnings (/aicr/contributor-guide/validators)healthCheck.assertFile:— chainsaw conformance assertions (/aicr/contributor-guide/validators)storageClassPaths:— where--storage-classis injectedpodScheduling.workload.workloadSelectorPaths— for workload-pod placementgkeCriticalPriority,hasSelfRefCRDs— narrow service-specific quirks (see godoc onComponentConfigfor when these apply)
4. Run make bom-docs and commit the regenerated
docs/user/container-images.md in the same PR. CLAUDE.md treats this
as a hard rule whenever you change registry.yaml, a component’s
values.yaml, or any chart version pin. See BOM regeneration.
5. Run make qualify — covers tests, lint, and the recipe-resolution
suite that parses every registry entry.
Adding a Kustomize Component
No recipes/components/<name>/values.yaml is required — Kustomize
reads its inputs from the upstream source. Reminder: no --set
overrides, and nodeScheduling paths do not apply.
Schema Reference
Authoritative definitions live in
pkg/recipe/components.go.
One-liner per field:
nodeScheduling.system vs accelerated
This is the field most contributors get wrong on first PR.
system— paths into chart values for workloads that must land on management / control-plane nodes (e.g., operators, controllers, webhooks). The bundler writes the--system-node-selectorand--system-node-tolerationvalues here.accelerated— paths into chart values for workloads that must land on GPU nodes (e.g., device-plugin DaemonSets, driver-validation, DCGM exporters). The bundler writes the--accelerated-node-selectorand--accelerated-node-tolerationvalues here.
Concrete example from gpu-operator:
Wrong column = workloads land on the wrong node class. A DaemonSet
placed under system will miss GPU nodes; an operator under
accelerated will refuse to schedule on a cluster with tainted GPU
nodes only.
valueOverrideKeys
--set <key>:<path>=<value> matches via GetByOverrideKey:
- The component
nameis checked first. - Each entry in
valueOverrideKeysis then checked.
For gpu-operator with valueOverrideKeys: [gpuoperator], both
--set gpu-operator:driver.version=... and
--set gpuoperator:driver.version=... resolve to the same component.
Pick a key that is easier to type (no hyphens) and document it in the
displayName-adjacent comments if non-obvious. Override keys are
globally unique — ComponentRegistry.Validate rejects duplicates.
deploymentOrder
RecipeResult.DeploymentOrder is derived, not authored.
TopologicalSort in pkg/recipe/metadata_store.go orders components
by componentRefs[].dependencyRefs declared in the overlay. When no
dependencies are declared, the order falls back to the order in
which components are listed in the overlay’s componentRefs. Express
ordering by declaring dependencyRefs on the dependent component, not
by writing a separate deploymentOrder block.
Local Format and Bundle Classification
The bundler emits a uniform NNN-<component>/ layout via
pkg/bundler/deployer/localformat.
Classification (single source of truth in localformat.classify):
If both helm and kustomize fields are populated, Validate
rejects the registry entry — there is no precedence rule because the
shape is invalid. manifestFiles are added post-chart; preManifestFiles
ship at sync-wave N-1 (e.g., a Namespace with PSS labels the chart
pods depend on).
Deployers
AICR ships five output adapters in
pkg/bundler/deployer/:
helm, helmfile, argocd, argocdhelm, flux. Each calls
localformat.Write() and then layers its own orchestration files
(deploy.sh, helmfile.yaml, Argo Application CRs, Flux
HelmReleases). Components do not need to be deployer-aware —
the bundler renders per-deployer from one component definition.
See /aicr/contributor-guide/architecture-overview for the deployer matrix.
BOM Regeneration
docs/user/container-images.md is rendered fresh from each Helm
chart’s actual templates by make bom-docs. Run it and commit the
regenerated file in the same PR whenever you:
- Add or remove a component
- Bump a chart version (in
registry.yaml, an overlay, or a mixin) - Change a
values.yamlin a way that affects which images render (image-repo override, subchart enable/disable, etc.)
make bom-check verifies the committed BOM matches a fresh regen
but is opt-in only — not wired into make qualify, make lint,
or the merge gate. Do not rely on CI to catch a missed regen.
Boundary: Components Are Metadata
A component entry describes what to deploy and where its values
land. Components do not carry apply, wait, uninstall, rollback,
or readiness-polling logic — those concerns belong to the deployer
that consumes the bundle. If you find yourself writing custom apply
code inside the bundler or under pkg/component/, you are on the
wrong side of the boundary — see
/aicr/contributor-guide/architecture-overview “What AICR Is Not”.
See Also
- /aicr/contributor-guide/recipes-overlays-and-mixins — overlays, mixins, criteria, the recipe data model
- /aicr/contributor-guide/validators — bundle-time component validation checks
- /aicr/contributor-guide/validators — chainsaw health checks and validator runner
- /aicr/contributor-guide/architecture-overview — contributor index and architectural boundary
- integrator/recipe-development.md — end-user recipe authoring
- user/component-catalog.md — end-user component catalog
pkg/recipe/components.go—ComponentConfigsource of truthrecipes/registry.yaml— live component catalog