Skip to content

Commit bbb5334

Browse files
committed
Wrap selecting boot config function
1 parent 7cf1f06 commit bbb5334

File tree

2 files changed

+133
-19
lines changed

2 files changed

+133
-19
lines changed

builder/linode/step_create_disk_config.go

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,32 @@ func flattenInstanceConfig(cfg InstanceConfig, diskLabelToID map[string]int) (li
225225
return opts, nil
226226
}
227227

228+
// selectBootConfig determines which configuration profile should be booted.
229+
// Returns the index of the config to boot, or an error if multiple configs have booted=true.
230+
// If no configs have booted=true, returns 0 (first config).
231+
// If one config has booted=true, returns its index.
232+
func selectBootConfig(configs []InstanceConfig) (int, error) {
233+
bootedCount := 0
234+
bootedIndex := -1
235+
236+
for i, cfg := range configs {
237+
if cfg.Booted {
238+
bootedCount++
239+
bootedIndex = i
240+
}
241+
}
242+
243+
if bootedCount > 1 {
244+
return 0, errors.New("only one configuration profile can have 'booted' set to true")
245+
}
246+
247+
if bootedIndex >= 0 {
248+
return bootedIndex, nil
249+
}
250+
251+
return 0, nil
252+
}
253+
228254
func (s *stepCreateDiskConfig) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
229255
c := state.Get("config").(*Config)
230256
ui := state.Get("ui").(packersdk.Ui)
@@ -288,25 +314,10 @@ func (s *stepCreateDiskConfig) Run(ctx context.Context, state multistep.StateBag
288314
// Store disk map in state for other steps
289315
state.Put("disk_label_to_id", diskLabelToID)
290316

291-
// Validate that only one config has booted=true
292-
bootedCount := 0
293-
bootedIndex := -1
294-
for i, cfgProfile := range c.InstanceConfigs {
295-
if cfgProfile.Booted {
296-
bootedCount++
297-
bootedIndex = i
298-
}
299-
}
300-
301-
if bootedCount > 1 {
302-
return handleError("Multiple configuration profiles marked as booted",
303-
errors.New("only one configuration profile can have 'booted' set to true"))
304-
}
305-
306-
// Determine which config to boot: the one marked as booted, or the first one
307-
bootConfigIndex := 0
308-
if bootedIndex >= 0 {
309-
bootConfigIndex = bootedIndex
317+
// Determine which config to boot
318+
bootConfigIndex, err := selectBootConfig(c.InstanceConfigs)
319+
if err != nil {
320+
return handleError("Multiple configuration profiles marked as booted", err)
310321
}
311322

312323
// Create configuration profiles and track the boot config ID

builder/linode/step_create_disk_config_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,106 @@ func TestFlattenInstanceConfig(t *testing.T) {
440440
})
441441
}
442442
}
443+
444+
// TestSelectBootConfig tests the boot configuration selection logic
445+
func TestSelectBootConfig(t *testing.T) {
446+
tests := []struct {
447+
name string
448+
configs []InstanceConfig
449+
wantIndex int
450+
wantError bool
451+
wantErrorContains string
452+
}{
453+
{
454+
name: "Multiple configs with booted=true should error",
455+
configs: []InstanceConfig{
456+
{Label: "config1", Booted: true},
457+
{Label: "config2", Booted: true},
458+
},
459+
wantError: true,
460+
wantErrorContains: "only one configuration profile can have 'booted' set to true",
461+
},
462+
{
463+
name: "Single config with booted=true should use that config",
464+
configs: []InstanceConfig{
465+
{Label: "config1", Booted: false},
466+
{Label: "config2", Booted: true},
467+
{Label: "config3", Booted: false},
468+
},
469+
wantIndex: 1,
470+
wantError: false,
471+
},
472+
{
473+
name: "No configs with booted=true should default to first config",
474+
configs: []InstanceConfig{
475+
{Label: "config1", Booted: false},
476+
{Label: "config2", Booted: false},
477+
},
478+
wantIndex: 0,
479+
wantError: false,
480+
},
481+
{
482+
name: "Single config not marked as booted should use that config",
483+
configs: []InstanceConfig{
484+
{Label: "config1", Booted: false},
485+
},
486+
wantIndex: 0,
487+
wantError: false,
488+
},
489+
{
490+
name: "First config marked as booted should return index 0",
491+
configs: []InstanceConfig{
492+
{Label: "config1", Booted: true},
493+
{Label: "config2", Booted: false},
494+
},
495+
wantIndex: 0,
496+
wantError: false,
497+
},
498+
{
499+
name: "Last config marked as booted should return its index",
500+
configs: []InstanceConfig{
501+
{Label: "config1", Booted: false},
502+
{Label: "config2", Booted: false},
503+
{Label: "config3", Booted: true},
504+
},
505+
wantIndex: 2,
506+
wantError: false,
507+
},
508+
{
509+
name: "Three configs with first one booted",
510+
configs: []InstanceConfig{
511+
{Label: "config1", Booted: true},
512+
{Label: "config2", Booted: false},
513+
{Label: "config3", Booted: false},
514+
},
515+
wantIndex: 0,
516+
wantError: false,
517+
},
518+
}
519+
520+
for _, tt := range tests {
521+
t.Run(tt.name, func(t *testing.T) {
522+
gotIndex, err := selectBootConfig(tt.configs)
523+
524+
if tt.wantError {
525+
if err == nil {
526+
t.Errorf("selectBootConfig() expected error but got none")
527+
return
528+
}
529+
if tt.wantErrorContains != "" && !strings.Contains(err.Error(), tt.wantErrorContains) {
530+
t.Errorf("selectBootConfig() error = %v, want error containing %q", err, tt.wantErrorContains)
531+
}
532+
return
533+
}
534+
535+
if err != nil {
536+
t.Errorf("selectBootConfig() unexpected error: %v", err)
537+
return
538+
}
539+
540+
if gotIndex != tt.wantIndex {
541+
t.Errorf("selectBootConfig() = %d, want %d (config: %q)", gotIndex, tt.wantIndex, tt.configs[tt.wantIndex].Label)
542+
}
543+
})
544+
}
545+
}

0 commit comments

Comments
 (0)