Skip to content

Commit 1a98f5d

Browse files
authored
determine pre-existing Template to use via hardware.tinkerbell.org/capt-template-override annotation (#510)
- Simple detour, but cyclops forced a bit of a refactor - logic: - TBMachineTemplate with no templateOverride - Hardware with `hardware.tinkerbell.org/capt-template-override` annotation - annot value is looked up as name of Template in same namespace as Hardware - template's spec.data used as CAPT's template for that Machine Signed-off-by: Ricardo Pardini <[email protected]>
2 parents d3b12c9 + 4423675 commit 1a98f5d

File tree

2 files changed

+67
-22
lines changed

2 files changed

+67
-22
lines changed

controller/machine/hardware.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const (
2727

2828
// HardwareProvisionedAnnotation signifies that the Hardware with this annotation has be provisioned by CAPT.
2929
HardwareProvisionedAnnotation = "v1alpha1.tinkerbell.org/provisioned"
30+
31+
// HardwareTemplateOverrideAnnotation can be used to override the default Template used for provisioning.
32+
HardwareTemplateOverrideAnnotation = "hardware.tinkerbell.org/capt-template-override"
3033
)
3134

3235
var (

controller/machine/template.go

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -158,33 +158,22 @@ func (scope *machineReconcileScope) createTemplate(hw *tinkv1.Hardware) error {
158158

159159
templateData := scope.tinkerbellMachine.Spec.TemplateOverride
160160
if templateData == "" {
161-
targetDisk := hw.Spec.Disks[0].Device
162-
targetDevice := firstPartitionFromDevice(targetDisk)
163-
164-
imageURL, err := scope.imageURL()
161+
scope.log.Info("tinkerbellMachine.Spec.TemplateOverride is empty, trying from hardware annotation")
162+
tmplFromAnnotation, err := scope.templateFromAnnotation(hw)
165163
if err != nil {
166-
return fmt.Errorf("failed to generate imageURL: %w", err)
167-
}
168-
169-
metadataIP := os.Getenv("TINKERBELL_IP")
170-
if metadataIP == "" {
171-
metadataIP = "192.168.1.1"
172-
}
173-
174-
metadataURL := fmt.Sprintf("http://%s:50061", metadataIP)
175-
176-
workflowTemplate := WorkflowTemplate{
177-
Name: scope.tinkerbellMachine.Name,
178-
MetadataURL: metadataURL,
179-
ImageURL: imageURL,
180-
DestDisk: targetDisk,
181-
DestPartition: targetDevice,
164+
return fmt.Errorf("failed to get template from hardware annotation: %w", err)
182165
}
166+
templateData = tmplFromAnnotation
167+
}
183168

184-
templateData, err = workflowTemplate.Render()
169+
// If still no template, generate the default one.
170+
if templateData == "" {
171+
scope.log.Info("no template found in hardware annotation, generating default template")
172+
defaultTemplate, err := scope.generateDefaultTemplate(hw)
185173
if err != nil {
186-
return fmt.Errorf("rendering template: %w", err)
174+
return err
187175
}
176+
templateData = defaultTemplate
188177
}
189178

190179
templateObject := &tinkv1.Template{
@@ -212,6 +201,59 @@ func (scope *machineReconcileScope) createTemplate(hw *tinkv1.Hardware) error {
212201
return nil
213202
}
214203

204+
func (scope *machineReconcileScope) generateDefaultTemplate(hw *tinkv1.Hardware) (string, error) {
205+
targetDisk := hw.Spec.Disks[0].Device
206+
targetDevice := firstPartitionFromDevice(targetDisk)
207+
208+
imageURL, err := scope.imageURL()
209+
if err != nil {
210+
return "", fmt.Errorf("failed to generate imageURL: %w", err)
211+
}
212+
213+
metadataIP := os.Getenv("TINKERBELL_IP")
214+
if metadataIP == "" {
215+
metadataIP = "192.168.1.1"
216+
}
217+
218+
metadataURL := fmt.Sprintf("http://%s:50061", metadataIP)
219+
220+
workflowTemplate := WorkflowTemplate{
221+
Name: scope.tinkerbellMachine.Name,
222+
MetadataURL: metadataURL,
223+
ImageURL: imageURL,
224+
DestDisk: targetDisk,
225+
DestPartition: targetDevice,
226+
}
227+
228+
templateData, err := workflowTemplate.Render()
229+
if err != nil {
230+
return "", fmt.Errorf("rendering template: %w", err)
231+
}
232+
return templateData, nil
233+
}
234+
235+
func (scope *machineReconcileScope) templateFromAnnotation(hw *tinkv1.Hardware) (string, error) {
236+
templateData := ""
237+
// Check if hardware has an annotation 'hardware.tinkerbell.org/capt-template-override', if so,
238+
// use it as the name of a Template resource in the same namespace as the Hardware, load it,
239+
// and use it's spec.data as the template.
240+
scope.log.Info("hardware annotations", "annotations", hw.Annotations)
241+
if templateName, ok := hw.Annotations[HardwareTemplateOverrideAnnotation]; ok {
242+
scope.log.Info("found template override in Hardware annotation", "templateName", templateName, "namespace", hw.Namespace)
243+
overrideTemplate := &tinkv1.Template{}
244+
namespacedName := types.NamespacedName{
245+
Name: templateName,
246+
Namespace: hw.Namespace,
247+
}
248+
if err := scope.client.Get(scope.ctx, namespacedName, overrideTemplate); err != nil {
249+
return "", fmt.Errorf("failed to get Template %q specified in hardware annotation: %w", templateName, err)
250+
}
251+
scope.log.V(4).Info("found template override in Hardware annotations, using it as template", "templateName", templateName)
252+
templateData = *overrideTemplate.Spec.Data
253+
}
254+
return templateData, nil
255+
}
256+
215257
func firstPartitionFromDevice(device string) string {
216258
nvmeDevice := regexp.MustCompile(`^/dev/nvme\d+n\d+$`)
217259
emmcDevice := regexp.MustCompile(`^/dev/mmcblk\d+$`)

0 commit comments

Comments
 (0)