Fix azurerm_virtual_machine_scale_sets (#11516)
* Image and vhdcontainers are mutually exclusive. * Fix ip configuration handling and update support for load balancer backend pools. * Fix os disk handling. * Remove os_type from disk hash. * Load balancer pools should not be computed. * Add support for the overprovision property. * Update documentation. * Create acceptance test for scale set lb changes. * Create acceptance test for scale set overprovisioning.
This commit is contained in:
parent
c6619b3495
commit
512b155f64
|
@ -64,6 +64,11 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
|
|||
Required: true,
|
||||
},
|
||||
|
||||
"overprovision": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"os_profile": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Required: true,
|
||||
|
@ -250,7 +255,6 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
|
|||
"load_balancer_backend_address_pool_ids": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: schema.HashString,
|
||||
},
|
||||
|
@ -276,12 +280,11 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
|
|||
"image": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"vhd_containers": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Required: true,
|
||||
Optional: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: schema.HashString,
|
||||
},
|
||||
|
@ -294,7 +297,6 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
|
|||
"os_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"create_option": &schema.Schema{
|
||||
|
@ -378,6 +380,7 @@ func resourceArmVirtualMachineScaleSetCreate(d *schema.ResourceData, meta interf
|
|||
}
|
||||
|
||||
updatePolicy := d.Get("upgrade_policy_mode").(string)
|
||||
overprovision := d.Get("overprovision").(bool)
|
||||
scaleSetProps := compute.VirtualMachineScaleSetProperties{
|
||||
UpgradePolicy: &compute.UpgradePolicy{
|
||||
Mode: compute.UpgradeMode(updatePolicy),
|
||||
|
@ -387,6 +390,7 @@ func resourceArmVirtualMachineScaleSetCreate(d *schema.ResourceData, meta interf
|
|||
StorageProfile: &storageProfile,
|
||||
OsProfile: osProfile,
|
||||
},
|
||||
Overprovision: &overprovision,
|
||||
}
|
||||
|
||||
scaleSetParams := compute.VirtualMachineScaleSet{
|
||||
|
@ -444,6 +448,7 @@ func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interfac
|
|||
properties := resp.VirtualMachineScaleSetProperties
|
||||
|
||||
d.Set("upgrade_policy_mode", properties.UpgradePolicy.Mode)
|
||||
d.Set("overprovision", properties.Overprovision)
|
||||
|
||||
if err := d.Set("os_profile", flattenAzureRMVirtualMachineScaleSetOsProfile(properties.VirtualMachineProfile.OsProfile)); err != nil {
|
||||
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile error: %#v", err)
|
||||
|
@ -619,12 +624,14 @@ func flattenAzureRmVirtualMachineScaleSetNetworkProfile(profile *compute.Virtual
|
|||
}
|
||||
|
||||
if properties.LoadBalancerBackendAddressPools != nil {
|
||||
addressPools := make([]string, 0, len(*properties.LoadBalancerBackendAddressPools))
|
||||
addressPools := make([]interface{}, 0, len(*properties.LoadBalancerBackendAddressPools))
|
||||
for _, pool := range *properties.LoadBalancerBackendAddressPools {
|
||||
addressPools = append(addressPools, *pool.ID)
|
||||
}
|
||||
config["load_balancer_backend_address_pool_ids"] = addressPools
|
||||
config["load_balancer_backend_address_pool_ids"] = schema.NewSet(schema.HashString, addressPools)
|
||||
}
|
||||
|
||||
ipConfigs = append(ipConfigs, config)
|
||||
}
|
||||
|
||||
s["ip_configuration"] = ipConfigs
|
||||
|
@ -656,14 +663,17 @@ func flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(profile *compute.V
|
|||
result["image"] = *profile.Image.URI
|
||||
}
|
||||
|
||||
if profile.VhdContainers != nil {
|
||||
containers := make([]interface{}, 0, len(*profile.VhdContainers))
|
||||
for _, container := range *profile.VhdContainers {
|
||||
containers = append(containers, container)
|
||||
}
|
||||
result["vhd_containers"] = schema.NewSet(schema.HashString, containers)
|
||||
}
|
||||
|
||||
result["caching"] = profile.Caching
|
||||
result["create_option"] = profile.CreateOption
|
||||
result["os_type"] = profile.OsType
|
||||
|
||||
return []interface{}{result}
|
||||
}
|
||||
|
@ -721,9 +731,6 @@ func resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash(v interface{}) in
|
|||
if m["image"] != nil {
|
||||
buf.WriteString(fmt.Sprintf("%s-", m["image"].(string)))
|
||||
}
|
||||
if m["os_type"] != nil {
|
||||
buf.WriteString(fmt.Sprintf("%s-", m["os_type"].(string)))
|
||||
}
|
||||
|
||||
return hashcode.String(buf.String())
|
||||
}
|
||||
|
@ -813,10 +820,18 @@ func expandAzureRmVirtualMachineScaleSetNetworkProfile(d *schema.ResourceData) *
|
|||
},
|
||||
},
|
||||
}
|
||||
//TODO: Add the support for the load balancers when it drops
|
||||
//if v := ipconfig["load_balancer_backend_address_pool_ids"]; v != nil {
|
||||
//
|
||||
//}
|
||||
|
||||
if v := ipconfig["load_balancer_backend_address_pool_ids"]; v != nil {
|
||||
pools := v.(*schema.Set).List()
|
||||
resources := make([]compute.SubResource, 0, len(pools))
|
||||
for _, p := range pools {
|
||||
id := p.(string)
|
||||
resources = append(resources, compute.SubResource{
|
||||
ID: &id,
|
||||
})
|
||||
}
|
||||
ipConfiguration.LoadBalancerBackendAddressPools = &resources
|
||||
}
|
||||
|
||||
ipConfigurations = append(ipConfigurations, ipConfiguration)
|
||||
}
|
||||
|
@ -897,25 +912,25 @@ func expandAzureRMVirtualMachineScaleSetsStorageProfileOsDisk(d *schema.Resource
|
|||
osType := osDiskConfig["os_type"].(string)
|
||||
createOption := osDiskConfig["create_option"].(string)
|
||||
|
||||
var vhdContainers []string
|
||||
containers := osDiskConfig["vhd_containers"].(*schema.Set).List()
|
||||
for _, v := range containers {
|
||||
str := v.(string)
|
||||
vhdContainers = append(vhdContainers, str)
|
||||
}
|
||||
|
||||
osDisk := &compute.VirtualMachineScaleSetOSDisk{
|
||||
Name: &name,
|
||||
Caching: compute.CachingTypes(caching),
|
||||
OsType: compute.OperatingSystemTypes(osType),
|
||||
CreateOption: compute.DiskCreateOptionTypes(createOption),
|
||||
VhdContainers: &vhdContainers,
|
||||
}
|
||||
|
||||
if image != "" {
|
||||
osDisk.Image = &compute.VirtualHardDisk{
|
||||
URI: &image,
|
||||
}
|
||||
} else {
|
||||
var vhdContainers []string
|
||||
containers := osDiskConfig["vhd_containers"].(*schema.Set).List()
|
||||
for _, v := range containers {
|
||||
str := v.(string)
|
||||
vhdContainers = append(vhdContainers, str)
|
||||
}
|
||||
osDisk.VhdContainers = &vhdContainers
|
||||
}
|
||||
|
||||
return osDisk, nil
|
||||
|
|
|
@ -48,6 +48,44 @@ func TestAccAzureRMVirtualMachineScaleSet_basicLinux_disappears(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAzureRMVirtualMachineScaleSet_loadBalancer(t *testing.T) {
|
||||
ri := acctest.RandInt()
|
||||
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSetLoadbalancerTemplate, ri, ri, ri, ri, ri, ri, ri)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testCheckAzureRMVirtualMachineScaleSetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: config,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testCheckAzureRMVirtualMachineScaleSetExists("azurerm_virtual_machine_scale_set.test"),
|
||||
testCheckAzureRMVirtualMachineScaleSetHasLoadbalancer("azurerm_virtual_machine_scale_set.test"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAzureRMVirtualMachineScaleSet_overprovision(t *testing.T) {
|
||||
ri := acctest.RandInt()
|
||||
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSetOverprovisionTemplate, ri, ri, ri, ri, ri, ri)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testCheckAzureRMVirtualMachineScaleSetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: config,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testCheckAzureRMVirtualMachineScaleSetExists("azurerm_virtual_machine_scale_set.test"),
|
||||
testCheckAzureRMVirtualMachineScaleSetOverprovision("azurerm_virtual_machine_scale_set.test"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testCheckAzureRMVirtualMachineScaleSetExists(name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
// Ensure we have enough information in state to look up in API
|
||||
|
@ -127,6 +165,81 @@ func testCheckAzureRMVirtualMachineScaleSetDestroy(s *terraform.State) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func testCheckAzureRMVirtualMachineScaleSetHasLoadbalancer(name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
// Ensure we have enough information in state to look up in API
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", name)
|
||||
}
|
||||
|
||||
name := rs.Primary.Attributes["name"]
|
||||
resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
|
||||
if !hasResourceGroup {
|
||||
return fmt.Errorf("Bad: no resource group found in state for virtual machine: scale set %s", name)
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*ArmClient).vmScaleSetClient
|
||||
resp, err := conn.Get(resourceGroup, name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Bad: Get on vmScaleSetClient: %s", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return fmt.Errorf("Bad: VirtualMachineScaleSet %q (resource group: %q) does not exist", name, resourceGroup)
|
||||
}
|
||||
|
||||
n := resp.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations
|
||||
if n == nil || len(*n) == 0 {
|
||||
return fmt.Errorf("Bad: Could not get network interface configurations for scale set %v", name)
|
||||
}
|
||||
|
||||
ip := (*n)[0].IPConfigurations
|
||||
if ip == nil || len(*ip) == 0 {
|
||||
return fmt.Errorf("Bad: Could not get ip configurations for scale set %v", name)
|
||||
}
|
||||
|
||||
pools := (*ip)[0].LoadBalancerBackendAddressPools
|
||||
if pools == nil || len(*pools) == 0 {
|
||||
return fmt.Errorf("Bad: Load balancer backend pools is empty for scale set %v", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testCheckAzureRMVirtualMachineScaleSetOverprovision(name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
// Ensure we have enough information in state to look up in API
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", name)
|
||||
}
|
||||
|
||||
name := rs.Primary.Attributes["name"]
|
||||
resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
|
||||
if !hasResourceGroup {
|
||||
return fmt.Errorf("Bad: no resource group found in state for virtual machine: scale set %s", name)
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*ArmClient).vmScaleSetClient
|
||||
resp, err := conn.Get(resourceGroup, name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Bad: Get on vmScaleSetClient: %s", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return fmt.Errorf("Bad: VirtualMachineScaleSet %q (resource group: %q) does not exist", name, resourceGroup)
|
||||
}
|
||||
|
||||
if *resp.Overprovision {
|
||||
return fmt.Errorf("Bad: Overprovision should have been false for scale set %v", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var testAccAzureRMVirtualMachineScaleSet_basicLinux = `
|
||||
resource "azurerm_resource_group" "test" {
|
||||
name = "acctestRG-%d"
|
||||
|
@ -219,3 +332,178 @@ resource "azurerm_virtual_machine_scale_set" "test" {
|
|||
}
|
||||
}
|
||||
`
|
||||
|
||||
var testAccAzureRMVirtualMachineScaleSetLoadbalancerTemplate = `
|
||||
resource "azurerm_resource_group" "test" {
|
||||
name = "acctestrg-%d"
|
||||
location = "southcentralus"
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_network" "test" {
|
||||
name = "acctvn-%d"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
location = "southcentralus"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "test" {
|
||||
name = "acctsub-%d"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
virtual_network_name = "${azurerm_virtual_network.test.name}"
|
||||
address_prefix = "10.0.2.0/24"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_account" "test" {
|
||||
name = "accsa%d"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
location = "southcentralus"
|
||||
account_type = "Standard_LRS"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_container" "test" {
|
||||
name = "vhds"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
storage_account_name = "${azurerm_storage_account.test.name}"
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
resource "azurerm_lb" "test" {
|
||||
name = "acctestlb-%d"
|
||||
location = "southcentralus"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
|
||||
frontend_ip_configuration {
|
||||
name = "default"
|
||||
subnet_id = "${azurerm_subnet.test.id}"
|
||||
private_ip_address_allocation = "Dynamic"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_lb_backend_address_pool" "test" {
|
||||
name = "test"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
location = "southcentralus"
|
||||
loadbalancer_id = "${azurerm_lb.test.id}"
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_machine_scale_set" "test" {
|
||||
name = "acctvmss-%d"
|
||||
location = "southcentralus"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
upgrade_policy_mode = "Manual"
|
||||
|
||||
sku {
|
||||
name = "Standard_A0"
|
||||
tier = "Standard"
|
||||
capacity = 1
|
||||
}
|
||||
|
||||
os_profile {
|
||||
computer_name_prefix = "testvm-%d"
|
||||
admin_username = "myadmin"
|
||||
admin_password = "Passwword1234"
|
||||
}
|
||||
|
||||
network_profile {
|
||||
name = "TestNetworkProfile"
|
||||
primary = true
|
||||
ip_configuration {
|
||||
name = "TestIPConfiguration"
|
||||
subnet_id = "${azurerm_subnet.test.id}"
|
||||
load_balancer_backend_address_pool_ids = [ "${azurerm_lb_backend_address_pool.test.id}" ]
|
||||
}
|
||||
}
|
||||
|
||||
storage_profile_os_disk {
|
||||
name = "os-disk"
|
||||
caching = "ReadWrite"
|
||||
create_option = "FromImage"
|
||||
vhd_containers = [ "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}" ]
|
||||
}
|
||||
|
||||
storage_profile_image_reference {
|
||||
publisher = "Canonical"
|
||||
offer = "UbuntuServer"
|
||||
sku = "14.04.2-LTS"
|
||||
version = "latest"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var testAccAzureRMVirtualMachineScaleSetOverprovisionTemplate = `
|
||||
resource "azurerm_resource_group" "test" {
|
||||
name = "acctestrg-%d"
|
||||
location = "southcentralus"
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_network" "test" {
|
||||
name = "acctvn-%d"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
location = "southcentralus"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "test" {
|
||||
name = "acctsub-%d"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
virtual_network_name = "${azurerm_virtual_network.test.name}"
|
||||
address_prefix = "10.0.2.0/24"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_account" "test" {
|
||||
name = "accsa%d"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
location = "southcentralus"
|
||||
account_type = "Standard_LRS"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_container" "test" {
|
||||
name = "vhds"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
storage_account_name = "${azurerm_storage_account.test.name}"
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_machine_scale_set" "test" {
|
||||
name = "acctvmss-%d"
|
||||
location = "southcentralus"
|
||||
resource_group_name = "${azurerm_resource_group.test.name}"
|
||||
upgrade_policy_mode = "Manual"
|
||||
overprovision = false
|
||||
|
||||
sku {
|
||||
name = "Standard_A0"
|
||||
tier = "Standard"
|
||||
capacity = 1
|
||||
}
|
||||
|
||||
os_profile {
|
||||
computer_name_prefix = "testvm-%d"
|
||||
admin_username = "myadmin"
|
||||
admin_password = "Passwword1234"
|
||||
}
|
||||
|
||||
network_profile {
|
||||
name = "TestNetworkProfile"
|
||||
primary = true
|
||||
ip_configuration {
|
||||
name = "TestIPConfiguration"
|
||||
subnet_id = "${azurerm_subnet.test.id}"
|
||||
}
|
||||
}
|
||||
|
||||
storage_profile_os_disk {
|
||||
name = "os-disk"
|
||||
caching = "ReadWrite"
|
||||
create_option = "FromImage"
|
||||
vhd_containers = [ "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}" ]
|
||||
}
|
||||
|
||||
storage_profile_image_reference {
|
||||
publisher = "Canonical"
|
||||
offer = "UbuntuServer"
|
||||
sku = "14.04.2-LTS"
|
||||
version = "latest"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
|
@ -112,6 +112,7 @@ The following arguments are supported:
|
|||
* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created.
|
||||
* `sku` - (Required) A sku block as documented below.
|
||||
* `upgrade_policy_mode` - (Required) Specifies the mode of an upgrade to virtual machines in the scale set. Possible values, `Manual` or `Automatic`.
|
||||
* `overprovision` - (Optional) Specifies whether the virtual machine scale set should be overprovisioned.
|
||||
* `os_profile` - (Required) A Virtual Machine OS Profile block as documented below.
|
||||
* `os_profile_secrets` - (Optional) A collection of Secret blocks as documented below.
|
||||
* `os_profile_windows_config` - (Required, when a windows machine) A Windows config block as documented below.
|
||||
|
@ -188,11 +189,12 @@ The following arguments are supported:
|
|||
`storage_profile_os_disk` supports the following:
|
||||
|
||||
* `name` - (Required) Specifies the disk name.
|
||||
* `vhd_containers` - (Required) Specifies the vhd uri.
|
||||
* `vhd_containers` - (Optional) Specifies the vhd uri. This property is ignored if using a custom image.
|
||||
* `create_option` - (Required) Specifies how the virtual machine should be created. The only possible option is `FromImage`.
|
||||
* `caching` - (Required) Specifies the caching requirements.
|
||||
* `image` - (Optional) Specifies the blob uri for user image. A virtual machine scale set creates an os disk in the same container as the user image.
|
||||
Updating the osDisk image causes the existing disk to be deleted and a new one created with the new image. If the VM scale set is in Manual upgrade mode then the virtual machines are not updated until they have manualUpgrade applied to them.
|
||||
If this property is set then vhd_containers is ignored.
|
||||
* `os_type` - (Optional) Specifies the operating system Type, valid values are windows, linux.
|
||||
|
||||
`storage_profile_image_reference` supports the following:
|
||||
|
|
Loading…
Reference in New Issue