provider/azurerm: VM Scale Sets - import support + fixes (#13464)

* Ensuring we base64 decode the custom data if it's base64 encoded

* Import support for VM Scale Sets

* Updating the docs to mention Import support

* Fixes #13009, where the SSH Keys would be set at the incorrect index

(leaving a null entry at the start, causing a crash on the second apply)

* Adding tests to cover the updating use-case

* Adding an import linux test

* Storing the base64 encoded value
Making custom_data a force new, since it an't be updated

* Updating the docs
This commit is contained in:
Tom Harvey 2017-04-16 23:37:28 +01:00 committed by Paul Stack
parent 1af649ed5a
commit f7f800bdfb
5 changed files with 747 additions and 313 deletions

View File

@ -0,0 +1,135 @@
package azurerm
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccAzureRMVirtualMachineScaleSet_importBasic(t *testing.T) {
resourceName := "azurerm_virtual_machine_scale_set.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSet_basic, ri, 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,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccAzureRMVirtualMachineScaleSet_importLinux(t *testing.T) {
resourceName := "azurerm_virtual_machine_scale_set.test"
ri := acctest.RandInt()
config := testAccAzureRMVirtualMachineScaleSet_linux(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMVirtualMachineScaleSetDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccAzureRMVirtualMachineScaleSet_importLoadBalancer(t *testing.T) {
resourceName := "azurerm_virtual_machine_scale_set.test"
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,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccAzureRMVirtualMachineScaleSet_importOverProvision(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 TestAccAzureRMVirtualMachineScaleSet_importExtension(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSetExtensionTemplate, 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"),
testCheckAzureRMVirtualMachineScaleSetExtension("azurerm_virtual_machine_scale_set.test"),
),
},
},
})
}
func TestAccAzureRMVirtualMachineScaleSet_importMultipleExtensions(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSetMultipleExtensionsTemplate, 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"),
testCheckAzureRMVirtualMachineScaleSetExtension("azurerm_virtual_machine_scale_set.test"),
),
},
},
})
}

View File

@ -346,7 +346,7 @@ func userDataStateFunc(v interface{}) string {
} }
} }
// Base64Encode encodes data if the input isn't already encoded using // base64Encode encodes data if the input isn't already encoded using
// base64.StdEncoding.EncodeToString. If the input is already base64 encoded, // base64.StdEncoding.EncodeToString. If the input is already base64 encoded,
// return the original input unchanged. // return the original input unchanged.
func base64Encode(data string) string { func base64Encode(data string) string {

View File

@ -19,6 +19,9 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
Read: resourceArmVirtualMachineScaleSetRead, Read: resourceArmVirtualMachineScaleSetRead,
Update: resourceArmVirtualMachineScaleSetCreate, Update: resourceArmVirtualMachineScaleSetCreate,
Delete: resourceArmVirtualMachineScaleSetDelete, Delete: resourceArmVirtualMachineScaleSetDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": { "name": {
@ -96,6 +99,7 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
"custom_data": { "custom_data": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true,
StateFunc: userDataStateFunc, StateFunc: userDataStateFunc,
}, },
}, },
@ -497,8 +501,9 @@ func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interfac
return fmt.Errorf("Error making Read request on Azure Virtual Machine Scale Set %s: %s", name, err) return fmt.Errorf("Error making Read request on Azure Virtual Machine Scale Set %s: %s", name, err)
} }
d.Set("location", resp.Location)
d.Set("name", resp.Name) d.Set("name", resp.Name)
d.Set("resource_group_name", resGroup)
d.Set("location", azureRMNormalizeLocation(*resp.Location))
if err := d.Set("sku", flattenAzureRmVirtualMachineScaleSetSku(resp.Sku)); err != nil { if err := d.Set("sku", flattenAzureRmVirtualMachineScaleSetSku(resp.Sku)); err != nil {
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Sku error: %#v", err) return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Sku error: %#v", err)
@ -509,7 +514,12 @@ func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interfac
d.Set("upgrade_policy_mode", properties.UpgradePolicy.Mode) d.Set("upgrade_policy_mode", properties.UpgradePolicy.Mode)
d.Set("overprovision", properties.Overprovision) d.Set("overprovision", properties.Overprovision)
if err := d.Set("os_profile", flattenAzureRMVirtualMachineScaleSetOsProfile(properties.VirtualMachineProfile.OsProfile)); err != nil { osProfile, err := flattenAzureRMVirtualMachineScaleSetOsProfile(properties.VirtualMachineProfile.OsProfile)
if err != nil {
return fmt.Errorf("[DEBUG] Error flattening Virtual Machine Scale Set OS Profile. Error: %#v", err)
}
if err := d.Set("os_profile", osProfile); err != nil {
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile error: %#v", err) return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile error: %#v", err)
} }
@ -578,7 +588,7 @@ func flattenAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(config *compute.Li
result["disable_password_authentication"] = *config.DisablePasswordAuthentication result["disable_password_authentication"] = *config.DisablePasswordAuthentication
if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 { if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 {
ssh_keys := make([]map[string]interface{}, len(*config.SSH.PublicKeys)) ssh_keys := make([]map[string]interface{}, 0, len(*config.SSH.PublicKeys))
for _, i := range *config.SSH.PublicKeys { for _, i := range *config.SSH.PublicKeys {
key := make(map[string]interface{}) key := make(map[string]interface{})
key["path"] = *i.Path key["path"] = *i.Path
@ -710,7 +720,7 @@ func flattenAzureRmVirtualMachineScaleSetNetworkProfile(profile *compute.Virtual
return result return result
} }
func flattenAzureRMVirtualMachineScaleSetOsProfile(profile *compute.VirtualMachineScaleSetOSProfile) []interface{} { func flattenAzureRMVirtualMachineScaleSetOsProfile(profile *compute.VirtualMachineScaleSetOSProfile) ([]interface{}, error) {
result := make(map[string]interface{}) result := make(map[string]interface{})
result["computer_name_prefix"] = *profile.ComputerNamePrefix result["computer_name_prefix"] = *profile.ComputerNamePrefix
@ -720,7 +730,7 @@ func flattenAzureRMVirtualMachineScaleSetOsProfile(profile *compute.VirtualMachi
result["custom_data"] = *profile.CustomData result["custom_data"] = *profile.CustomData
} }
return []interface{}{result} return []interface{}{result}, nil
} }
func flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(profile *compute.VirtualMachineScaleSetOSDisk) []interface{} { func flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(profile *compute.VirtualMachineScaleSetOSDisk) []interface{} {
@ -849,7 +859,11 @@ func resourceArmVirtualMachineScaleSetsOsProfileHash(v interface{}) int {
buf.WriteString(fmt.Sprintf("%s-", m["computer_name_prefix"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["computer_name_prefix"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string)))
if m["custom_data"] != nil { if m["custom_data"] != nil {
buf.WriteString(fmt.Sprintf("%s-", m["custom_data"].(string))) customData := m["custom_data"].(string)
if !isBase64Encoded(customData) {
customData = base64Encode(customData)
}
buf.WriteString(fmt.Sprintf("%s-", customData))
} }
return hashcode.String(buf.String()) return hashcode.String(buf.String())
} }
@ -1076,12 +1090,12 @@ func expandAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(d *schema.ResourceD
linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{}) linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{})
disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool) disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool)
config := &compute.LinuxConfiguration{
DisablePasswordAuthentication: &disablePasswordAuth,
}
linuxKeys := linuxConfig["ssh_keys"].([]interface{}) linuxKeys := linuxConfig["ssh_keys"].([]interface{})
sshPublicKeys := make([]compute.SSHPublicKey, 0, len(linuxKeys)) sshPublicKeys := make([]compute.SSHPublicKey, 0, len(linuxKeys))
for _, key := range linuxKeys { for _, key := range linuxKeys {
if key == nil {
continue
}
sshKey := key.(map[string]interface{}) sshKey := key.(map[string]interface{})
path := sshKey["path"].(string) path := sshKey["path"].(string)
keyData := sshKey["key_data"].(string) keyData := sshKey["key_data"].(string)
@ -1094,8 +1108,11 @@ func expandAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(d *schema.ResourceD
sshPublicKeys = append(sshPublicKeys, sshPublicKey) sshPublicKeys = append(sshPublicKeys, sshPublicKey)
} }
config.SSH = &compute.SSHConfiguration{ config := &compute.LinuxConfiguration{
DisablePasswordAuthentication: &disablePasswordAuth,
SSH: &compute.SSHConfiguration{
PublicKeys: &sshPublicKeys, PublicKeys: &sshPublicKeys,
},
} }
return config, nil return config, nil

View File

@ -10,9 +10,9 @@ import (
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
) )
func TestAccAzureRMVirtualMachineScaleSet_basicLinux(t *testing.T) { func TestAccAzureRMVirtualMachineScaleSet_basic(t *testing.T) {
ri := acctest.RandInt() ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSet_basicLinux, ri, ri, ri, ri, ri, ri, ri, ri) config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSet_basic, ri, ri, ri, ri, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders, Providers: testAccProviders,
@ -28,9 +28,36 @@ func TestAccAzureRMVirtualMachineScaleSet_basicLinux(t *testing.T) {
}) })
} }
func TestAccAzureRMVirtualMachineScaleSet_linuxUpdated(t *testing.T) {
resourceName := "azurerm_virtual_machine_scale_set.test"
ri := acctest.RandInt()
config := testAccAzureRMVirtualMachineScaleSet_linux(ri)
updatedConfig := testAccAzureRMVirtualMachineScaleSet_linuxUpdated(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMVirtualMachineScaleSetDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualMachineScaleSetExists(resourceName),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualMachineScaleSetExists(resourceName),
),
},
},
})
}
func TestAccAzureRMVirtualMachineScaleSet_basicLinux_disappears(t *testing.T) { func TestAccAzureRMVirtualMachineScaleSet_basicLinux_disappears(t *testing.T) {
ri := acctest.RandInt() ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSet_basicLinux, ri, ri, ri, ri, ri, ri, ri, ri) config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSet_basic, ri, ri, ri, ri, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders, Providers: testAccProviders,
@ -311,7 +338,7 @@ func testCheckAzureRMVirtualMachineScaleSetExtension(name string) resource.TestC
} }
} }
var testAccAzureRMVirtualMachineScaleSet_basicLinux = ` var testAccAzureRMVirtualMachineScaleSet_basic = `
resource "azurerm_resource_group" "test" { resource "azurerm_resource_group" "test" {
name = "acctestRG-%d" name = "acctestRG-%d"
location = "West US" location = "West US"
@ -382,6 +409,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
network_profile { network_profile {
name = "TestNetworkProfile-%d" name = "TestNetworkProfile-%d"
primary = true primary = true
ip_configuration { ip_configuration {
name = "TestIPConfiguration" name = "TestIPConfiguration"
subnet_id = "${azurerm_subnet.test.id}" subnet_id = "${azurerm_subnet.test.id}"
@ -404,6 +432,244 @@ resource "azurerm_virtual_machine_scale_set" "test" {
} }
` `
func testAccAzureRMVirtualMachineScaleSet_linux(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West Europe"
}
resource "azurerm_virtual_network" "test" {
name = "acctestvn-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
address_space = ["10.0.0.0/8"]
}
resource "azurerm_subnet" "test" {
name = "acctestsn-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.1.0/24"
}
resource "azurerm_storage_account" "test" {
name = "accsa%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
account_type = "Standard_LRS"
}
resource "azurerm_storage_container" "test" {
name = "acctestsc-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
storage_account_name = "${azurerm_storage_account.test.name}"
container_access_type = "private"
}
resource "azurerm_public_ip" "test" {
name = "acctestpip-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "acctestlb-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
frontend_ip_configuration {
name = "ip-address"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_backend_address_pool" "test" {
name = "acctestbap-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
}
resource "azurerm_virtual_machine_scale_set" "test" {
name = "acctestvmss-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
upgrade_policy_mode = "Automatic"
sku {
name = "Standard_A0"
tier = "Standard"
capacity = "1"
}
os_profile {
computer_name_prefix = "prefix"
admin_username = "ubuntu"
admin_password = "password"
custom_data = "custom data!"
}
os_profile_linux_config {
disable_password_authentication = true
ssh_keys {
path = "/home/ubuntu/.ssh/authorized_keys"
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDCsTcryUl51Q2VSEHqDRNmceUFo55ZtcIwxl2QITbN1RREti5ml/VTytC0yeBOvnZA4x4CFpdw/lCDPk0yrH9Ei5vVkXmOrExdTlT3qI7YaAzj1tUVlBd4S6LX1F7y6VLActvdHuDDuXZXzCDd/97420jrDfWZqJMlUK/EmCE5ParCeHIRIvmBxcEnGfFIsw8xQZl0HphxWOtJil8qsUWSdMyCiJYYQpMoMliO99X40AUc4/AlsyPyT5ddbKk08YrZ+rKDVHF7o29rh4vi5MmHkVgVQHKiKybWlHq+b71gIAUQk9wrJxD+dqt4igrmDSpIjfjwnd+l5UIn5fJSO5DYV4YT/4hwK7OKmuo7OFHD0WyY5YnkYEMtFgzemnRBdE8ulcT60DQpVgRMXFWHvhyCWy0L6sgj1QWDZlLpvsIvNfHsyhKFMG1frLnMt/nP0+YCcfg+v1JYeCKjeoJxB8DWcRBsjzItY0CGmzP8UYZiYKl/2u+2TgFS5r7NWH11bxoUzjKdaa1NLw+ieA8GlBFfCbfWe6YVB9ggUte4VtYFMZGxOjS2bAiYtfgTKFJv+XqORAwExG6+G2eDxIDyo80/OA9IG7Xv/jwQr7D6KDjDuULFcN/iTxuttoKrHeYz1hf5ZQlBdllwJHYx6fK2g8kha6r2JIQKocvsAXiiONqSfw== hello@world.com"
}
}
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 = "osDiskProfile"
caching = "ReadWrite"
create_option = "FromImage"
os_type = "linux"
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"
}
}
`, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt)
}
func testAccAzureRMVirtualMachineScaleSet_linuxUpdated(rInt int) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "West Europe"
}
resource "azurerm_virtual_network" "test" {
name = "acctestvn-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
address_space = ["10.0.0.0/8"]
}
resource "azurerm_subnet" "test" {
name = "acctestsn-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.1.0/24"
}
resource "azurerm_storage_account" "test" {
name = "accsa%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
account_type = "Standard_LRS"
}
resource "azurerm_storage_container" "test" {
name = "acctestsc-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
storage_account_name = "${azurerm_storage_account.test.name}"
container_access_type = "private"
}
resource "azurerm_public_ip" "test" {
name = "acctestpip-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
public_ip_address_allocation = "static"
}
resource "azurerm_lb" "test" {
name = "acctestlb-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
frontend_ip_configuration {
name = "ip-address"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
}
resource "azurerm_lb_backend_address_pool" "test" {
name = "acctestbap-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
}
resource "azurerm_virtual_machine_scale_set" "test" {
name = "acctestvmss-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
upgrade_policy_mode = "Automatic"
sku {
name = "Standard_A0"
tier = "Standard"
capacity = "1"
}
os_profile {
computer_name_prefix = "prefix"
admin_username = "ubuntu"
admin_password = "password"
custom_data = "custom data!"
}
os_profile_linux_config {
disable_password_authentication = true
ssh_keys {
path = "/home/ubuntu/.ssh/authorized_keys"
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDCsTcryUl51Q2VSEHqDRNmceUFo55ZtcIwxl2QITbN1RREti5ml/VTytC0yeBOvnZA4x4CFpdw/lCDPk0yrH9Ei5vVkXmOrExdTlT3qI7YaAzj1tUVlBd4S6LX1F7y6VLActvdHuDDuXZXzCDd/97420jrDfWZqJMlUK/EmCE5ParCeHIRIvmBxcEnGfFIsw8xQZl0HphxWOtJil8qsUWSdMyCiJYYQpMoMliO99X40AUc4/AlsyPyT5ddbKk08YrZ+rKDVHF7o29rh4vi5MmHkVgVQHKiKybWlHq+b71gIAUQk9wrJxD+dqt4igrmDSpIjfjwnd+l5UIn5fJSO5DYV4YT/4hwK7OKmuo7OFHD0WyY5YnkYEMtFgzemnRBdE8ulcT60DQpVgRMXFWHvhyCWy0L6sgj1QWDZlLpvsIvNfHsyhKFMG1frLnMt/nP0+YCcfg+v1JYeCKjeoJxB8DWcRBsjzItY0CGmzP8UYZiYKl/2u+2TgFS5r7NWH11bxoUzjKdaa1NLw+ieA8GlBFfCbfWe6YVB9ggUte4VtYFMZGxOjS2bAiYtfgTKFJv+XqORAwExG6+G2eDxIDyo80/OA9IG7Xv/jwQr7D6KDjDuULFcN/iTxuttoKrHeYz1hf5ZQlBdllwJHYx6fK2g8kha6r2JIQKocvsAXiiONqSfw== hello@world.com"
}
}
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 = "osDiskProfile"
caching = "ReadWrite"
create_option = "FromImage"
os_type = "linux"
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"
}
tags {
ThisIs = "a test"
}
}
`, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt)
}
var testAccAzureRMVirtualMachineScaleSetLoadbalancerTemplate = ` var testAccAzureRMVirtualMachineScaleSetLoadbalancerTemplate = `
resource "azurerm_resource_group" "test" { resource "azurerm_resource_group" "test" {
name = "acctestrg-%d" name = "acctestrg-%d"
@ -478,6 +744,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
network_profile { network_profile {
name = "TestNetworkProfile" name = "TestNetworkProfile"
primary = true primary = true
ip_configuration { ip_configuration {
name = "TestIPConfiguration" name = "TestIPConfiguration"
subnet_id = "${azurerm_subnet.test.id}" subnet_id = "${azurerm_subnet.test.id}"
@ -557,6 +824,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
network_profile { network_profile {
name = "TestNetworkProfile" name = "TestNetworkProfile"
primary = true primary = true
ip_configuration { ip_configuration {
name = "TestIPConfiguration" name = "TestIPConfiguration"
subnet_id = "${azurerm_subnet.test.id}" subnet_id = "${azurerm_subnet.test.id}"
@ -635,6 +903,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
network_profile { network_profile {
name = "TestNetworkProfile" name = "TestNetworkProfile"
primary = true primary = true
ip_configuration { ip_configuration {
name = "TestIPConfiguration" name = "TestIPConfiguration"
subnet_id = "${azurerm_subnet.test.id}" subnet_id = "${azurerm_subnet.test.id}"
@ -661,6 +930,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
type = "CustomScript" type = "CustomScript"
type_handler_version = "2.0" type_handler_version = "2.0"
auto_upgrade_minor_version = true auto_upgrade_minor_version = true
settings = <<SETTINGS settings = <<SETTINGS
{ {
"commandToExecute": "echo $HOSTNAME" "commandToExecute": "echo $HOSTNAME"
@ -675,6 +945,7 @@ SETTINGS
SETTINGS SETTINGS
} }
} }
` `
var testAccAzureRMVirtualMachineScaleSetMultipleExtensionsTemplate = ` var testAccAzureRMVirtualMachineScaleSetMultipleExtensionsTemplate = `
@ -733,6 +1004,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
network_profile { network_profile {
name = "TestNetworkProfile" name = "TestNetworkProfile"
primary = true primary = true
ip_configuration { ip_configuration {
name = "TestIPConfiguration" name = "TestIPConfiguration"
subnet_id = "${azurerm_subnet.test.id}" subnet_id = "${azurerm_subnet.test.id}"
@ -759,6 +1031,7 @@ resource "azurerm_virtual_machine_scale_set" "test" {
type = "CustomScript" type = "CustomScript"
type_handler_version = "2.0" type_handler_version = "2.0"
auto_upgrade_minor_version = true auto_upgrade_minor_version = true
settings = <<SETTINGS settings = <<SETTINGS
{ {
"commandToExecute": "echo $HOSTNAME" "commandToExecute": "echo $HOSTNAME"

View File

@ -140,7 +140,7 @@ The following arguments are supported:
* `computer_name_prefix` - (Required) Specifies the computer name prefix for all of the virtual machines in the scale set. Computer name prefixes must be 1 to 15 characters long. * `computer_name_prefix` - (Required) Specifies the computer name prefix for all of the virtual machines in the scale set. Computer name prefixes must be 1 to 15 characters long.
* `admin_username` - (Required) Specifies the administrator account name to use for all the instances of virtual machines in the scale set. * `admin_username` - (Required) Specifies the administrator account name to use for all the instances of virtual machines in the scale set.
* `admin_password` - (Required) Specifies the administrator password to use for all the instances of virtual machines in a scale set.. * `admin_password` - (Required) Specifies the administrator password to use for all the instances of virtual machines in a scale set..
* `custom_data` - (Optional) Specifies custom data to supply to the machine. On linux-based systems, this can be used as a cloud-init script. On other systems, this will be copied as a file on disk. Internally, Terraform will base64 encode this value before sending it to the API. The maximum length of the binary array is 65535 bytes. * `custom_data` - (Optional) Specifies custom data to supply to the machine. On linux-based systems, this can be used as a cloud-init script. On other systems, this will be copied as a file on disk. Internally, Terraform will base64 encode this value before sending it to the API. The maximum length of the binary array is 65535 bytes. Changing this forces a new resource to be created.
`os_profile_secrets` supports the following: `os_profile_secrets` supports the following:
@ -177,7 +177,7 @@ The following arguments are supported:
* `disable_password_authentication` - (Required) Specifies whether password authentication should be disabled. * `disable_password_authentication` - (Required) Specifies whether password authentication should be disabled.
* `ssh_keys` - (Optional) Specifies a collection of `path` and `key_data` to be placed on the virtual machine. * `ssh_keys` - (Optional) Specifies a collection of `path` and `key_data` to be placed on the virtual machine.
~> **Note:** Please note that the only allowed `path` is `/home/<username>/.ssh/authorized_keys` due to a limitation of Azure_ ~> _**Note:** Please note that the only allowed `path` is `/home/<username>/.ssh/authorized_keys` due to a limitation of Azure_
`network_profile` supports the following: `network_profile` supports the following:
@ -225,3 +225,12 @@ The following arguments are supported:
The following attributes are exported: The following attributes are exported:
* `id` - The virtual machine scale set ID. * `id` - The virtual machine scale set ID.
## Import
Virtual Machine Scale Sets can be imported using the `resource id`, e.g.
```
terraform import azurerm_virtual_machine_scale_set.scaleset1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Compute/virtualMachineScaleSets/scaleset1
```