From b46afd2bbf5a6a96e593a11feb4f9bce1113f7c7 Mon Sep 17 00:00:00 2001 From: Arcturus Date: Tue, 14 Jul 2020 12:27:34 +0800 Subject: [PATCH] Update `azurerm_orchestrated_virtual_machine_scale_set` - Add proximity placement group support (#7510) --- ...inux_virtual_machine_scale_set_resource.go | 2 +- ...ated_virtual_machine_scale_set_resource.go | 22 +++++ ...tual_machine_resource_orchestrated_test.go | 95 +++++++++++++++++++ ...tual_machine_resource_orchestrated_test.go | 90 ++++++++++++++++++ ...dows_virtual_machine_scale_set_resource.go | 2 +- ...ed_virtual_machine_scale_set.html.markdown | 2 + 6 files changed, 211 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/compute/linux_virtual_machine_scale_set_resource.go b/azurerm/internal/services/compute/linux_virtual_machine_scale_set_resource.go index 25d3157cc56c..0c55fefae917 100644 --- a/azurerm/internal/services/compute/linux_virtual_machine_scale_set_resource.go +++ b/azurerm/internal/services/compute/linux_virtual_machine_scale_set_resource.go @@ -184,7 +184,7 @@ func resourceArmLinuxVirtualMachineScaleSet() *schema.Resource { Optional: true, ForceNew: true, ValidateFunc: validate.ProximityPlacementGroupID, - // the Compute API is broken and returns the Resource Group name in UPPERCASE :shrug: + // the Compute API is broken and returns the Resource Group name in UPPERCASE :shrug:, github issue: https://github.com/Azure/azure-rest-api-specs/issues/10016 DiffSuppressFunc: suppress.CaseDifference, }, diff --git a/azurerm/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go b/azurerm/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go index 5eaba49efe83..d75d0c256af5 100644 --- a/azurerm/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go +++ b/azurerm/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go @@ -9,10 +9,12 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" @@ -58,6 +60,15 @@ func resourceArmOrchestratedVirtualMachineScaleSet() *schema.Resource { ValidateFunc: validation.IntBetween(0, 5), }, + "proximity_placement_group_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.ProximityPlacementGroupID, + // the Compute/VM API is broken and returns the Resource Group name in UPPERCASE :shrug:, github issue: https://github.com/Azure/azure-rest-api-specs/issues/10016 + DiffSuppressFunc: suppress.CaseDifference, + }, + "single_placement_group": { Type: schema.TypeBool, Optional: true, @@ -111,6 +122,12 @@ func resourceArmOrchestratedVirtualMachineScaleSetCreateUpdate(d *schema.Resourc Zones: azure.ExpandZones(d.Get("zones").([]interface{})), } + if v, ok := d.GetOk("proximity_placement_group_id"); ok { + props.VirtualMachineScaleSetProperties.ProximityPlacementGroup = &compute.SubResource{ + ID: utils.String(v.(string)), + } + } + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, props) if err != nil { return fmt.Errorf("creating Orchestrated Virtual Machine Scale Set %q (Resource Group %q): %+v", name, resourceGroup, err) @@ -161,6 +178,11 @@ func resourceArmOrchestratedVirtualMachineScaleSetRead(d *schema.ResourceData, m if props := resp.VirtualMachineScaleSetProperties; props != nil { d.Set("platform_fault_domain_count", props.PlatformFaultDomainCount) d.Set("single_placement_group", props.SinglePlacementGroup) + proximityPlacementGroupID := "" + if props.ProximityPlacementGroup != nil && props.ProximityPlacementGroup.ID != nil { + proximityPlacementGroupID = *props.ProximityPlacementGroup.ID + } + d.Set("proximity_placement_group_id", proximityPlacementGroupID) d.Set("unique_id", props.UniqueID) } diff --git a/azurerm/internal/services/compute/tests/linux_virtual_machine_resource_orchestrated_test.go b/azurerm/internal/services/compute/tests/linux_virtual_machine_resource_orchestrated_test.go index 014923718ae1..4cb42c1e0c45 100644 --- a/azurerm/internal/services/compute/tests/linux_virtual_machine_resource_orchestrated_test.go +++ b/azurerm/internal/services/compute/tests/linux_virtual_machine_resource_orchestrated_test.go @@ -22,6 +22,26 @@ func TestAccAzureRMLinuxVirtualMachine_orchestratedZonal(t *testing.T) { checkLinuxVirtualMachineExists(data.ResourceName), ), }, + data.ImportStep("admin_password"), + }, + }) +} + +func TestAccAzureRMLinuxVirtualMachine_orchestratedZonalWithProximityPlacementGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: checkLinuxVirtualMachineIsDestroyed, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMLinuxVirtualMachine_orchestratedZonalWithProximityPlacementGroup(data), + Check: resource.ComposeTestCheckFunc( + checkLinuxVirtualMachineExists(data.ResourceName), + ), + }, + data.ImportStep("admin_password"), }, }) } @@ -40,6 +60,7 @@ func TestAccAzureRMLinuxVirtualMachine_orchestratedNonZonal(t *testing.T) { checkLinuxVirtualMachineExists(data.ResourceName), ), }, + data.ImportStep("admin_password"), }, }) } @@ -58,6 +79,7 @@ func TestAccAzureRMLinuxVirtualMachine_orchestratedMultipleZonal(t *testing.T) { checkLinuxVirtualMachineExists(data.ResourceName), ), }, + data.ImportStep("admin_password"), }, }) } @@ -76,6 +98,7 @@ func TestAccAzureRMLinuxVirtualMachine_orchestratedMultipleNonZonal(t *testing.T checkLinuxVirtualMachineExists(data.ResourceName), ), }, + data.ImportStep("admin_password"), }, }) } @@ -141,6 +164,78 @@ resource "azurerm_linux_virtual_machine" "test" { `, template, data.RandomInteger, data.RandomInteger, data.RandomInteger) } +func testAccAzureRMLinuxVirtualMachine_orchestratedZonalWithProximityPlacementGroup(data acceptance.TestData) string { + template := testLinuxVirtualMachine_templateBaseForOchestratedVMSS(data) + return fmt.Sprintf(` +%s + +resource "azurerm_proximity_placement_group" "test" { + name = "acctestPPG-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +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 + + proximity_placement_group_id = azurerm_proximity_placement_group.test.id + + 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 + + proximity_placement_group_id = azurerm_proximity_placement_group.test.id + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.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 = azurerm_orchestrated_virtual_machine_scale_set.test.zones.0 +} +`, template, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + func testAccAzureRMLinuxVirtualMachine_orchestratedNonZonal(data acceptance.TestData) string { template := testLinuxVirtualMachine_templateBaseForOchestratedVMSS(data) return fmt.Sprintf(` diff --git a/azurerm/internal/services/compute/tests/windows_virtual_machine_resource_orchestrated_test.go b/azurerm/internal/services/compute/tests/windows_virtual_machine_resource_orchestrated_test.go index 2b0f646e5d15..e685b7f68d13 100644 --- a/azurerm/internal/services/compute/tests/windows_virtual_machine_resource_orchestrated_test.go +++ b/azurerm/internal/services/compute/tests/windows_virtual_machine_resource_orchestrated_test.go @@ -27,6 +27,25 @@ func TestAccAzureRMWindowsVirtualMachine_orchestratedZonal(t *testing.T) { }) } +func TestAccAzureRMWindowsVirtualMachine_orchestratedZonalWithProximityPlacementGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: checkWindowsVirtualMachineIsDestroyed, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMWindowsVirtualMachine_orchestratedZonalWithProximityPlacementGroup(data), + Check: resource.ComposeTestCheckFunc( + checkWindowsVirtualMachineExists(data.ResourceName), + ), + }, + data.ImportStep("admin_password"), + }, + }) +} + func TestAccAzureRMWindowsVirtualMachine_orchestratedNonZonal(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") @@ -144,6 +163,77 @@ resource "azurerm_windows_virtual_machine" "test" { `, template, data.RandomInteger, data.RandomInteger) } +func testAccAzureRMWindowsVirtualMachine_orchestratedZonalWithProximityPlacementGroup(data acceptance.TestData) string { + template := testWindowsVirtualMachine_templateBaseForOchestratedVMSS(data) + return fmt.Sprintf(` +%s + +resource "azurerm_proximity_placement_group" "test" { + name = "acctestPPG-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +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 + + proximity_placement_group_id = azurerm_proximity_placement_group.test.id + + 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!" + + proximity_placement_group_id = azurerm_proximity_placement_group.test.id + + 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 = azurerm_orchestrated_virtual_machine_scale_set.test.zones.0 +} +`, template, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + func testAccAzureRMWindowsVirtualMachine_orchestratedNonZonal(data acceptance.TestData) string { template := testWindowsVirtualMachine_templateBaseForOchestratedVMSS(data) return fmt.Sprintf(` diff --git a/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go b/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go index 03e015dc56c3..8f1af227e5e5 100644 --- a/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go +++ b/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go @@ -197,7 +197,7 @@ func resourceArmWindowsVirtualMachineScaleSet() *schema.Resource { Optional: true, ForceNew: true, ValidateFunc: azure.ValidateResourceID, - // the Compute API is broken and returns the Resource Group name in UPPERCASE :shrug: + // the Compute API is broken and returns the Resource Group name in UPPERCASE :shrug:, github issue: https://github.com/Azure/azure-rest-api-specs/issues/10016 DiffSuppressFunc: suppress.CaseDifference, }, diff --git a/website/docs/r/orchestrated_virtual_machine_scale_set.html.markdown b/website/docs/r/orchestrated_virtual_machine_scale_set.html.markdown index 1e8c2d30de38..73bad9b60487 100644 --- a/website/docs/r/orchestrated_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/orchestrated_virtual_machine_scale_set.html.markdown @@ -47,6 +47,8 @@ The following arguments are supported: ~> **NOTE:** The number of Fault Domains varies depending on which Azure Region you're using - a list can be found [here](https://github.com/MicrosoftDocs/azure-docs/blob/master/includes/managed-disks-common-fault-domain-region-list.md). +* `proximity_placement_group_id` - (Optional) The ID of the Proximity Placement Group which the Virtual Machine should be assigned to. Changing this forces a new resource to be created. + * `single_placement_group` - (Optional / **Deprecated**) Should the Orchestrated Virtual Machine Scale Set use single placement group? ~> **NOTE:** Due to a limitation of the Azure API at this time, you can only assign `single_placement_group` to `false`.