mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-30 18:42:58 +00:00
feat(vm): do not force VM re-create on initialization.user_account
changes (#1885)
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
51e6d7b8db
commit
d631ccbf90
@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/plancheck"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/utils"
|
||||
)
|
||||
@ -479,19 +480,6 @@ func TestAccResourceVMInitialization(t *testing.T) {
|
||||
overwrite_unmanaged = true
|
||||
}`),
|
||||
}}},
|
||||
{"native cloud-init: do not upgrade packages", []resource.TestStep{{
|
||||
Config: te.RenderConfig(`
|
||||
resource "proxmox_virtual_environment_vm" "test_vm_cloudinit3" {
|
||||
node_name = "{{.NodeName}}"
|
||||
started = false
|
||||
initialization {
|
||||
upgrade = false
|
||||
}
|
||||
}`),
|
||||
Check: ResourceAttributes("proxmox_virtual_environment_vm.test_vm_cloudinit3", map[string]string{
|
||||
"initialization.0.upgrade": "false",
|
||||
}),
|
||||
}}},
|
||||
{"native cloud-init: username should not change", []resource.TestStep{{
|
||||
Config: te.RenderConfig(`
|
||||
resource "proxmox_virtual_environment_vm" "test_vm_cloudinit4" {
|
||||
@ -547,6 +535,36 @@ func TestAccResourceVMInitialization(t *testing.T) {
|
||||
"initialization.0.user_account.0.password": `\*\*\*\*\*\*\*\*\*\*`,
|
||||
}),
|
||||
}}},
|
||||
{"native cloud-init: username update should not cause replacement", []resource.TestStep{{
|
||||
Config: te.RenderConfig(`
|
||||
resource "proxmox_virtual_environment_vm" "test_vm" {
|
||||
node_name = "{{.NodeName}}"
|
||||
started = false
|
||||
initialization {
|
||||
user_account {
|
||||
username = "ubuntu"
|
||||
password = "password"
|
||||
}
|
||||
}
|
||||
}`),
|
||||
}, {
|
||||
Config: te.RenderConfig(`
|
||||
resource "proxmox_virtual_environment_vm" "test_vm" {
|
||||
node_name = "{{.NodeName}}"
|
||||
started = false
|
||||
initialization {
|
||||
user_account {
|
||||
username = "ubuntu-updated"
|
||||
password = "password"
|
||||
}
|
||||
}
|
||||
}`),
|
||||
ConfigPlanChecks: resource.ConfigPlanChecks{
|
||||
PreApply: []plancheck.PlanCheck{
|
||||
plancheck.ExpectResourceAction("proxmox_virtual_environment_vm.test_vm", plancheck.ResourceActionUpdate),
|
||||
},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -290,6 +290,16 @@ func (c *Client) ListVMs(ctx context.Context) ([]*ListResponseData, error) {
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
// RebuildCloudInitDisk regenerates and changes cloud-init config drive.
|
||||
func (c *Client) RebuildCloudInitDisk(ctx context.Context) error {
|
||||
err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath("cloudinit"), nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error rebuilding cloud-init drive: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RebootVM reboots a virtual machine.
|
||||
func (c *Client) RebootVM(ctx context.Context, d *RebootRequestBody) error {
|
||||
taskID, err := c.RebootVMAsync(ctx, d)
|
||||
|
@ -843,7 +843,6 @@ func VM() *schema.Resource {
|
||||
Type: schema.TypeList,
|
||||
Description: "The user account configuration",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
DefaultFunc: func() (interface{}, error) {
|
||||
return []interface{}{}, nil
|
||||
},
|
||||
@ -853,14 +852,12 @@ func VM() *schema.Resource {
|
||||
Type: schema.TypeList,
|
||||
Description: "The SSH keys",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
mkInitializationUserAccountPassword: {
|
||||
Type: schema.TypeString,
|
||||
Description: "The SSH password",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Sensitive: true,
|
||||
Default: dvInitializationUserAccountPassword,
|
||||
DiffSuppressFunc: func(_, oldVal, _ string, _ *schema.ResourceData) bool {
|
||||
@ -872,7 +869,6 @@ func VM() *schema.Resource {
|
||||
Type: schema.TypeString,
|
||||
Description: "The SSH username",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -4786,7 +4782,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
if d.HasChange(mkNodeName) {
|
||||
migrateTimeoutSec := d.Get(mkTimeoutMigrate).(int)
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(migrateTimeoutSec)*time.Second)
|
||||
migrateCtx, cancel := context.WithTimeout(ctx, time.Duration(migrateTimeoutSec)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
oldNodeNameValue, _ := d.GetChange(mkNodeName)
|
||||
@ -4800,7 +4796,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
OnlineMigration: &trueValue,
|
||||
}
|
||||
|
||||
err := vmAPI.MigrateVM(ctx, migrateBody)
|
||||
err := vmAPI.MigrateVM(migrateCtx, migrateBody)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
@ -5113,11 +5109,12 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
|
||||
// Prepare the new cloud-init configuration.
|
||||
stoppedBeforeUpdate := false
|
||||
cloudInitRebuildRequired := false
|
||||
|
||||
if d.HasChange(mkInitialization) {
|
||||
initializationConfig := vmGetCloudInitConfig(d)
|
||||
cloudInitConfig := vmGetCloudInitConfig(d)
|
||||
|
||||
updateBody.CloudInitConfig = initializationConfig
|
||||
updateBody.CloudInitConfig = cloudInitConfig
|
||||
|
||||
initialization := d.Get(mkInitialization).([]interface{})
|
||||
|
||||
@ -5158,12 +5155,12 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
if mustMove || mustChangeDatastore || existingInterface == "" {
|
||||
// CloudInit must be moved, either from a device to another or from a datastore
|
||||
// to another (or both). This requires the VM to be stopped.
|
||||
if err := vmShutdown(ctx, vmAPI, d); err != nil {
|
||||
return err
|
||||
if er := vmShutdown(ctx, vmAPI, d); er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
if err := deleteIdeDrives(ctx, vmAPI, initializationInterface, existingInterface); err != nil {
|
||||
return err
|
||||
if er := deleteIdeDrives(ctx, vmAPI, initializationInterface, existingInterface); er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
stoppedBeforeUpdate = true
|
||||
@ -5179,6 +5176,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
})
|
||||
}
|
||||
|
||||
cloudInitRebuildRequired = true
|
||||
rebootRequired = true
|
||||
}
|
||||
|
||||
@ -5402,14 +5400,20 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
return diags
|
||||
}
|
||||
} else {
|
||||
if e := vmShutdown(ctx, vmAPI, d); e != nil {
|
||||
return e
|
||||
if er := vmShutdown(ctx, vmAPI, d); er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
rebootRequired = false
|
||||
}
|
||||
}
|
||||
|
||||
if cloudInitRebuildRequired {
|
||||
if er := vmAPI.RebuildCloudInitDisk(ctx); er != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Change the disk locations and/or sizes, if necessary.
|
||||
return vmUpdateDiskLocationAndSize(
|
||||
ctx,
|
||||
|
Loading…
Reference in New Issue
Block a user