v1beta2 Spec#557
Conversation
Users must now provide a workflow template explicitly via templateInline or templateRef. The built-in default template was tightly coupled to a specific OS image layout and hindered customization. Removing it along with the ImageLookup* fields (imageLookupBaseRegistry, imageLookupOSDistro, imageLookupOSVersion, imageLookupFormat) simplifies the API surface and eliminates dead code paths. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
TemplateOverride implied replacing a default that no longer exists. Rename to TemplateInline to reflect its purpose as an inline workflow template definition. Add TemplateRef on TinkerbellMachineSpec to allow referencing a Tinkerbell Template CR by name/namespace, with machine-level TemplateRef taking precedence over cluster-level settings. Add CEL validation to enforce mutual exclusivity of templateInline and templateRef. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
Introduce TinkerbellMachineConfig containing only user-configurable fields (TemplateInline, TemplateRef, HardwareAffinity, BootOptions) and embed it in TinkerbellMachineSpec. Change TinkerbellMachineTemplateResource.Spec to use TinkerbellMachineConfig instead of TinkerbellMachineSpec, structurally preventing providerID and hardwareName from appearing in machine templates. This replaces the runtime webhook checks with compile-time type safety. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
Move api/ into its own Go module so downstream consumers can import API types without pulling in controller-runtime. Replace scheme.Builder with runtime.NewSchemeBuilder from k8s.io/apimachinery and centralize type registration. Move webhook implementations to a top-level webhooks/ package using wrapper types, since methods cannot be defined on types from external modules. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR removes CAPT’s default template/image-lookup workflow generation, introduces explicit template selection (templateInline/templateRef), refactors machine template safety via TinkerbellMachineConfig, and extracts API types into a standalone Go module while relocating webhook implementations.
Changes:
- Remove
ImageLookup*fields and default template generation; reconciliation now requires an explicit template source. - Rename
templateOverride→templateInline, addtemplateRef, and enforce mutual exclusivity via CEL validations/CRD schema updates. - Split
api/into a separate Go module and move webhook implementations to a top-levelwebhooks/package.
Reviewed changes
Copilot reviewed 29 out of 31 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| webhooks/webhooks.go | Rename package and centralize shared webhook helpers. |
| webhooks/tinkerbellmachinetemplate_webhook.go | New webhook wrapper for TinkerbellMachineTemplate validation/immutability. |
| webhooks/tinkerbellmachine_webhook.go | New webhook wrapper for TinkerbellMachine validation. |
| webhooks/tinkerbellmachine_webhook_test.go | Update tests to use the new webhooks package wrapper types. |
| webhooks/tinkerbellcluster_webhook.go | New no-op cluster webhook wrapper (defaulting removed with image lookup). |
| main.go | Wire up the new top-level webhooks package in manager setup. |
| controller/machine/template.go | Remove default template generation and implement template resolution (inline/ref/annotation/cluster). |
| controller/machine/template_test.go | Remove tests for deleted default-template rendering helper. |
| controller/machine/tinkerbellmachine_test.go | Update tests for templateInline/templateRef and add cluster template inline data in fixtures. |
| controller/cluster/tinkerbellcluster_test.go | Remove calls to cluster defaulting that no longer exists. |
| api/v1beta1/tinkerbellmachine.go | Introduce TinkerbellMachineConfig, embed into TinkerbellMachineSpec, add inline/ref fields. |
| api/v1beta1/types.go | Use TinkerbellMachineConfig in machine templates to prevent runtime fields in templates. |
| api/v1beta1/tinkerbellcluster.go | Remove image lookup fields; add templateInline/templateRef. |
| api/v1beta1/groupversion_info.go | Replace controller-runtime scheme builder with apimachinery scheme builder registration. |
| api/v1beta1/zz_generated.deepcopy.go | Regenerate deepcopy for new config/spec structures. |
| api/v1beta1/tinkerbellcluster_webhook.go | Remove old in-api webhook implementation (moved to top-level webhooks/). |
| api/v1beta1/tinkerbellmachinetemplate_webhook.go | Remove old in-api webhook implementation (moved to top-level webhooks/). |
| api/v1beta1/tinkerbellmachinetemplate.go | Remove per-file scheme registration init (centralized in groupversion). |
| templates/cluster-template.yaml | Remove image lookup field from rendered cluster template. |
| config/crd/bases/infrastructure.cluster.x-k8s.io_tinkerbellclusters.yaml | CRD schema updates for templateInline/templateRef and CEL validation. |
| config/crd/bases/infrastructure.cluster.x-k8s.io_tinkerbellmachines.yaml | CRD schema updates for embedded config + controller-managed fields + template fields. |
| config/crd/bases/infrastructure.cluster.x-k8s.io_tinkerbellmachinetemplates.yaml | CRD schema updates to use config-only spec and add template inline/ref fields + CEL. |
| config/manager/manager.yaml | Remove TINKERBELL_IP env var now that default template generation is gone. |
| docs/QUICK-START.md | Update docs to reflect required explicit template configuration and new field names. |
| docs/PLAYGROUND.md | Remove TINKERBELL_IP env var from example usage. |
| Tiltfile | Remove TINKERBELL_IP string replacement since env var is no longer used. |
| Makefile | Adjust manifest generation to run controller-gen for webhooks separately. |
| go.mod | Add internal api module dependency + replace, update Go version, adjust direct/indirect deps. |
| go.sum | Dependency checksum updates from module refactor/tidy. |
| api/go.mod | New standalone API module definition for downstream consumption. |
| api/go.sum | New API module dependency checksums. |
Comments suppressed due to low confidence (1)
webhooks/tinkerbellmachine_webhook.go:85
- The field path in the validation error uses Go field names ("HardwareAffinity", "Preferred") instead of the JSON field names ("hardwareAffinity", "preferred"). This makes API error responses point to non-existent spec paths. Use the JSON field names in field.Path construction so users can locate the invalid field.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…bhook: Extract fetchTemplateRefData helper to eliminate duplicate template-fetch-and-nil-check logic across resolveTemplateData, clusterTemplate, and templateFromAnnotation. This also fixes a nil-pointer dereference in templateFromAnnotation when a referenced Template exists but has no spec.data. Add tests for machine-level templateInline/templateRef resolution and error paths (no template configured, template ref with nil data). Remove the no-op Defaulter webhook and mutating webhook registration for TinkerbellCluster since there is nothing left to default after the imageLookup fields were removed. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
The mutating webhook for TinkerbellCluster was removed in the previous commit but the kustomize overlay still referenced it, breaking the release build. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 35 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
webhooks/tinkerbellmachine_webhook.go:85
- The FieldPath in the validation error uses Go field names ("HardwareAffinity"/"Preferred") instead of the JSON field names ("hardwareAffinity"/"preferred"). This will surface incorrect paths to users and tooling when the webhook rejects an object. Use the JSON field names in field.NewPath/Child calls so the returned Invalid error points at the correct spec location.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if err != nil { | ||
| return "", fmt.Errorf("unable to execute template: %w", err) | ||
| if refTemplate.Spec.Data == nil { | ||
| return "", fmt.Errorf("%w: %s", ErrTemplateRefNoData, namespacedName.String()) |
There was a problem hiding this comment.
When the referenced Template exists but has nil spec.data, the returned error omits which reference source triggered it (machine/cluster/hardware annotation). Since source is already passed in for error reporting, include it in this error path as well to make debugging easier (especially when multiple template sources are configured).
| return "", fmt.Errorf("%w: %s", ErrTemplateRefNoData, namespacedName.String()) | |
| return "", fmt.Errorf("%w: %s referenced by %s", ErrTemplateRefNoData, namespacedName.String(), source) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 35 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
webhooks/tinkerbellmachine_webhook.go:86
- The generated field path for invalid preferred affinity weights uses Go struct field names ("HardwareAffinity", "Preferred") rather than the JSON field names ("hardwareAffinity", "preferred"). This will produce confusing/incorrect error locations in API validation responses. Use the JSON field names in the field path so users see the correct spec path.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # A Tinkerbell Template is required for provisioning. Set templateInline with an | ||
| # inline template definition, or templateRef to reference an existing Template object. | ||
| # See docs/QUICK-START.md for examples and the template resolution order. |
There was a problem hiding this comment.
This cluster template now leaves spec: empty (YAML null) and does not set templateInline or templateRef anywhere (cluster-level or machine templates). With the new behavior (“no default template”), applying these manifests will fail schema validation (spec must be an object) and/or reconciliation will fail due to no template being configured. Update the example to use spec: {} at minimum and include a concrete templateInline or templateRef (or add a placeholder with clear instructions) so the template is valid with the new API.
| # A Tinkerbell Template is required for provisioning. Set templateInline with an | |
| # inline template definition, or templateRef to reference an existing Template object. | |
| # See docs/QUICK-START.md for examples and the template resolution order. | |
| # A Tinkerbell Template is required for provisioning. Replace this placeholder | |
| # templateRef with a real Template object in your environment, or use | |
| # templateInline instead. | |
| # See docs/QUICK-START.md for examples and the template resolution order. | |
| templateRef: | |
| apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1 | |
| kind: Template | |
| name: "${CLUSTER_NAME}-template" |
Without this, migrating existing v1beta1 cluster would be extremely impactful. The user experience would not be great. This uses the existing Kubernetes model for API versioning and conversion. Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
Description
This PR makes four structural changes to the CAPT API surface and codebase organization. Up to this point the API specs for CAPT had fields like
imageLookupBaseRegistry,imageLookupOSDistro,imageLookupOSVersion,imageLookupFormat. Using these fields would allow a "default Tinkerbell Template" to be generated. This default Template has almost always, if not always, not been enough for users. User would use the "TemplateOverride". This PR removes unused code, feature, capability, etc.1. Remove ImageLookup fields and default template generation
Users must now provide a workflow template explicitly via
templateInlineortemplateRef. The built-in default template was tightly coupled to a specific OS image layout and hindered customization. Removing it along with theImageLookup*fields (imageLookupBaseRegistry,imageLookupOSDistro,imageLookupOSVersion,imageLookupFormat) simplifies the API surface and eliminates dead code paths.2. Rename TemplateOverride to TemplateInline and add TemplateRef
TemplateOverrideimplied replacing a default that no longer exists. Rename toTemplateInlineto reflect its purpose as an inline workflow template definition. AddTemplateRefonTinkerbellMachineSpecto allow referencing a Tinkerbell Template CR by name/namespace, with machine-levelTemplateReftaking precedence over cluster-level settings. CEL validation enforces mutual exclusivity oftemplateInlineandtemplateRef.3. Extract TinkerbellMachineConfig for template resource safety
Introduce
TinkerbellMachineConfigcontaining only user-configurable fields (TemplateInline,TemplateRef,HardwareAffinity,BootOptions) and embed it inTinkerbellMachineSpec. ChangeTinkerbellMachineTemplateResource.Specto useTinkerbellMachineConfiginstead ofTinkerbellMachineSpec, structurally preventingproviderIDandhardwareNamefrom appearing in machine templates. This replaces the runtime webhook checks with compile-time type safety.4. Extract API types into separate Go module and move webhooks
Move
api/into its own Go module (github.com/tinkerbell/cluster-api-provider-tinkerbell/api) so downstream consumers can import API types without pulling incontroller-runtime. Replacescheme.Builderwithruntime.NewSchemeBuilderfromk8s.io/apimachineryand centralize type registration. Move webhook implementations to a top-levelwebhooks/package using wrapper types, since methods cannot be defined on types from external modules. This will allow for the Tinkerbell repo to pull in the API specs so that the UI can display them along with the core Tinkerbell APIs.Breaking changes
spec.imageLookupBaseRegistry,spec.imageLookupOSDistro,spec.imageLookupOSVersion, andspec.imageLookupFormatare removed fromTinkerbellClusterSpecandTinkerbellMachineSpec.spec.templateOverrideis renamed tospec.templateInlineon bothTinkerbellClusterSpecandTinkerbellMachineSpec.TinkerbellMachineTemplateResource.Specis nowTinkerbellMachineConfiginstead ofTinkerbellMachineSpec— templates can no longer specifyproviderIDorhardwareName.api/directory is now a separate Go module. Consumers must importgithub.com/tinkerbell/cluster-api-provider-tinkerbell/apidirectly.Fixes: #
How Has This Been Tested?
How are existing users impacted? What migration steps/scripts do we need?
Checklist:
I have: