Skip to content

v1beta2 Spec#557

Open
jacobweinstock wants to merge 9 commits into
tinkerbell:mainfrom
jacobweinstock:remote-default-template
Open

v1beta2 Spec#557
jacobweinstock wants to merge 9 commits into
tinkerbell:mainfrom
jacobweinstock:remote-default-template

Conversation

@jacobweinstock

@jacobweinstock jacobweinstock commented Apr 15, 2026

Copy link
Copy Markdown
Member

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 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.

2. Rename TemplateOverride to TemplateInline and add TemplateRef

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. CEL validation enforces mutual exclusivity of templateInline and templateRef.

3. Extract TinkerbellMachineConfig for template resource safety

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.

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 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. 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, and spec.imageLookupFormat are removed from TinkerbellClusterSpec and TinkerbellMachineSpec.
  • spec.templateOverride is renamed to spec.templateInline on both TinkerbellClusterSpec and TinkerbellMachineSpec.
  • TinkerbellMachineTemplateResource.Spec is now TinkerbellMachineConfig instead of TinkerbellMachineSpec — templates can no longer specify providerID or hardwareName.
  • The api/ directory is now a separate Go module. Consumers must import github.com/tinkerbell/cluster-api-provider-tinkerbell/api directly.

Fixes: #

How Has This Been Tested?

How are existing users impacted? What migration steps/scripts do we need?

Checklist:

I have:

  • updated the documentation and/or roadmap (if required)
  • added unit or e2e tests
  • provided instructions on how to upgrade

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>
@jacobweinstock jacobweinstock added kind/feature Categorizes issue or PR as related to a new feature. kind/breaking-change labels Apr 15, 2026
@jacobweinstock jacobweinstock changed the title Remote default template Remove default template Apr 15, 2026
@jacobweinstock jacobweinstock changed the title Remove default template Remove default template; Update API specs accordingly Apr 15, 2026
Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 templateOverridetemplateInline, add templateRef, and enforce mutual exclusivity via CEL validations/CRD schema updates.
  • Split api/ into a separate Go module and move webhook implementations to a top-level webhooks/ 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.

Comment thread controller/machine/template.go
Comment thread Makefile
Comment thread templates/cluster-template.yaml Outdated
Comment thread controller/machine/template.go Outdated
…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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread docs/UPGRADING-v0.6-to-v0.7.md
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())

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
return "", fmt.Errorf("%w: %s", ErrTemplateRefNoData, namespacedName.String())
return "", fmt.Errorf("%w: %s referenced by %s", ErrTemplateRefNoData, namespacedName.String(), source)

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +75 to +77
# 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.

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
# 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"

Copilot uses AI. Check for mistakes.
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>
@jacobweinstock jacobweinstock changed the title Remove default template; Update API specs accordingly v1beta2 Spec Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/breaking-change kind/feature Categorizes issue or PR as related to a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants