@@ -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+
215257func firstPartitionFromDevice (device string ) string {
216258 nvmeDevice := regexp .MustCompile (`^/dev/nvme\d+n\d+$` )
217259 emmcDevice := regexp .MustCompile (`^/dev/mmcblk\d+$` )
0 commit comments