mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-30 10:33:46 +00:00
feat(vm): add support for protection
attribute (#1126)
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
014b59e04f
commit
cea65a8a12
@ -447,10 +447,9 @@ output "ubuntu_vm_public_key" {
|
||||
- `win11` - Windows 11
|
||||
- `wvista` - Windows Vista.
|
||||
- `wxp` - Windows XP.
|
||||
- `pool_id` - (Optional) The identifier for a pool to assign the virtual machine
|
||||
to.
|
||||
- `reboot` - (Optional) Reboot the VM after initial creation. (defaults
|
||||
to `false`)
|
||||
- `pool_id` - (Optional) The identifier for a pool to assign the virtual machine to.
|
||||
- `protection` - (Optional) Sets the protection flag of the VM. This will disable the remove VM and remove disk operations (defaults to `false`).
|
||||
- `reboot` - (Optional) Reboot the VM after initial creation. (defaults to `false`)
|
||||
- `serial_device` - (Optional) A serial device (multiple blocks supported).
|
||||
- `device` - (Optional) The device (defaults to `socket`).
|
||||
- `/dev/*` - A host serial device.
|
||||
|
@ -20,9 +20,9 @@ func TestAccResourceVM(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
step resource.TestStep
|
||||
step []resource.TestStep
|
||||
}{
|
||||
{"multiline description", resource.TestStep{
|
||||
{"multiline description", []resource.TestStep{{
|
||||
Config: providerConfig + `
|
||||
resource "proxmox_virtual_environment_vm" "test_vm1" {
|
||||
node_name = "pve"
|
||||
@ -37,8 +37,8 @@ func TestAccResourceVM(t *testing.T) {
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm.test_vm1", "description", "my\ndescription\nvalue"),
|
||||
),
|
||||
}},
|
||||
{"single line description", resource.TestStep{
|
||||
}}},
|
||||
{"single line description", []resource.TestStep{{
|
||||
Config: providerConfig + `
|
||||
resource "proxmox_virtual_environment_vm" "test_vm2" {
|
||||
node_name = "pve"
|
||||
@ -49,8 +49,8 @@ func TestAccResourceVM(t *testing.T) {
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm.test_vm2", "description", "my description value"),
|
||||
),
|
||||
}},
|
||||
{"no description", resource.TestStep{
|
||||
}}},
|
||||
{"no description", []resource.TestStep{{
|
||||
Config: `
|
||||
resource "proxmox_virtual_environment_vm" "test_vm3" {
|
||||
node_name = "pve"
|
||||
@ -61,7 +61,32 @@ func TestAccResourceVM(t *testing.T) {
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm.test_vm3", "description", ""),
|
||||
),
|
||||
}}},
|
||||
{
|
||||
"protection", []resource.TestStep{{
|
||||
Config: `
|
||||
resource "proxmox_virtual_environment_vm" "test_vm4" {
|
||||
node_name = "pve"
|
||||
started = false
|
||||
|
||||
protection = true
|
||||
}`,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm.test_vm4", "protection", "true"),
|
||||
),
|
||||
}, {
|
||||
Config: `
|
||||
resource "proxmox_virtual_environment_vm" "test_vm4" {
|
||||
node_name = "pve"
|
||||
started = false
|
||||
|
||||
protection = false
|
||||
}`,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm.test_vm4", "protection", "false"),
|
||||
),
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
accProviders := testAccMuxProviders(context.Background(), t)
|
||||
@ -73,7 +98,7 @@ func TestAccResourceVM(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: accProviders,
|
||||
Steps: []resource.TestStep{tt.step},
|
||||
Steps: tt.step,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ type CreateRequestBody struct {
|
||||
CPUUnits *int `json:"cpuunits,omitempty" url:"cpuunits,omitempty"`
|
||||
DedicatedMemory *int `json:"memory,omitempty" url:"memory,omitempty"`
|
||||
Delete []string `json:"delete,omitempty" url:"delete,omitempty,comma"`
|
||||
DeletionProtection *types.CustomBool `json:"protection,omitempty" url:"force,omitempty,int"`
|
||||
DeletionProtection *types.CustomBool `json:"protection,omitempty" url:"protection,omitempty,int"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
EFIDisk *CustomEFIDisk `json:"efidisk0,omitempty" url:"efidisk0,omitempty"`
|
||||
FloatingMemory *int `json:"balloon,omitempty" url:"balloon,omitempty"`
|
||||
|
@ -104,6 +104,7 @@ const (
|
||||
dvNetworkDeviceMTU = 0
|
||||
dvOperatingSystemType = "other"
|
||||
dvPoolID = ""
|
||||
dvProtection = false
|
||||
dvSerialDeviceDevice = "socket"
|
||||
dvSMBIOSFamily = ""
|
||||
dvSMBIOSManufacturer = ""
|
||||
@ -242,6 +243,7 @@ const (
|
||||
mkOperatingSystem = "operating_system"
|
||||
mkOperatingSystemType = "type"
|
||||
mkPoolID = "pool_id"
|
||||
mkProtection = "protection"
|
||||
mkSerialDevice = "serial_device"
|
||||
mkSerialDeviceDevice = "device"
|
||||
mkSMBIOS = "smbios"
|
||||
@ -1195,6 +1197,12 @@ func VM() *schema.Resource {
|
||||
Optional: true,
|
||||
Default: dvPoolID,
|
||||
},
|
||||
mkProtection: {
|
||||
Type: schema.TypeBool,
|
||||
Description: "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations",
|
||||
Optional: true,
|
||||
Default: dvProtection,
|
||||
},
|
||||
mkSerialDevice: {
|
||||
Type: schema.TypeList,
|
||||
Description: "The serial devices",
|
||||
@ -1822,6 +1830,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
serialDevice := d.Get(mkSerialDevice).([]interface{})
|
||||
onBoot := types.CustomBool(d.Get(mkOnBoot).(bool))
|
||||
tabletDevice := types.CustomBool(d.Get(mkTabletDevice).(bool))
|
||||
protection := types.CustomBool(d.Get(mkProtection).(bool))
|
||||
template := types.CustomBool(d.Get(mkTemplate).(bool))
|
||||
vga := d.Get(mkVGA).([]interface{})
|
||||
|
||||
@ -2061,6 +2070,11 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
updateBody.TabletDeviceEnabled = &tabletDevice
|
||||
}
|
||||
|
||||
//nolint:gosimple
|
||||
if protection != dvProtection {
|
||||
updateBody.DeletionProtection = &protection
|
||||
}
|
||||
|
||||
if len(tags) > 0 {
|
||||
tagString := vmGetTagsString(d)
|
||||
updateBody.Tags = &tagString
|
||||
@ -2433,6 +2447,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
operatingSystemType := operatingSystem[mkOperatingSystemType].(string)
|
||||
|
||||
poolID := d.Get(mkPoolID).(string)
|
||||
protection := types.CustomBool(d.Get(mkProtection).(bool))
|
||||
|
||||
serialDevices := vmGetSerialDeviceList(d)
|
||||
|
||||
@ -2548,6 +2563,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
CPUSockets: &cpuSockets,
|
||||
CPUUnits: &cpuUnits,
|
||||
DedicatedMemory: &memoryDedicated,
|
||||
DeletionProtection: &protection,
|
||||
EFIDisk: efiDisk,
|
||||
TPMState: tpmState,
|
||||
FloatingMemory: &memoryFloating,
|
||||
@ -4672,6 +4688,23 @@ func vmReadPrimitiveValues(
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
}
|
||||
|
||||
currentProtection := d.Get(mkProtection).(bool)
|
||||
|
||||
//nolint:gosimple
|
||||
if len(clone) == 0 || currentProtection != dvProtection {
|
||||
if vmConfig.DeletionProtection != nil {
|
||||
err = d.Set(
|
||||
mkProtection,
|
||||
bool(*vmConfig.DeletionProtection),
|
||||
)
|
||||
} else {
|
||||
// Default value of "protection" is "0" according to the API documentation.
|
||||
err = d.Set(mkProtection, false)
|
||||
}
|
||||
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
}
|
||||
|
||||
if !d.Get(mkTemplate).(bool) {
|
||||
err = d.Set(mkStarted, vmStatus.Status == "running")
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
@ -4878,6 +4911,11 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
updateBody.Name = &name
|
||||
}
|
||||
|
||||
if d.HasChange(mkProtection) {
|
||||
protection := types.CustomBool(d.Get(mkProtection).(bool))
|
||||
updateBody.DeletionProtection = &protection
|
||||
}
|
||||
|
||||
if d.HasChange(mkTabletDevice) {
|
||||
tabletDevice := types.CustomBool(d.Get(mkTabletDevice).(bool))
|
||||
updateBody.TabletDeviceEnabled = &tabletDevice
|
||||
|
Loading…
Reference in New Issue
Block a user