Skip to content

Commit

Permalink
azurerm_linux_virtual_machine,azurerm_windows_virtual_machine - S…
Browse files Browse the repository at this point in the history
…upport update `virtual_machine_scale_set_id` (#24768)

* add code

* add notes for enabling the preview feature
  • Loading branch information
ms-zhenhua authored Feb 20, 2024
1 parent a6e2151 commit f94772c
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 4 deletions.
13 changes: 12 additions & 1 deletion internal/services/compute/linux_virtual_machine_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource {
"virtual_machine_scale_set_id": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
ConflictsWith: []string{
"availability_set_id",
},
Expand Down Expand Up @@ -1194,6 +1193,18 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface
}
}

if d.HasChange("virtual_machine_scale_set_id") {
shouldUpdate = true

if vmssIDRaw, ok := d.GetOk("virtual_machine_scale_set_id"); ok {
update.VirtualMachineProperties.VirtualMachineScaleSet = &compute.SubResource{
ID: utils.String(vmssIDRaw.(string)),
}
} else {
update.VirtualMachineProperties.VirtualMachineScaleSet = &compute.SubResource{}
}
}

if d.HasChange("proximity_placement_group_id") {
shouldUpdate = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,35 @@ func TestAccLinuxVirtualMachine_orchestratedMultipleNonZonal(t *testing.T) {
})
}

func TestAccLinuxVirtualMachine_orchestratedIdUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test")
r := LinuxVirtualMachineResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.orchestratedIdUnAttached(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
{
Config: r.orchestratedIdAttached(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
{
Config: r.orchestratedIdUnAttached(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
})
}

func (r LinuxVirtualMachineResource) orchestratedZonal(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
Expand Down Expand Up @@ -161,6 +190,125 @@ resource "azurerm_linux_virtual_machine" "test" {
`, r.templateBaseForOchestratedVMSS(data), data.RandomInteger, data.RandomInteger, data.RandomInteger)
}

func (r LinuxVirtualMachineResource) orchestratedIdUnAttached(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_network_interface" "test" {
name = "acctestnic-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.test.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_orchestrated_virtual_machine_scale_set" "test" {
name = "acctestVMO-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
platform_fault_domain_count = 1
zones = ["1"]
tags = {
ENV = "Test"
}
}
resource "azurerm_linux_virtual_machine" "test" {
name = "acctestVM-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
size = "Standard_F2"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.test.id,
]
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
zone = tolist(azurerm_orchestrated_virtual_machine_scale_set.test.zones)[0]
}
`, r.templateBaseForOchestratedVMSS(data), data.RandomInteger, data.RandomInteger, data.RandomInteger)
}

func (r LinuxVirtualMachineResource) orchestratedIdAttached(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_network_interface" "test" {
name = "acctestnic-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.test.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_orchestrated_virtual_machine_scale_set" "test" {
name = "acctestVMO-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
platform_fault_domain_count = 1
zones = ["1"]
tags = {
ENV = "Test"
}
}
resource "azurerm_linux_virtual_machine" "test" {
name = "acctestVM-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
size = "Standard_F2"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.test.id,
]
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
virtual_machine_scale_set_id = azurerm_orchestrated_virtual_machine_scale_set.test.id
zone = tolist(azurerm_orchestrated_virtual_machine_scale_set.test.zones)[0]
}
`, r.templateBaseForOchestratedVMSS(data), data.RandomInteger, data.RandomInteger, data.RandomInteger)
}

func (r LinuxVirtualMachineResource) orchestratedWithPlatformFaultDomain(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
Expand Down
13 changes: 12 additions & 1 deletion internal/services/compute/windows_virtual_machine_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource {
"virtual_machine_scale_set_id": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
ConflictsWith: []string{
"availability_set_id",
},
Expand Down Expand Up @@ -1355,6 +1354,18 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa
}
}

if d.HasChange("virtual_machine_scale_set_id") {
shouldUpdate = true

if vmssIDRaw, ok := d.GetOk("virtual_machine_scale_set_id"); ok {
update.VirtualMachineProperties.VirtualMachineScaleSet = &compute.SubResource{
ID: utils.String(vmssIDRaw.(string)),
}
} else {
update.VirtualMachineProperties.VirtualMachineScaleSet = &compute.SubResource{}
}
}

if d.HasChange("proximity_placement_group_id") {
shouldUpdate = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,35 @@ func TestAccWindowsVirtualMachine_orchestratedMultipleNoneZonal(t *testing.T) {
})
}

func TestAccWindowsVirtualMachine_orchestratedIdUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test")
r := WindowsVirtualMachineResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.orchestratedIdUnAttached(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
{
Config: r.orchestratedIdAttached(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
{
Config: r.orchestratedIdUnAttached(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
})
}

func (r WindowsVirtualMachineResource) orchestratedZonal(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
Expand Down Expand Up @@ -160,6 +189,123 @@ resource "azurerm_windows_virtual_machine" "test" {
`, r.templateBaseForOchestratedVMSS(data), data.RandomInteger, data.RandomInteger)
}

func (r WindowsVirtualMachineResource) orchestratedIdUnAttached(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_network_interface" "test" {
name = "acctestnic-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.test.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_orchestrated_virtual_machine_scale_set" "test" {
name = "acctestVMO-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
platform_fault_domain_count = 1
zones = ["1"]
tags = {
ENV = "Test"
}
}
resource "azurerm_windows_virtual_machine" "test" {
name = local.vm_name
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
size = "Standard_F2"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
network_interface_ids = [
azurerm_network_interface.test.id,
]
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
zone = tolist(azurerm_orchestrated_virtual_machine_scale_set.test.zones)[0]
}
`, r.templateBaseForOchestratedVMSS(data), data.RandomInteger, data.RandomInteger)
}

func (r WindowsVirtualMachineResource) orchestratedIdAttached(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_network_interface" "test" {
name = "acctestnic-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.test.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_orchestrated_virtual_machine_scale_set" "test" {
name = "acctestVMO-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
platform_fault_domain_count = 1
zones = ["1"]
tags = {
ENV = "Test"
}
}
resource "azurerm_windows_virtual_machine" "test" {
name = local.vm_name
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
size = "Standard_F2"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
network_interface_ids = [
azurerm_network_interface.test.id,
]
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
virtual_machine_scale_set_id = azurerm_orchestrated_virtual_machine_scale_set.test.id
zone = tolist(azurerm_orchestrated_virtual_machine_scale_set.test.zones)[0]
}
`, r.templateBaseForOchestratedVMSS(data), data.RandomInteger, data.RandomInteger)
}

func (r WindowsVirtualMachineResource) orchestratedWithPlatformFaultDomain(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
Expand Down
4 changes: 3 additions & 1 deletion website/docs/r/linux_virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ The following arguments are supported:

* `vtpm_enabled` - (Optional) Specifies whether vTPM should be enabled on the virtual machine. Changing this forces a new resource to be created.

* `virtual_machine_scale_set_id` - (Optional) Specifies the Orchestrated Virtual Machine Scale Set that this Virtual Machine should be created within. Changing this forces a new resource to be created.
* `virtual_machine_scale_set_id` - (Optional) Specifies the Orchestrated Virtual Machine Scale Set that this Virtual Machine should be created within.

-> **NOTE:** To update `virtual_machine_scale_set_id` the Preview Feature `Microsoft.Compute/SingleFDAttachDetachVMToVmss` needs to be enabled, see [the documentation](https://review.learn.microsoft.com/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-attach-detach-vm#enroll-in-the-preview) for more information.

~> **NOTE:** Orchestrated Virtual Machine Scale Sets can be provisioned using [the `azurerm_orchestrated_virtual_machine_scale_set` resource](/docs/providers/azurerm/r/orchestrated_virtual_machine_scale_set.html).

Expand Down
4 changes: 3 additions & 1 deletion website/docs/r/windows_virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ The following arguments are supported:

* `user_data` - (Optional) The Base64-Encoded User Data which should be used for this Virtual Machine.

* `virtual_machine_scale_set_id` - (Optional) Specifies the Orchestrated Virtual Machine Scale Set that this Virtual Machine should be created within. Changing this forces a new resource to be created.
* `virtual_machine_scale_set_id` - (Optional) Specifies the Orchestrated Virtual Machine Scale Set that this Virtual Machine should be created within.

-> **NOTE:** To update `virtual_machine_scale_set_id` the Preview Feature `Microsoft.Compute/SingleFDAttachDetachVMToVmss` needs to be enabled, see [the documentation](https://review.learn.microsoft.com/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-attach-detach-vm#enroll-in-the-preview) for more information.

~> **NOTE:** Orchestrated Virtual Machine Scale Sets can be provisioned using [the `azurerm_orchestrated_virtual_machine_scale_set` resource](/docs/providers/azurerm/r/orchestrated_virtual_machine_scale_set.html).

Expand Down

0 comments on commit f94772c

Please sign in to comment.