mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
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:
parent
1af649ed5a
commit
f7f800bdfb
@ -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"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@ -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 {
|
||||||
|
@ -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{
|
||||||
PublicKeys: &sshPublicKeys,
|
DisablePasswordAuthentication: &disablePasswordAuth,
|
||||||
|
SSH: &compute.SSHConfiguration{
|
||||||
|
PublicKeys: &sshPublicKeys,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||||
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user