diff --git a/builder/proxmox/clone/config.hcl2spec.go b/builder/proxmox/clone/config.hcl2spec.go index 5ada6d7c..f7a1dee3 100644 --- a/builder/proxmox/clone/config.hcl2spec.go +++ b/builder/proxmox/clone/config.hcl2spec.go @@ -106,6 +106,7 @@ type FlatConfig struct { DisableKVM *bool `mapstructure:"disable_kvm" cty:"disable_kvm" hcl:"disable_kvm"` TemplateName *string `mapstructure:"template_name" cty:"template_name" hcl:"template_name"` TemplateDescription *string `mapstructure:"template_description" cty:"template_description" hcl:"template_description"` + SkipConvertToTemplate *bool `mapstructure:"skip_convert_to_template" cty:"skip_convert_to_template" hcl:"skip_convert_to_template"` CloudInit *bool `mapstructure:"cloud_init" cty:"cloud_init" hcl:"cloud_init"` CloudInitStoragePool *string `mapstructure:"cloud_init_storage_pool" cty:"cloud_init_storage_pool" hcl:"cloud_init_storage_pool"` AdditionalISOFiles []proxmox.FlatadditionalISOsConfig `mapstructure:"additional_iso_files" cty:"additional_iso_files" hcl:"additional_iso_files"` @@ -221,6 +222,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "disable_kvm": &hcldec.AttrSpec{Name: "disable_kvm", Type: cty.Bool, Required: false}, "template_name": &hcldec.AttrSpec{Name: "template_name", Type: cty.String, Required: false}, "template_description": &hcldec.AttrSpec{Name: "template_description", Type: cty.String, Required: false}, + "skip_convert_to_template": &hcldec.AttrSpec{Name: "skip_convert_to_template", Type: cty.Bool, Required: false}, "cloud_init": &hcldec.AttrSpec{Name: "cloud_init", Type: cty.Bool, Required: false}, "cloud_init_storage_pool": &hcldec.AttrSpec{Name: "cloud_init_storage_pool", Type: cty.String, Required: false}, "additional_iso_files": &hcldec.BlockListSpec{TypeName: "additional_iso_files", Nested: hcldec.ObjectSpec((*proxmox.FlatadditionalISOsConfig)(nil).HCL2Spec())}, diff --git a/builder/proxmox/common/artifact.go b/builder/proxmox/common/artifact.go index fd8c5f1b..7ac60aa9 100644 --- a/builder/proxmox/common/artifact.go +++ b/builder/proxmox/common/artifact.go @@ -11,7 +11,8 @@ import ( type Artifact struct { builderID string - templateID int + vmID int + isTemplate bool proxmoxClient *proxmox.Client // StateData should store data such as GeneratedData @@ -31,11 +32,15 @@ func (*Artifact) Files() []string { } func (a *Artifact) Id() string { - return strconv.Itoa(a.templateID) + return strconv.Itoa(a.vmID) } func (a *Artifact) String() string { - return fmt.Sprintf("A template was created: %d", a.templateID) + + if a.isTemplate { + return fmt.Sprintf("A Template was created: %d", a.vmID) + } + return fmt.Sprintf("A VM was created: %d", a.vmID) } func (a *Artifact) State(name string) interface{} { @@ -43,7 +48,12 @@ func (a *Artifact) State(name string) interface{} { } func (a *Artifact) Destroy() error { - log.Printf("Destroying template: %d", a.templateID) - _, err := a.proxmoxClient.DeleteVm(proxmox.NewVmRef(a.templateID)) + + if a.isTemplate { + log.Printf("Destroying Template: %d", a.vmID) + } else { + log.Printf("Destroying VM: %d", a.vmID) + } + _, err := a.proxmoxClient.DeleteVm(proxmox.NewVmRef(a.vmID)) return err } diff --git a/builder/proxmox/common/builder.go b/builder/proxmox/common/builder.go index 13f24d99..512984fc 100644 --- a/builder/proxmox/common/builder.go +++ b/builder/proxmox/common/builder.go @@ -47,29 +47,31 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook, comm := &b.config.Comm - // Build the steps - coreSteps := []multistep.Step{ - &stepStartVM{ - vmCreator: b.vmCreator, - }, - commonsteps.HTTPServerFromHTTPConfig(&b.config.HTTPConfig), - &stepTypeBootCommand{ - BootConfig: b.config.BootConfig, - Ctx: b.config.Ctx, - }, - &communicator.StepConnect{ - Config: comm, - Host: commHost((*comm).Host()), - SSHConfig: (*comm).SSHConfigFunc(), - }, - &commonsteps.StepProvision{}, - &commonsteps.StepCleanupTempKeys{ - Comm: &b.config.Comm, - }, - &stepConvertToTemplate{}, - &stepFinalizeTemplateConfig{}, - &stepSuccess{}, - } + // Build the steps (Order matters) + coreSteps := []multistep.Step{} + + coreSteps = append(coreSteps, &stepStartVM{vmCreator: b.vmCreator}) + coreSteps = append(coreSteps, commonsteps.HTTPServerFromHTTPConfig(&b.config.HTTPConfig)) + coreSteps = append(coreSteps, &stepTypeBootCommand{ + BootConfig: b.config.BootConfig, + Ctx: b.config.Ctx, + }) + coreSteps = append(coreSteps, &communicator.StepConnect{ + Config: comm, + Host: commHost((*comm).Host()), + SSHConfig: (*comm).SSHConfigFunc(), + }) + coreSteps = append(coreSteps, &commonsteps.StepProvision{}) + coreSteps = append(coreSteps, &commonsteps.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }) + coreSteps = append(coreSteps, &stepStopVM{}) + + coreSteps = append(coreSteps, &stepConvertToTemplate{}) + + coreSteps = append(coreSteps, &stepFinalizeVMConfig{}) + coreSteps = append(coreSteps, &stepSuccess{}) + preSteps := b.preSteps for idx := range b.config.AdditionalISOFiles { preSteps = append(preSteps, &commonsteps.StepDownload{ @@ -97,15 +99,16 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook, return nil, errors.New("build was cancelled") } - // Verify that the template_id was set properly, otherwise we didn't progress through the last step - tplID, ok := state.Get("template_id").(int) + // Get vmRef for vmid in artifact storage + vmRef, ok := state.Get("vmRef").(*proxmox.VmRef) if !ok { - return nil, fmt.Errorf("template ID could not be determined") + return nil, fmt.Errorf("vmRef could not be determined") } artifact := &Artifact{ builderID: b.id, - templateID: tplID, + vmID: vmRef.VmId(), + isTemplate: !b.config.SkipConvertToTemplate.True(), proxmoxClient: b.proxmoxClient, StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, } diff --git a/builder/proxmox/common/config.go b/builder/proxmox/common/config.go index 0380a84e..ac57ebce 100644 --- a/builder/proxmox/common/config.go +++ b/builder/proxmox/common/config.go @@ -62,8 +62,9 @@ type Config struct { Onboot bool `mapstructure:"onboot"` DisableKVM bool `mapstructure:"disable_kvm"` - TemplateName string `mapstructure:"template_name"` - TemplateDescription string `mapstructure:"template_description"` + TemplateName string `mapstructure:"template_name"` + TemplateDescription string `mapstructure:"template_description"` + SkipConvertToTemplate config.Trilean `mapstructure:"skip_convert_to_template"` CloudInit bool `mapstructure:"cloud_init"` CloudInitStoragePool string `mapstructure:"cloud_init_storage_pool"` @@ -109,6 +110,7 @@ type vgaConfig struct { func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []string, error) { // Do not add a cloud-init cdrom by default c.CloudInit = false + var md mapstructure.Metadata err := config.Decode(upper, &config.DecodeOpts{ Metadata: &md, diff --git a/builder/proxmox/common/config.hcl2spec.go b/builder/proxmox/common/config.hcl2spec.go index 4e4b78b5..0b824c86 100644 --- a/builder/proxmox/common/config.hcl2spec.go +++ b/builder/proxmox/common/config.hcl2spec.go @@ -105,6 +105,7 @@ type FlatConfig struct { DisableKVM *bool `mapstructure:"disable_kvm" cty:"disable_kvm" hcl:"disable_kvm"` TemplateName *string `mapstructure:"template_name" cty:"template_name" hcl:"template_name"` TemplateDescription *string `mapstructure:"template_description" cty:"template_description" hcl:"template_description"` + SkipConvertToTemplate *bool `mapstructure:"skip_convert_to_template" cty:"skip_convert_to_template" hcl:"skip_convert_to_template"` CloudInit *bool `mapstructure:"cloud_init" cty:"cloud_init" hcl:"cloud_init"` CloudInitStoragePool *string `mapstructure:"cloud_init_storage_pool" cty:"cloud_init_storage_pool" hcl:"cloud_init_storage_pool"` AdditionalISOFiles []FlatadditionalISOsConfig `mapstructure:"additional_iso_files" cty:"additional_iso_files" hcl:"additional_iso_files"` @@ -218,6 +219,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "disable_kvm": &hcldec.AttrSpec{Name: "disable_kvm", Type: cty.Bool, Required: false}, "template_name": &hcldec.AttrSpec{Name: "template_name", Type: cty.String, Required: false}, "template_description": &hcldec.AttrSpec{Name: "template_description", Type: cty.String, Required: false}, + "skip_convert_to_template": &hcldec.AttrSpec{Name: "skip_convert_to_template", Type: cty.Bool, Required: false}, "cloud_init": &hcldec.AttrSpec{Name: "cloud_init", Type: cty.Bool, Required: false}, "cloud_init_storage_pool": &hcldec.AttrSpec{Name: "cloud_init_storage_pool", Type: cty.String, Required: false}, "additional_iso_files": &hcldec.BlockListSpec{TypeName: "additional_iso_files", Nested: hcldec.ObjectSpec((*FlatadditionalISOsConfig)(nil).HCL2Spec())}, diff --git a/builder/proxmox/common/step_convert_to_template.go b/builder/proxmox/common/step_convert_to_template.go index 9bdb7e2f..91ed7ce5 100644 --- a/builder/proxmox/common/step_convert_to_template.go +++ b/builder/proxmox/common/step_convert_to_template.go @@ -3,21 +3,17 @@ package proxmox import ( "context" "fmt" - "log" "github.com/Telmate/proxmox-api-go/proxmox" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) -// stepConvertToTemplate takes the running VM configured in earlier steps, stops it, and -// converts it into a Proxmox template. -// -// It sets the template_id state which is used for Artifact lookup. +// stepConvertToTemplate takes the stopped VM configured in earlier steps, +// and converts it into a Proxmox VM template. type stepConvertToTemplate struct{} type templateConverter interface { - ShutdownVm(*proxmox.VmRef) (string, error) CreateTemplate(*proxmox.VmRef) error } @@ -27,26 +23,22 @@ func (s *stepConvertToTemplate) Run(ctx context.Context, state multistep.StateBa ui := state.Get("ui").(packersdk.Ui) client := state.Get("proxmoxClient").(templateConverter) vmRef := state.Get("vmRef").(*proxmox.VmRef) + c := state.Get("config").(*Config) - ui.Say("Stopping VM") - _, err := client.ShutdownVm(vmRef) - if err != nil { - err := fmt.Errorf("Error converting VM to template, could not stop: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } + if !c.SkipConvertToTemplate.True() { + + ui.Say("Converting VM to template") + var err = client.CreateTemplate(vmRef) + if err != nil { + err := fmt.Errorf("error converting VM to template: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } - ui.Say("Converting VM to template") - err = client.CreateTemplate(vmRef) - if err != nil { - err := fmt.Errorf("Error converting VM to template: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt + } else { + ui.Say("Skipping VM template conversion") } - log.Printf("template_id: %d", vmRef.VmId()) - state.Put("template_id", vmRef.VmId()) return multistep.ActionContinue } diff --git a/builder/proxmox/common/step_convert_to_template_test.go b/builder/proxmox/common/step_convert_to_template_test.go index a1026296..138f6dc9 100644 --- a/builder/proxmox/common/step_convert_to_template_test.go +++ b/builder/proxmox/common/step_convert_to_template_test.go @@ -8,16 +8,13 @@ import ( "github.com/Telmate/proxmox-api-go/proxmox" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer-plugin-sdk/template/config" ) type converterMock struct { - shutdownVm func(*proxmox.VmRef) (string, error) createTemplate func(*proxmox.VmRef) error } -func (m converterMock) ShutdownVm(r *proxmox.VmRef) (string, error) { - return m.shutdownVm(r) -} func (m converterMock) CreateTemplate(r *proxmox.VmRef) error { return m.createTemplate(r) } @@ -27,46 +24,54 @@ var _ templateConverter = converterMock{} func TestConvertToTemplate(t *testing.T) { cs := []struct { name string - shutdownErr error expectCallCreateTemplate bool createTemplateErr error expectedAction multistep.StepAction - expectTemplateIdSet bool + builderConfig *Config }{ { - name: "no errors returns continue and sets template id", + name: "NoErrorsUnset", expectCallCreateTemplate: true, + createTemplateErr: nil, expectedAction: multistep.ActionContinue, - expectTemplateIdSet: true, + builderConfig: &Config{}, }, { - name: "when shutdown fails, don't try to create template and halt", - shutdownErr: fmt.Errorf("failed to stop vm"), - expectCallCreateTemplate: false, - expectedAction: multistep.ActionHalt, - expectTemplateIdSet: false, + name: "NoErrors", + expectCallCreateTemplate: true, + createTemplateErr: nil, + expectedAction: multistep.ActionContinue, + builderConfig: &Config{ + SkipConvertToTemplate: config.TriFalse, + }, }, { - name: "when create template fails, halt", + name: "RaiseConvertTemplateError", expectCallCreateTemplate: true, - createTemplateErr: fmt.Errorf("failed to stop vm"), + createTemplateErr: fmt.Errorf("failed to convert vm to template"), expectedAction: multistep.ActionHalt, - expectTemplateIdSet: false, + builderConfig: &Config{ + SkipConvertToTemplate: config.TriFalse, + }, + }, + { + name: "SkipConvertToTemplate", + expectCallCreateTemplate: false, + createTemplateErr: nil, + expectedAction: multistep.ActionContinue, + builderConfig: &Config{ + SkipConvertToTemplate: config.TriTrue, + }, }, } - const vmid = 123 + const vmid = 1 for _, c := range cs { t.Run(c.name, func(t *testing.T) { converter := converterMock{ - shutdownVm: func(r *proxmox.VmRef) (string, error) { - if r.VmId() != vmid { - t.Errorf("ShutdownVm called with unexpected id, expected %d, got %d", vmid, r.VmId()) - } - return "", c.shutdownErr - }, createTemplate: func(r *proxmox.VmRef) error { + if r.VmId() != vmid { t.Errorf("CreateTemplate called with unexpected id, expected %d, got %d", vmid, r.VmId()) } @@ -82,6 +87,7 @@ func TestConvertToTemplate(t *testing.T) { state.Put("ui", packersdk.TestUi(t)) state.Put("vmRef", proxmox.NewVmRef(vmid)) state.Put("proxmoxClient", converter) + state.Put("config", c.builderConfig) step := stepConvertToTemplate{} action := step.Run(context.TODO(), state) @@ -89,15 +95,6 @@ func TestConvertToTemplate(t *testing.T) { t.Errorf("Expected action to be %v, got %v", c.expectedAction, action) } - id, wasSet := state.GetOk("template_id") - - if c.expectTemplateIdSet != wasSet { - t.Errorf("Expected template_id state present=%v was present=%v", c.expectTemplateIdSet, wasSet) - } - - if c.expectTemplateIdSet && id != vmid { - t.Errorf("Expected template_id state to be set to %d, got %v", vmid, id) - } }) } } diff --git a/builder/proxmox/common/step_finalize_template_config.go b/builder/proxmox/common/step_finalize_vm_config.go similarity index 91% rename from builder/proxmox/common/step_finalize_template_config.go rename to builder/proxmox/common/step_finalize_vm_config.go index abf6b000..3c0949b1 100644 --- a/builder/proxmox/common/step_finalize_template_config.go +++ b/builder/proxmox/common/step_finalize_vm_config.go @@ -10,10 +10,10 @@ import ( packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) -// stepFinalizeTemplateConfig does any required modifications to the configuration _after_ +// stepFinalizeVMConfig does any required modifications to the configuration _after_ // the VM has been converted into a template, such as updating name and description, or // unmounting the installation ISO. -type stepFinalizeTemplateConfig struct{} +type stepFinalizeVMConfig struct{} type templateFinalizer interface { GetVmConfig(*proxmox.VmRef) (map[string]interface{}, error) @@ -22,7 +22,7 @@ type templateFinalizer interface { var _ templateFinalizer = &proxmox.Client{} -func (s *stepFinalizeTemplateConfig) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { +func (s *stepFinalizeVMConfig) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packersdk.Ui) client := state.Get("proxmoxClient").(templateFinalizer) c := state.Get("config").(*Config) @@ -118,4 +118,4 @@ func (s *stepFinalizeTemplateConfig) Run(ctx context.Context, state multistep.St return multistep.ActionContinue } -func (s *stepFinalizeTemplateConfig) Cleanup(state multistep.StateBag) {} +func (s *stepFinalizeVMConfig) Cleanup(state multistep.StateBag) {} diff --git a/builder/proxmox/common/step_finalize_template_config_test.go b/builder/proxmox/common/step_finalize_vm_config_test.go similarity index 99% rename from builder/proxmox/common/step_finalize_template_config_test.go rename to builder/proxmox/common/step_finalize_vm_config_test.go index 0f00bce6..eb5bd209 100644 --- a/builder/proxmox/common/step_finalize_template_config_test.go +++ b/builder/proxmox/common/step_finalize_vm_config_test.go @@ -191,7 +191,7 @@ func TestTemplateFinalize(t *testing.T) { state.Put("vmRef", proxmox.NewVmRef(1)) state.Put("proxmoxClient", finalizer) - step := stepFinalizeTemplateConfig{} + step := stepFinalizeVMConfig{} action := step.Run(context.TODO(), state) if action != c.expectedAction { t.Errorf("Expected action to be %v, got %v", c.expectedAction, action) diff --git a/builder/proxmox/common/step_stop_vm.go b/builder/proxmox/common/step_stop_vm.go new file mode 100644 index 00000000..6d717d7b --- /dev/null +++ b/builder/proxmox/common/step_stop_vm.go @@ -0,0 +1,39 @@ +package proxmox + +import ( + "context" + "fmt" + + "github.com/Telmate/proxmox-api-go/proxmox" + "github.com/hashicorp/packer-plugin-sdk/multistep" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" +) + +// stepStopVM takes the running VM configured in earlier steps and stops it. + +type stepStopVM struct{} + +type vmTerminator interface { + ShutdownVm(*proxmox.VmRef) (string, error) +} + +var _ templateConverter = &proxmox.Client{} + +func (s *stepStopVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packersdk.Ui) + client := state.Get("proxmoxClient").(vmTerminator) + vmRef := state.Get("vmRef").(*proxmox.VmRef) + + ui.Say("Stopping VM") + _, err := client.ShutdownVm(vmRef) + if err != nil { + err := fmt.Errorf("Error converting VM to template, could not stop: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *stepStopVM) Cleanup(state multistep.StateBag) {} diff --git a/builder/proxmox/common/step_stop_vm_test.go b/builder/proxmox/common/step_stop_vm_test.go new file mode 100644 index 00000000..13fb24a5 --- /dev/null +++ b/builder/proxmox/common/step_stop_vm_test.go @@ -0,0 +1,71 @@ +package proxmox + +import ( + "context" + "fmt" + "testing" + + "github.com/Telmate/proxmox-api-go/proxmox" + "github.com/hashicorp/packer-plugin-sdk/multistep" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" +) + +type vmTerminatorMock struct { + shutdownVm func(*proxmox.VmRef) (string, error) +} + +func (m vmTerminatorMock) ShutdownVm(r *proxmox.VmRef) (string, error) { + return m.shutdownVm(r) +} + +var _ vmTerminator = vmTerminatorMock{} + +func TestStopVM(t *testing.T) { + cs := []struct { + name string + shutdownErr error + expectCallShutdownVm bool + expectedAction multistep.StepAction + }{ + { + name: "NoError", + expectCallShutdownVm: true, + expectedAction: multistep.ActionContinue, + }, + { + name: "RaiseShutdownVMError", + expectCallShutdownVm: true, + shutdownErr: fmt.Errorf("failed to stop vm"), + expectedAction: multistep.ActionHalt, + }, + } + + const vmid = 123 + + for _, c := range cs { + t.Run(c.name, func(t *testing.T) { + terminator := vmTerminatorMock{ + shutdownVm: func(r *proxmox.VmRef) (string, error) { + if r.VmId() != vmid { + t.Errorf("ShutdownVm called with unexpected id, expected %d, got %d", vmid, r.VmId()) + } + if !c.expectCallShutdownVm { + t.Error("Did not expect ShutdownVM to be called") + } + return "", c.shutdownErr + }, + } + + state := new(multistep.BasicStateBag) + state.Put("ui", packersdk.TestUi(t)) + state.Put("vmRef", proxmox.NewVmRef(vmid)) + state.Put("proxmoxClient", terminator) + + step := stepStopVM{} + action := step.Run(context.TODO(), state) + if action != c.expectedAction { + t.Errorf("Expected action to be %v, got %v", c.expectedAction, action) + } + }) + } +} diff --git a/builder/proxmox/iso/config.hcl2spec.go b/builder/proxmox/iso/config.hcl2spec.go index b7797d64..07ea8013 100644 --- a/builder/proxmox/iso/config.hcl2spec.go +++ b/builder/proxmox/iso/config.hcl2spec.go @@ -106,6 +106,7 @@ type FlatConfig struct { DisableKVM *bool `mapstructure:"disable_kvm" cty:"disable_kvm" hcl:"disable_kvm"` TemplateName *string `mapstructure:"template_name" cty:"template_name" hcl:"template_name"` TemplateDescription *string `mapstructure:"template_description" cty:"template_description" hcl:"template_description"` + SkipConvertToTemplate *bool `mapstructure:"skip_convert_to_template" cty:"skip_convert_to_template" hcl:"skip_convert_to_template"` CloudInit *bool `mapstructure:"cloud_init" cty:"cloud_init" hcl:"cloud_init"` CloudInitStoragePool *string `mapstructure:"cloud_init_storage_pool" cty:"cloud_init_storage_pool" hcl:"cloud_init_storage_pool"` AdditionalISOFiles []proxmox.FlatadditionalISOsConfig `mapstructure:"additional_iso_files" cty:"additional_iso_files" hcl:"additional_iso_files"` @@ -227,6 +228,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "disable_kvm": &hcldec.AttrSpec{Name: "disable_kvm", Type: cty.Bool, Required: false}, "template_name": &hcldec.AttrSpec{Name: "template_name", Type: cty.String, Required: false}, "template_description": &hcldec.AttrSpec{Name: "template_description", Type: cty.String, Required: false}, + "skip_convert_to_template": &hcldec.AttrSpec{Name: "skip_convert_to_template", Type: cty.Bool, Required: false}, "cloud_init": &hcldec.AttrSpec{Name: "cloud_init", Type: cty.Bool, Required: false}, "cloud_init_storage_pool": &hcldec.AttrSpec{Name: "cloud_init_storage_pool", Type: cty.String, Required: false}, "additional_iso_files": &hcldec.BlockListSpec{TypeName: "additional_iso_files", Nested: hcldec.ObjectSpec((*proxmox.FlatadditionalISOsConfig)(nil).HCL2Spec())}, diff --git a/builder/proxmox/iso/config_test.go b/builder/proxmox/iso/config_test.go index 94fe2788..740d7ae1 100644 --- a/builder/proxmox/iso/config_test.go +++ b/builder/proxmox/iso/config_test.go @@ -42,11 +42,12 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { "ssh_username": "root", "ssh_timeout": "15m", "ssh_password": "packer", - + "unmount_iso": true, "template_name": "fedora-29", - "template_description": "Fedora 29-1.2, generated on {{ isotime \"2006-01-02T15:04:05Z\" }}" - } + "template_description": "Fedora 29-1.2, generated on {{ isotime \"2006-01-02T15:04:05Z\" }}", + "skip_convert_to_template": true + } ] }` tpl, err := template.Parse(strings.NewReader(config)) @@ -109,6 +110,9 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { if b.config.CloudInit != false { t.Errorf("Expected CloudInit to be false, got %t", b.config.CloudInit) } + if b.config.SkipConvertToTemplate.False() { + t.Errorf("Expected ConvertToTemplate to be true, got %t", b.config.SkipConvertToTemplate.True()) + } } func TestAgentSetToFalse(t *testing.T) { diff --git a/docs-partials/builder/proxmox/common/Config-not-required.mdx b/docs-partials/builder/proxmox/common/Config-not-required.mdx index df171186..4fdc97d9 100644 --- a/docs-partials/builder/proxmox/common/Config-not-required.mdx +++ b/docs-partials/builder/proxmox/common/Config-not-required.mdx @@ -58,6 +58,8 @@ - `template_description` (string) - Template Description +- `skip_convert_to_template` (bool) - Skips VM template conversion. + - `cloud_init` (bool) - Cloud Init - `cloud_init_storage_pool` (string) - Cloud Init Storage Pool diff --git a/docs/builders/clone.mdx b/docs/builders/clone.mdx index c17d2eaf..e89f8ba1 100644 --- a/docs/builders/clone.mdx +++ b/docs/builders/clone.mdx @@ -3,7 +3,7 @@ description: | The proxmox image Packer builder is able to create new images for use with Proxmox VE. The builder takes a cloud-init enabled virtual machine template name, runs any provisioning necessary on the image after - launching it, then creates a virtual machine template. + launching it, and creates a virtual machine or virtual machine template. page_title: Proxmox Clone - Builders sidebar_title: proxmox-clone nav_title: Clone @@ -17,17 +17,15 @@ Artifact BuilderId: `proxmox.clone` The `proxmox-clone` Packer builder is able to create new images for use with [Proxmox](https://www.proxmox.com/en/proxmox-ve). The builder takes a virtual machine template, runs any provisioning necessary on the image after launching it, -then creates a virtual machine template. This template can then be used as to -create new virtual machines within Proxmox. +and creates a virtual machine or virtual machine template. -The builder does _not_ manage templates. Once it creates a template, it is up +The builder does _not_ manage templates. It only creates a VM or VM template, it is up to you to use it or delete it. ## Configuration Reference There are many configuration options available for the builder. They are -segmented below into two categories: required and optional parameters. Within -each category, the available configuration keys are alphabetized. +segmented below into two categories: required and optional parameters. In addition to the options listed here, a [communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this @@ -194,6 +192,8 @@ in the image's Cloud-Init settings for provisioning. - `template_description` (string) - Description of the template, visible in the Proxmox interface. +- `skip_convert_to_template` (bool) - Skips VM template conversion. Defaults to `false`. + - `onboot` (boolean) - Specifies whether a VM will be started during system bootup. Defaults to `false`. diff --git a/docs/builders/index.mdx b/docs/builders/index.mdx index f499ed73..ccb96cb5 100644 --- a/docs/builders/index.mdx +++ b/docs/builders/index.mdx @@ -17,10 +17,10 @@ Packer is able to target both ISO and existing Cloud-Init images: - [proxmox-clone](/docs/builders/proxmox/clone) - The proxmox image Packer builder is able to create new images for use with Proxmox VE. The builder takes a cloud-init enabled virtual machine template name, runs any - provisioning necessary on the image after launching it, then creates a virtual - machine template. + provisioning necessary on the image after launching it, and creates a virtual + machine or virtual machine template. - [proxmox-iso](/docs/builders/proxmox/iso) - The proxmox Packer builder is able to create new images for use with Proxmox VE. The builder takes an ISO source, runs any provisioning necessary on the image after - launching it, then creates a virtual machine template. + launching it, and creates a virtual machine or virtual machine template. diff --git a/docs/builders/iso.mdx b/docs/builders/iso.mdx index 4d9c8989..7ad6ff69 100644 --- a/docs/builders/iso.mdx +++ b/docs/builders/iso.mdx @@ -2,8 +2,7 @@ description: | The proxmox Packer builder is able to create new images for use with Proxmox VE. The builder takes an ISO source, runs any provisioning - necessary on the image after launching it, then creates a virtual machine - template. + necessary on the image after launching it, and creates a virtual machine or virtual machine template. page_title: Proxmox ISO - Builders sidebar_title: proxmox-iso nav_title: ISO @@ -16,18 +15,16 @@ Artifact BuilderId: `proxmox.iso` The `proxmox-iso` Packer builder is able to create new images for use with [Proxmox](https://www.proxmox.com/en/proxmox-ve). The builder takes an ISO -image, runs any provisioning necessary on the image after launching it, then -creates a virtual machine template. This template can then be used as to -create new virtual machines within Proxmox. +image, runs any provisioning necessary on the image after launching it, and +creates a virtual machine or virtual machine template. -The builder does _not_ manage templates. Once it creates a template, it is up +The builder does _not_ manage templates. It only creates a VM or VM template, it is up to you to use it or delete it. ## Configuration Reference There are many configuration options available for the builder. They are -segmented below into two categories: required and optional parameters. Within -each category, the available configuration keys are alphabetized. +segmented below into two categories: required and optional parameters. In addition to the options listed here, a [communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this @@ -208,6 +205,8 @@ builder. - `template_description` (string) - Description of the template, visible in the Proxmox interface. +- `skip_convert_to_template` (bool) - Skips VM template conversion. Defaults to `false`. + - `unmount_iso` (bool) - If true, remove the mounted ISO from the template after finishing. Defaults to `false`.