From 07d7c43c7c6f5d60524bad5da47566df1df59eba Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Fri, 3 Apr 2020 11:50:15 +0800 Subject: [PATCH 1/3] Add support for automatic instance repair of VMSS --- ...rce_arm_linux_virtual_machine_scale_set.go | 14 ++ ...e_arm_windows_virtual_machine_scale_set.go | 15 ++ ...ux_virtual_machine_scale_set_other_test.go | 175 +++++++++++++++-- ...ws_virtual_machine_scale_set_other_test.go | 181 ++++++++++++++++-- .../compute/virtual_machine_scale_set.go | 59 ++++++ .../linux/rolling-upgrade-policy/main.tf | 13 +- ...ux_virtual_machine_scale_set.html.markdown | 16 ++ ...ws_virtual_machine_scale_set.html.markdown | 16 ++ 8 files changed, 450 insertions(+), 39 deletions(-) diff --git a/azurerm/internal/services/compute/resource_arm_linux_virtual_machine_scale_set.go b/azurerm/internal/services/compute/resource_arm_linux_virtual_machine_scale_set.go index f21f8417509d..2b90e53cfe25 100644 --- a/azurerm/internal/services/compute/resource_arm_linux_virtual_machine_scale_set.go +++ b/azurerm/internal/services/compute/resource_arm_linux_virtual_machine_scale_set.go @@ -94,6 +94,8 @@ func resourceArmLinuxVirtualMachineScaleSet() *schema.Resource { "automatic_os_upgrade_policy": VirtualMachineScaleSetAutomatedOSUpgradePolicySchema(), + "automatic_instance_repair": VirtualMachineScaleSetAutomaticRepairsPolicySchema(), + "boot_diagnostics": bootDiagnosticsSchema(), "computer_name_prefix": { @@ -429,6 +431,8 @@ func resourceArmLinuxVirtualMachineScaleSetCreate(d *schema.ResourceData, meta i } scaleInPolicy := d.Get("scale_in_policy").(string) + automaticRepairsPolicyRaw := d.Get("automatic_instance_repair").([]interface{}) + automaticRepairsPolicy := ExpandVirtualMachineScaleSetAutomaticRepairsPolicy(automaticRepairsPolicyRaw) props := compute.VirtualMachineScaleSet{ Location: utils.String(location), @@ -444,6 +448,7 @@ func resourceArmLinuxVirtualMachineScaleSetCreate(d *schema.ResourceData, meta i Tags: tags.Expand(t), VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{ AdditionalCapabilities: additionalCapabilities, + AutomaticRepairsPolicy: automaticRepairsPolicy, DoNotRunExtensionsOnOverprovisionedVMs: utils.Bool(d.Get("do_not_run_extensions_on_overprovisioned_machines").(bool)), Overprovision: utils.Bool(d.Get("overprovision").(bool)), SinglePlacementGroup: utils.Bool(d.Get("single_placement_group").(bool)), @@ -680,6 +685,11 @@ func resourceArmLinuxVirtualMachineScaleSetUpdate(d *schema.ResourceData, meta i updateProps.VirtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(notificationRaw) } + if d.HasChange("automatic_instance_repair") { + automaticRepairsPolicyRaw := d.Get("automatic_instance_repair").([]interface{}) + updateProps.AutomaticRepairsPolicy = ExpandVirtualMachineScaleSetAutomaticRepairsPolicy(automaticRepairsPolicyRaw) + } + if d.HasChange("identity") { identityRaw := d.Get("identity").([]interface{}) identity, err := ExpandVirtualMachineScaleSetIdentity(identityRaw) @@ -791,6 +801,10 @@ func resourceArmLinuxVirtualMachineScaleSetRead(d *schema.ResourceData, meta int return fmt.Errorf("Error setting `additional_capabilities`: %+v", props.AdditionalCapabilities) } + if err := d.Set("automatic_instance_repair", FlattenVirtualMachineScaleSetAutomaticRepairsPolicy(props.AutomaticRepairsPolicy)); err != nil { + return fmt.Errorf("Error setting `automatic_instance_repair`: %+v", err) + } + d.Set("do_not_run_extensions_on_overprovisioned_machines", props.DoNotRunExtensionsOnOverprovisionedVMs) d.Set("overprovision", props.Overprovision) proximityPlacementGroupId := "" diff --git a/azurerm/internal/services/compute/resource_arm_windows_virtual_machine_scale_set.go b/azurerm/internal/services/compute/resource_arm_windows_virtual_machine_scale_set.go index 26337fd1f362..b27a22e55221 100644 --- a/azurerm/internal/services/compute/resource_arm_windows_virtual_machine_scale_set.go +++ b/azurerm/internal/services/compute/resource_arm_windows_virtual_machine_scale_set.go @@ -95,6 +95,8 @@ func resourceArmWindowsVirtualMachineScaleSet() *schema.Resource { "automatic_os_upgrade_policy": VirtualMachineScaleSetAutomatedOSUpgradePolicySchema(), + "automatic_instance_repair": VirtualMachineScaleSetAutomaticRepairsPolicySchema(), + "boot_diagnostics": bootDiagnosticsSchema(), "computer_name_prefix": { @@ -455,6 +457,8 @@ func resourceArmWindowsVirtualMachineScaleSetCreate(d *schema.ResourceData, meta } scaleInPolicy := d.Get("scale_in_policy").(string) + automaticRepairsPolicyRaw := d.Get("automatic_instance_repair").([]interface{}) + automaticRepairsPolicy := ExpandVirtualMachineScaleSetAutomaticRepairsPolicy(automaticRepairsPolicyRaw) props := compute.VirtualMachineScaleSet{ Location: utils.String(location), @@ -470,6 +474,7 @@ func resourceArmWindowsVirtualMachineScaleSetCreate(d *schema.ResourceData, meta Tags: tags.Expand(t), VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{ AdditionalCapabilities: additionalCapabilities, + AutomaticRepairsPolicy: automaticRepairsPolicy, DoNotRunExtensionsOnOverprovisionedVMs: utils.Bool(d.Get("do_not_run_extensions_on_overprovisioned_machines").(bool)), Overprovision: utils.Bool(d.Get("overprovision").(bool)), SinglePlacementGroup: utils.Bool(d.Get("single_placement_group").(bool)), @@ -710,6 +715,12 @@ func resourceArmWindowsVirtualMachineScaleSetUpdate(d *schema.ResourceData, meta updateProps.VirtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(notificationRaw) } + if d.HasChange("automatic_instance_repair") { + automaticRepairsPolicyRaw := d.Get("automatic_instance_repair").([]interface{}) + automaticRepairsPolicy := ExpandVirtualMachineScaleSetAutomaticRepairsPolicy(automaticRepairsPolicyRaw) + updateProps.AutomaticRepairsPolicy = automaticRepairsPolicy + } + if d.HasChange("identity") { identityRaw := d.Get("identity").([]interface{}) identity, err := ExpandVirtualMachineScaleSetIdentity(identityRaw) @@ -821,6 +832,10 @@ func resourceArmWindowsVirtualMachineScaleSetRead(d *schema.ResourceData, meta i return fmt.Errorf("Error setting `additional_capabilities`: %+v", props.AdditionalCapabilities) } + if err := d.Set("automatic_instance_repair", FlattenVirtualMachineScaleSetAutomaticRepairsPolicy(props.AutomaticRepairsPolicy)); err != nil { + return fmt.Errorf("Error setting `automatic_instance_repair`: %+v", err) + } + d.Set("do_not_run_extensions_on_overprovisioned_machines", props.DoNotRunExtensionsOnOverprovisionedVMs) d.Set("overprovision", props.Overprovision) proximityPlacementGroupId := "" diff --git a/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go b/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go index 4324d388df90..10ab249de8be 100644 --- a/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go +++ b/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go @@ -460,6 +460,38 @@ func TestAccAzureRMLinuxVirtualMachineScaleSet_otherTerminateNotification(t *tes }) } +func TestAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine_scale_set", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMLinuxVirtualMachineScaleSetDestroy, + Steps: []resource.TestStep{ + // turn automatic repair on + { + Config: testAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), + // turn automatic repair off + { + Config: testAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, false), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), + }, + }) +} + func testAccAzureRMLinuxVirtualMachineScaleSet_otherBootDiagnostics(data acceptance.TestData) string { template := testAccAzureRMLinuxVirtualMachineScaleSet_template(data) return fmt.Sprintf(` @@ -1293,21 +1325,21 @@ func testAccAzureRMLinuxVirtualMachineScaleSet_updateLoadBalancerHealthProbeSKUB resource "azurerm_public_ip" "test" { name = "acctestpip-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Dynamic" idle_timeout_in_minutes = 4 } resource "azurerm_lb" "test" { name = "acctestlb-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name sku = "Basic" frontend_ip_configuration { name = "internal" - public_ip_address_id = "${azurerm_public_ip.test.id}" + public_ip_address_id = azurerm_public_ip.test.id } } @@ -1358,8 +1390,6 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { admin_password = "P@ssword1234!" health_probe_id = azurerm_lb_probe.test.id - depends_on = ["azurerm_lb_rule.test"] - disable_password_authentication = false source_image_reference { @@ -1393,6 +1423,8 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { load_balancer_inbound_nat_rules_ids = [azurerm_lb_nat_pool.test.id] } } + + depends_on = [azurerm_lb_rule.test] } `, template, data.RandomInteger) } @@ -1404,8 +1436,8 @@ func testAccAzureRMLinuxVirtualMachineScaleSet_updateLoadBalancerHealthProbeSKUS resource "azurerm_public_ip" "test" { name = "acctestpip-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Static" idle_timeout_in_minutes = 4 sku = "Standard" @@ -1413,13 +1445,13 @@ resource "azurerm_public_ip" "test" { resource "azurerm_lb" "test" { name = "acctestlb-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name sku = "Standard" frontend_ip_configuration { name = "internal" - public_ip_address_id = "${azurerm_public_ip.test.id}" + public_ip_address_id = azurerm_public_ip.test.id } } @@ -1470,8 +1502,6 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { admin_password = "P@ssword1234!" health_probe_id = azurerm_lb_probe.test.id - depends_on = ["azurerm_lb_rule.test"] - disable_password_authentication = false source_image_reference { @@ -1505,6 +1535,8 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { load_balancer_inbound_nat_rules_ids = [azurerm_lb_nat_pool.test.id] } } + + depends_on = [azurerm_lb_rule.test] } `, template, data.RandomInteger) } @@ -1600,3 +1632,118 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { } `, template, data.RandomInteger, enabled) } + +func testAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data acceptance.TestData, enabled bool) string { + template := testAccAzureRMLinuxVirtualMachineScaleSet_template(data) + return fmt.Sprintf(` +%[1]s + +resource "azurerm_public_ip" "test" { + name = "acctestpip-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Dynamic" + idle_timeout_in_minutes = 4 +} + +resource "azurerm_lb" "test" { + name = "acctestlb-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Basic" + + frontend_ip_configuration { + name = "internal" + public_ip_address_id = azurerm_public_ip.test.id + } +} + +resource "azurerm_lb_backend_address_pool" "test" { + name = "test" + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id +} + +resource "azurerm_lb_nat_pool" "test" { + name = "test" + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id + frontend_ip_configuration_name = "internal" + protocol = "Tcp" + frontend_port_start = 80 + frontend_port_end = 81 + backend_port = 8080 +} + +resource "azurerm_lb_probe" "test" { + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id + name = "acctest-lb-probe" + port = 22 + protocol = "Tcp" +} + +resource "azurerm_lb_rule" "test" { + name = "AccTestLBRule" + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id + probe_id = azurerm_lb_probe.test.id + backend_address_pool_id = azurerm_lb_backend_address_pool.test.id + frontend_ip_configuration_name = "internal" + protocol = "Tcp" + frontend_port = 22 + backend_port = 22 +} + +resource "azurerm_linux_virtual_machine_scale_set" "test" { + name = "acctestvmss-%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + health_probe_id = azurerm_lb_probe.test.id + + disable_password_authentication = false + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + data_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + disk_size_gb = 10 + lun = 10 + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.test.id + load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.test.id] + load_balancer_inbound_nat_rules_ids = [azurerm_lb_nat_pool.test.id] + } + } + + automatic_instance_repair { + enabled = %[3]t + } + + depends_on = [azurerm_lb_rule.test] +} +`, template, data.RandomInteger, enabled) +} diff --git a/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go b/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go index da58c517e15d..d0867d42628c 100644 --- a/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go +++ b/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go @@ -581,7 +581,7 @@ func TestAccAzureRMWindowsVirtualMachineScaleSet_otherScaleInPolicy(t *testing.T resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMLinuxVirtualMachineScaleSetDestroy, + CheckDestroy: testCheckAzureRMWindowsVirtualMachineScaleSetDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherScaleInPolicy(data), @@ -603,7 +603,7 @@ func TestAccAzureRMWindowsVirtualMachineScaleSet_otherTerminateNotification(t *t resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMLinuxVirtualMachineScaleSetDestroy, + CheckDestroy: testCheckAzureRMWindowsVirtualMachineScaleSetDestroy, Steps: []resource.TestStep{ // turn terminate notification on { @@ -630,6 +630,38 @@ func TestAccAzureRMWindowsVirtualMachineScaleSet_otherTerminateNotification(t *t }) } +func TestAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine_scale_set", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMWindowsVirtualMachineScaleSetDestroy, + Steps: []resource.TestStep{ + // turn automatic repair on + { + Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), + // turn automatic repair off + { + Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, false), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), + }, + }) +} + func testAccAzureRMWindowsVirtualMachineScaleSet_otherBootDiagnostics(data acceptance.TestData) string { template := testAccAzureRMWindowsVirtualMachineScaleSet_template(data) return fmt.Sprintf(` @@ -1567,8 +1599,8 @@ data "azurerm_client_config" "current" {} resource "azurerm_key_vault" "test" { name = "acctestkv%s" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location sku_name = "standard" tenant_id = data.azurerm_client_config.current.tenant_id @@ -1732,21 +1764,21 @@ func testAccAzureRMWindowsVirtualMachineScaleSet_updateLoadBalancerHealthProbeSK resource "azurerm_public_ip" "test" { name = "acctestpip-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Dynamic" idle_timeout_in_minutes = 4 } resource "azurerm_lb" "test" { name = "acctestlb-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name sku = "Basic" frontend_ip_configuration { name = "internal" - public_ip_address_id = "${azurerm_public_ip.test.id}" + public_ip_address_id = azurerm_public_ip.test.id } } @@ -1797,8 +1829,6 @@ resource "azurerm_windows_virtual_machine_scale_set" "test" { admin_password = "P@ssword1234!" health_probe_id = azurerm_lb_probe.test.id - depends_on = ["azurerm_lb_rule.test"] - source_image_reference { publisher = "MicrosoftWindowsServer" offer = "WindowsServer" @@ -1830,6 +1860,8 @@ resource "azurerm_windows_virtual_machine_scale_set" "test" { load_balancer_inbound_nat_rules_ids = [azurerm_lb_nat_pool.test.id] } } + + depends_on = [azurerm_lb_rule.test] } `, template, data.RandomInteger) } @@ -1841,8 +1873,8 @@ func testAccAzureRMWindowsVirtualMachineScaleSet_updateLoadBalancerHealthProbeSK resource "azurerm_public_ip" "test" { name = "acctestpip-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name allocation_method = "Static" idle_timeout_in_minutes = 4 sku = "Standard" @@ -1850,13 +1882,13 @@ resource "azurerm_public_ip" "test" { resource "azurerm_lb" "test" { name = "acctestlb-%[2]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name sku = "Standard" frontend_ip_configuration { name = "internal" - public_ip_address_id = "${azurerm_public_ip.test.id}" + public_ip_address_id = azurerm_public_ip.test.id } } @@ -1907,8 +1939,6 @@ resource "azurerm_windows_virtual_machine_scale_set" "test" { admin_password = "P@ssword1234!" health_probe_id = azurerm_lb_probe.test.id - depends_on = ["azurerm_lb_rule.test"] - source_image_reference { publisher = "MicrosoftWindowsServer" offer = "WindowsServer" @@ -1940,6 +1970,8 @@ resource "azurerm_windows_virtual_machine_scale_set" "test" { load_balancer_inbound_nat_rules_ids = [azurerm_lb_nat_pool.test.id] } } + + depends_on = [azurerm_lb_rule.test] } `, template, data.RandomInteger) } @@ -2029,3 +2061,116 @@ resource "azurerm_windows_virtual_machine_scale_set" "test" { } `, template, enabled) } + +func testAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data acceptance.TestData, enabled bool) string { + template := testAccAzureRMWindowsVirtualMachineScaleSet_template(data) + return fmt.Sprintf(` +%[1]s + +resource "azurerm_public_ip" "test" { + name = "acctestpip-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Dynamic" + idle_timeout_in_minutes = 4 +} + +resource "azurerm_lb" "test" { + name = "acctestlb-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Basic" + + frontend_ip_configuration { + name = "internal" + public_ip_address_id = azurerm_public_ip.test.id + } +} + +resource "azurerm_lb_backend_address_pool" "test" { + name = "test" + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id +} + +resource "azurerm_lb_nat_pool" "test" { + name = "test" + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id + frontend_ip_configuration_name = "internal" + protocol = "Tcp" + frontend_port_start = 80 + frontend_port_end = 81 + backend_port = 8080 +} + +resource "azurerm_lb_probe" "test" { + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id + name = "acctest-lb-probe" + port = 22 + protocol = "Tcp" +} + +resource "azurerm_lb_rule" "test" { + name = "AccTestLBRule" + resource_group_name = azurerm_resource_group.test.name + loadbalancer_id = azurerm_lb.test.id + probe_id = azurerm_lb_probe.test.id + backend_address_pool_id = azurerm_lb_backend_address_pool.test.id + frontend_ip_configuration_name = "internal" + protocol = "Tcp" + frontend_port = 22 + backend_port = 22 +} + +resource "azurerm_windows_virtual_machine_scale_set" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + health_probe_id = azurerm_lb_probe.test.id + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2019-Datacenter" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + data_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + disk_size_gb = 10 + lun = 10 + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.test.id + load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.test.id] + load_balancer_inbound_nat_rules_ids = [azurerm_lb_nat_pool.test.id] + } + } + + automatic_instance_repair { + enabled = %[3]t + } + + depends_on = [azurerm_lb_rule.test] +} +`, template, data.RandomInteger, enabled) +} diff --git a/azurerm/internal/services/compute/virtual_machine_scale_set.go b/azurerm/internal/services/compute/virtual_machine_scale_set.go index 205707994d4d..c6e385276aa3 100644 --- a/azurerm/internal/services/compute/virtual_machine_scale_set.go +++ b/azurerm/internal/services/compute/virtual_machine_scale_set.go @@ -1255,3 +1255,62 @@ func FlattenVirtualMachineScaleSetScheduledEventsProfile(input *compute.Schedule }, } } + +func VirtualMachineScaleSetAutomaticRepairsPolicySchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + "grace_period": { + Type: schema.TypeString, + Optional: true, + Default: "PT30M", + // this field actually has a range from 30m to 90m, is there a function that can do this validation? + ValidateFunc: azValidate.ISO8601Duration, + }, + }, + }, + } +} + +func ExpandVirtualMachineScaleSetAutomaticRepairsPolicy(input []interface{}) *compute.AutomaticRepairsPolicy { + if len(input) == 0 { + return nil + } + + raw := input[0].(map[string]interface{}) + + return &compute.AutomaticRepairsPolicy{ + Enabled: utils.Bool(raw["enabled"].(bool)), + GracePeriod: utils.String(raw["grace_period"].(string)), + } +} + +func FlattenVirtualMachineScaleSetAutomaticRepairsPolicy(input *compute.AutomaticRepairsPolicy) []interface{} { + // if enabled is set to false, there will be no AutomaticRepairsPolicy in response, to avoid plan non empty when + // a user explicitly set enabled to false, we need to assign a default block to this field + + enabled := false + if input != nil && input.Enabled != nil { + enabled = *input.Enabled + } + + gracePeriod := "PT30M" + if input != nil && input.GracePeriod != nil { + gracePeriod = *input.GracePeriod + } + + return []interface{}{ + map[string]interface{}{ + "enabled": enabled, + "grace_period": gracePeriod, + }, + } +} diff --git a/examples/vm-scale-set/linux/rolling-upgrade-policy/main.tf b/examples/vm-scale-set/linux/rolling-upgrade-policy/main.tf index b96b3e3befe1..56c631b79e1b 100644 --- a/examples/vm-scale-set/linux/rolling-upgrade-policy/main.tf +++ b/examples/vm-scale-set/linux/rolling-upgrade-policy/main.tf @@ -10,14 +10,14 @@ resource "azurerm_resource_group" "main" { resource "azurerm_virtual_network" "main" { name = "${var.prefix}-network" address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.main.location}" - resource_group_name = "${azurerm_resource_group.main.name}" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name } resource "azurerm_subnet" "internal" { name = "internal" - resource_group_name = "${azurerm_resource_group.main.name}" - virtual_network_name = "${azurerm_virtual_network.main.name}" + resource_group_name = azurerm_resource_group.main.name + virtual_network_name = azurerm_virtual_network.main.name address_prefix = "10.0.2.0/24" } @@ -29,7 +29,7 @@ resource "azurerm_public_ip" "main" { allocation_method = "Static" } -resource "azurerm_lb" "test" { +resource "azurerm_lb" "main" { name = "${var.prefix}-lb" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name @@ -42,7 +42,6 @@ resource "azurerm_lb" "test" { resource "azurerm_lb_backend_address_pool" "main" { name = "backend-pool" - location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name loadbalancer_id = azurerm_lb.main.id } @@ -122,5 +121,5 @@ resource "azurerm_linux_virtual_machine_scale_set" "main" { pause_time_between_batches = "PT30S" } - depends_on = ["azurerm_lb_rule.main"] + depends_on = [azurerm_lb_rule.main] } diff --git a/website/docs/r/linux_virtual_machine_scale_set.html.markdown b/website/docs/r/linux_virtual_machine_scale_set.html.markdown index b59de4e863a9..918ac89154b0 100644 --- a/website/docs/r/linux_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/linux_virtual_machine_scale_set.html.markdown @@ -23,6 +23,10 @@ Manages a Linux Virtual Machine Scale Set. This example provisions a basic Linux Virtual Machine Scale Set on an internal network. Additional examples of how to use the `azurerm_linux_virtual_machine_scale_set` resource can be found [in the ./examples/vm-scale-set/linux` directory within the Github Repository](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/vm-scale-set/linux). ```hcl +provider "azurerm" { + features {} +} + resource "azurerm_resource_group" "example" { name = "example-resources" location = "West Europe" @@ -118,6 +122,10 @@ The following arguments are supported: * `automatic_os_upgrade_policy` - (Optional) A `automatic_os_upgrade_policy` block as defined below. This is Required and can only be specified when `upgrade_mode` is set to `Automatic`. +* `automatic_instance_repair` - (Optional) A `automatic_instance_repair` block as defined below. To enable the automatic instance repair, this Virtual Machine Scale Set must have a valid `health_probe_id` or an [Application Health Extension](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-health-extension). + +~> **NOTE:** Automatic repairs policy is currently under public preview, to opt-in the preview project and to get more information about this feature, please refer to [this doc](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs). + * `boot_diagnostics` - (Optional) A `boot_diagnostics` block as defined below. * `computer_name_prefix` - (Optional) The prefix which should be used for the name of the Virtual Machines in this Scale Set. If unspecified this defaults to the value for the `name` field. @@ -212,6 +220,14 @@ A `automatic_os_upgrade_policy` block supports the following: --- +A `automatic_instance_repair` block supports the following: + +* `enabled` - (Required) Should the automatic instance repair be enabled on this Virtual Machine Scale Set? + +* `grace_period` - (Optional) Amount of time (in minutes, between 30 and 90, defaults to 30 minutes) for which automatic repairs will be delayed. The grace period starts right after the VM is found unhealthy. The time duration should be specified in ISO 8601 format. + +--- + A `boot_diagnostics` block supports the following: * `storage_account_uri` - (Required) The Primary/Secondary Endpoint for the Azure Storage Account which should be used to store Boot Diagnostics, including Console Output and Screenshots from the Hypervisor. diff --git a/website/docs/r/windows_virtual_machine_scale_set.html.markdown b/website/docs/r/windows_virtual_machine_scale_set.html.markdown index 117c20ac7993..7ca2f90ab321 100644 --- a/website/docs/r/windows_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/windows_virtual_machine_scale_set.html.markdown @@ -23,6 +23,10 @@ Manages a Windows Virtual Machine Scale Set. This example provisions a basic Windows Virtual Machine Scale Set on an internal network. Additional examples of how to use the `azurerm_windows_virtual_machine_scale_set` resource can be found [in the ./examples/vm-scale-set/windows` directory within the Github Repository](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/vm-scale-set/windows). ```hcl +provider "azurerm" { + features {} +} + resource "azurerm_resource_group" "example" { name = "example-resources" location = "West Europe" @@ -108,6 +112,10 @@ The following arguments are supported: * `automatic_os_upgrade_policy` - (Optional) A `automatic_os_upgrade_policy` block as defined below. This is Required and can only be specified when `upgrade_mode` is set to `Automatic`. +* `automatic_instance_repair` - (Optional) A `automatic_instance_repair` block as defined below. To enable the automatic instance repair, this Virtual Machine Scale Set must have a valid `health_probe_id` or an [Application Health Extension](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-health-extension). + +~> **NOTE:** Automatic repairs policy is currently under public preview, to opt-in the preview project and to get more information about this feature, please refer to [this doc](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs). + * `boot_diagnostics` - (Optional) A `boot_diagnostics` block as defined below. * `computer_name_prefix` - (Optional) The prefix which should be used for the name of the Virtual Machines in this Scale Set. If unspecified this defaults to the value for the `name` field. @@ -202,6 +210,14 @@ A `automatic_os_upgrade_policy` block supports the following: --- +A `automatic_instance_repair` block supports the following: + +* `enabled` - (Required) Should the automatic instance repair be enabled on this Virtual Machine Scale Set? + +* `grace_period` - (Optional) Amount of time (in minutes, between 30 and 90, defaults to 30 minutes) for which automatic repairs will be delayed. The grace period starts right after the VM is found unhealthy. The time duration should be specified in ISO 8601 format. + +--- + A `boot_diagnostics` block supports the following: * `storage_account_uri` - (Required) The Primary/Secondary Endpoint for the Azure Storage Account which should be used to store Boot Diagnostics, including Console Output and Screenshots from the Hypervisor. From 1a3444490d88e80c315c074268db8fd88792da8b Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Wed, 8 Apr 2020 13:29:21 +0800 Subject: [PATCH 2/3] Add a test step that turns the feature on again --- ...ux_virtual_machine_scale_set_other_test.go | 25 +++++++++++++++++++ ...ws_virtual_machine_scale_set_other_test.go | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go b/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go index 10ab249de8be..f173d7157c52 100644 --- a/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go +++ b/azurerm/internal/services/compute/tests/resource_arm_linux_virtual_machine_scale_set_other_test.go @@ -444,6 +444,9 @@ func TestAccAzureRMLinuxVirtualMachineScaleSet_otherTerminateNotification(t *tes resource.TestCheckResourceAttr(data.ResourceName, "terminate_notification.0.enabled", "true"), ), }, + data.ImportStep( + "admin_password", + ), // turn terminate notification off { Config: testAccAzureRMLinuxVirtualMachineScaleSet_otherTerminateNotification(data, false), @@ -456,6 +459,18 @@ func TestAccAzureRMLinuxVirtualMachineScaleSet_otherTerminateNotification(t *tes data.ImportStep( "admin_password", ), + // turn terminate notification on again + { + Config: testAccAzureRMLinuxVirtualMachineScaleSet_otherTerminateNotification(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "terminate_notification.#", "1"), + resource.TestCheckResourceAttr(data.ResourceName, "terminate_notification.0.enabled", "true"), + ), + }, + data.ImportStep( + "admin_password", + ), }, }) } @@ -488,6 +503,16 @@ func TestAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(t *te data.ImportStep( "admin_password", ), + // turn automatic repair on again + { + Config: testAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), }, }) } diff --git a/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go b/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go index d0867d42628c..b3a70b9397ac 100644 --- a/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go +++ b/azurerm/internal/services/compute/tests/resource_arm_windows_virtual_machine_scale_set_other_test.go @@ -614,6 +614,9 @@ func TestAccAzureRMWindowsVirtualMachineScaleSet_otherTerminateNotification(t *t resource.TestCheckResourceAttr(data.ResourceName, "terminate_notification.0.enabled", "true"), ), }, + data.ImportStep( + "admin_password", + ), // turn terminate notification off { Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherTerminateNotification(data, false), @@ -626,6 +629,18 @@ func TestAccAzureRMWindowsVirtualMachineScaleSet_otherTerminateNotification(t *t data.ImportStep( "admin_password", ), + // turn terminate notification on again + { + Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherTerminateNotification(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "terminate_notification.#", "1"), + resource.TestCheckResourceAttr(data.ResourceName, "terminate_notification.0.enabled", "true"), + ), + }, + data.ImportStep( + "admin_password", + ), }, }) } @@ -658,6 +673,16 @@ func TestAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(t * data.ImportStep( "admin_password", ), + // turn automatic repair on again + { + Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), }, }) } From 6edc622308e50957a82cabc044abb709a8a2dc74 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Tue, 21 Apr 2020 07:33:40 +0800 Subject: [PATCH 3/3] Update docs since this feature is now GA --- website/docs/r/linux_virtual_machine_scale_set.html.markdown | 2 +- website/docs/r/windows_virtual_machine_scale_set.html.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/linux_virtual_machine_scale_set.html.markdown b/website/docs/r/linux_virtual_machine_scale_set.html.markdown index 918ac89154b0..b8b52404b7a6 100644 --- a/website/docs/r/linux_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/linux_virtual_machine_scale_set.html.markdown @@ -124,7 +124,7 @@ The following arguments are supported: * `automatic_instance_repair` - (Optional) A `automatic_instance_repair` block as defined below. To enable the automatic instance repair, this Virtual Machine Scale Set must have a valid `health_probe_id` or an [Application Health Extension](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-health-extension). -~> **NOTE:** Automatic repairs policy is currently under public preview, to opt-in the preview project and to get more information about this feature, please refer to [this doc](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs). +~> **NOTE:** For more information about Automatic Instance Repair, please refer to [this doc](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs). * `boot_diagnostics` - (Optional) A `boot_diagnostics` block as defined below. diff --git a/website/docs/r/windows_virtual_machine_scale_set.html.markdown b/website/docs/r/windows_virtual_machine_scale_set.html.markdown index 7ca2f90ab321..165776ab75ef 100644 --- a/website/docs/r/windows_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/windows_virtual_machine_scale_set.html.markdown @@ -114,7 +114,7 @@ The following arguments are supported: * `automatic_instance_repair` - (Optional) A `automatic_instance_repair` block as defined below. To enable the automatic instance repair, this Virtual Machine Scale Set must have a valid `health_probe_id` or an [Application Health Extension](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-health-extension). -~> **NOTE:** Automatic repairs policy is currently under public preview, to opt-in the preview project and to get more information about this feature, please refer to [this doc](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs). +~> **NOTE:** For more information about Automatic Instance Repair, please refer to [this doc](https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs). * `boot_diagnostics` - (Optional) A `boot_diagnostics` block as defined below.