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 a5561fc3e564..fd87400734b0 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 @@ -95,6 +95,8 @@ func resourceArmLinuxVirtualMachineScaleSet() *schema.Resource { "automatic_os_upgrade_policy": VirtualMachineScaleSetAutomatedOSUpgradePolicySchema(), + "automatic_instance_repair": VirtualMachineScaleSetAutomaticRepairsPolicySchema(), + "boot_diagnostics": bootDiagnosticsSchema(), "computer_name_prefix": { @@ -430,6 +432,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), @@ -445,6 +449,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)), @@ -681,6 +686,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) @@ -792,6 +802,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 ab71a6caeb8d..1d834071c844 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 @@ -96,6 +96,8 @@ func resourceArmWindowsVirtualMachineScaleSet() *schema.Resource { "automatic_os_upgrade_policy": VirtualMachineScaleSetAutomatedOSUpgradePolicySchema(), + "automatic_instance_repair": VirtualMachineScaleSetAutomaticRepairsPolicySchema(), + "boot_diagnostics": bootDiagnosticsSchema(), "computer_name_prefix": { @@ -456,6 +458,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), @@ -471,6 +475,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)), @@ -711,6 +716,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) @@ -822,6 +833,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 aceab5357b25..a4ea0f662e90 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 @@ -439,6 +439,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), @@ -451,6 +454,60 @@ 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", + ), + }, + }) +} + +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", + ), + // turn automatic repair on again + { + Config: testAccAzureRMLinuxVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), }, }) } @@ -1288,21 +1345,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 } } @@ -1353,8 +1410,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 { @@ -1388,6 +1443,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) } @@ -1399,8 +1456,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" @@ -1408,13 +1465,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 } } @@ -1465,8 +1522,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 { @@ -1500,6 +1555,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) } @@ -1595,3 +1652,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 d9439ac20ebf..78c1bab89ef2 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 @@ -576,7 +576,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), @@ -598,7 +598,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 { @@ -609,6 +609,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), @@ -621,6 +624,60 @@ 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", + ), + }, + }) +} + +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", + ), + // turn automatic repair on again + { + Config: testAccAzureRMWindowsVirtualMachineScaleSet_otherAutomaticRepairsPolicy(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMLinuxVirtualMachineScaleSetExists(data.ResourceName), + ), + }, + data.ImportStep( + "admin_password", + ), }, }) } @@ -1562,8 +1619,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 @@ -1727,21 +1784,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 } } @@ -1792,8 +1849,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" @@ -1825,6 +1880,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) } @@ -1836,8 +1893,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" @@ -1845,13 +1902,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 } } @@ -1902,8 +1959,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" @@ -1935,6 +1990,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) } @@ -2024,3 +2081,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 d60b86b12ebd..617c3b05bc14 100644 --- a/azurerm/internal/services/compute/virtual_machine_scale_set.go +++ b/azurerm/internal/services/compute/virtual_machine_scale_set.go @@ -1229,3 +1229,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..b8b52404b7a6 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:** 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. * `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..165776ab75ef 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:** 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. * `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.