diff --git a/azurerm/disks.go b/azurerm/disks.go index 6d975221fd2f0..f5df8686f8364 100644 --- a/azurerm/disks.go +++ b/azurerm/disks.go @@ -19,6 +19,11 @@ func storageAccountNameForUnmanagedDisk(uri string, meta interface{}) (*Unmanage return nil, fmt.Errorf("Cannot parse Disk VHD URI: %s", err) } + blobDomainSuffix := meta.(*ArmClient).environment.StorageEndpointSuffix + if !strings.HasSuffix(strings.ToLower(vhdURL.Host), strings.ToLower(blobDomainSuffix)) { + return nil, fmt.Errorf("Error: Disk VHD URI %q doesn't appear to be a Blob Storage URI (%q) - expected a suffix of %q)", uri, vhdURL.Host, blobDomainSuffix) + } + // VHD URI is in the form: https://storageAccountName.blob.core.windows.net/containerName/blobName storageAccountName := strings.Split(vhdURL.Host, ".")[0] path := strings.Split(strings.TrimPrefix(vhdURL.Path, "/"), "/") diff --git a/azurerm/import_arm_virtual_machine_data_disk_attachment_test.go b/azurerm/import_arm_virtual_machine_data_disk_attachment_test.go index de25dfa043bb8..694571b0babf0 100644 --- a/azurerm/import_arm_virtual_machine_data_disk_attachment_test.go +++ b/azurerm/import_arm_virtual_machine_data_disk_attachment_test.go @@ -7,11 +7,11 @@ import ( "github.com/hashicorp/terraform/helper/resource" ) -func TestAccAzureRMVirtualMachineDataDiskAttachment_importSingleVHD(t *testing.T) { +func TestAccAzureRMVirtualMachineDataDiskAttachment_importBasic(t *testing.T) { resourceName := "azurerm_virtual_machine_data_disk_attachment.test" ri := acctest.RandInt() location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_singleVHD(ri, location) + config := testAccAzureRMVirtualMachineDataDiskAttachment_basic(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -30,11 +30,10 @@ func TestAccAzureRMVirtualMachineDataDiskAttachment_importSingleVHD(t *testing.T }) } -func TestAccAzureRMVirtualMachineDataDiskAttachment_importSingleManagedDisk(t *testing.T) { - resourceName := "azurerm_virtual_machine_data_disk_attachment.test" +func TestAccAzureRMVirtualMachineDataDiskAttachment_importMultipleDisks(t *testing.T) { ri := acctest.RandInt() location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_singleManagedDisk(ri, location) + config := testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -45,41 +44,23 @@ func TestAccAzureRMVirtualMachineDataDiskAttachment_importSingleManagedDisk(t *t Config: config, }, { - ResourceName: resourceName, + ResourceName: "azurerm_virtual_machine_data_disk_attachment.first", ImportState: true, ImportStateVerify: true, }, - }, - }) -} - -func TestAccAzureRMVirtualMachineDataDiskAttachment_importExistingManagedDisk(t *testing.T) { - resourceName := "azurerm_virtual_machine_data_disk_attachment.test" - ri := acctest.RandInt() - location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_existingManagedDisk(ri, location) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMVirtualMachineDataDiskAttachmentDestroy, - Steps: []resource.TestStep{ - { - Config: config, - }, { - ResourceName: resourceName, + ResourceName: "azurerm_virtual_machine_data_disk_attachment.second", ImportState: true, ImportStateVerify: true, }, }, }) } - -func TestAccAzureRMVirtualMachineDataDiskAttachment_importMultipleDisks(t *testing.T) { +func TestAccAzureRMVirtualMachineDataDiskAttachment_importCustomName(t *testing.T) { + resourceName := "azurerm_virtual_machine_data_disk_attachment.test" ri := acctest.RandInt() location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(ri, location, 1, 2) + config := testAccAzureRMVirtualMachineDataDiskAttachment_customName(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -90,12 +71,7 @@ func TestAccAzureRMVirtualMachineDataDiskAttachment_importMultipleDisks(t *testi Config: config, }, { - ResourceName: "azurerm_virtual_machine_data_disk_attachment.first", - ImportState: true, - ImportStateVerify: true, - }, - { - ResourceName: "azurerm_virtual_machine_data_disk_attachment.second", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, diff --git a/azurerm/resource_arm_virtual_machine_data_disk_attachment.go b/azurerm/resource_arm_virtual_machine_data_disk_attachment.go index ce5de59cc2e70..1b478fc0b911e 100644 --- a/azurerm/resource_arm_virtual_machine_data_disk_attachment.go +++ b/azurerm/resource_arm_virtual_machine_data_disk_attachment.go @@ -2,11 +2,7 @@ package azurerm import ( "fmt" - "log" - "strings" - - "context" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/hashicorp/terraform/helper/schema" @@ -25,10 +21,11 @@ func resourceArmVirtualMachineDataDiskAttachment() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + "managed_disk_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, "virtual_machine_id": { @@ -38,48 +35,30 @@ func resourceArmVirtualMachineDataDiskAttachment() *schema.Resource { }, "lun": { - Type: schema.TypeInt, - Required: true, - }, - - "vhd_uri": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ConflictsWith: []string{"managed_disk_id", "managed_disk_type"}, + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(0), }, - "managed_disk_id": { + "create_option": { Type: schema.TypeString, Optional: true, ForceNew: true, - Computed: true, + Default: string(compute.DiskCreateOptionTypesAttach), + ValidateFunc: validation.StringInSlice([]string{}, true), DiffSuppressFunc: ignoreCaseDiffSuppressFunc, - ConflictsWith: []string{"vhd_uri"}, }, - "managed_disk_type": { + "caching": { Type: schema.TypeString, - Optional: true, - Computed: true, + Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(compute.PremiumLRS), - string(compute.StandardLRS), + string(compute.CachingTypesNone), + string(compute.CachingTypesReadOnly), + string(compute.CachingTypesReadWrite), }, true), - ConflictsWith: []string{"vhd_uri"}, - }, - - "caching": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - - "disk_size_gb": { - Type: schema.TypeInt, - Optional: true, - Computed: true, - ValidateFunc: validateDiskSizeGB, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, }, } @@ -92,8 +71,9 @@ func resourceArmVirtualMachineDataDiskAttachmentCreateUpdate(d *schema.ResourceD virtualMachineId := d.Get("virtual_machine_id").(string) parsedVirtualMachineId, err := parseAzureResourceID(virtualMachineId) if err != nil { - return err + return fmt.Errorf("Error parsing Virtual Machine ID %q: %+v", virtualMachineId, err) } + resourceGroup := parsedVirtualMachineId.ResourceGroup virtualMachineName := parsedVirtualMachineId.Path["virtualMachines"] @@ -109,70 +89,66 @@ func resourceArmVirtualMachineDataDiskAttachmentCreateUpdate(d *schema.ResourceD return fmt.Errorf("Error loading Virtual Machine %q (Resource Group %q): %+v", virtualMachineName, resourceGroup, err) } - name := d.Get("name").(string) - lun := int32(d.Get("lun").(int)) - - expandedDisk := compute.DataDisk{ - Name: utils.String(name), - Lun: utils.Int32(lun), - } - if v, ok := d.GetOk("vhd_uri"); ok { - expandedDisk.Vhd = &compute.VirtualHardDisk{ - URI: utils.String(v.(string)), - } - } else { - storageAccountType := d.Get("managed_disk_type").(string) - expandedDisk.ManagedDisk = &compute.ManagedDiskParameters{ - StorageAccountType: compute.StorageAccountTypes(storageAccountType), - } - - if v, ok := d.GetOk("managed_disk_id"); ok { - expandedDisk.ManagedDisk.ID = utils.String(v.(string)) - } + managedDiskId := d.Get("managed_disk_id").(string) + managedDisk, err := retrieveDataDiskAttachmentManagedDisk(meta, managedDiskId) + if err != nil { + return fmt.Errorf("Error retrieving Managed Disk %q: %+v", managedDiskId, err) } - if v, ok := d.GetOk("caching"); ok { - expandedDisk.Caching = compute.CachingTypes(v.(string)) + if managedDisk.Sku == nil { + return fmt.Errorf("Error: unable to determine Storage Account Type for Managed Disk %q: %+v", managedDiskId, err) } - if v, ok := d.GetOk("disk_size_gb"); ok { - expandedDisk.DiskSizeGB = utils.Int32(int32(v.(int))) - } + name := *managedDisk.Name + lun := int32(d.Get("lun").(int)) + caching := d.Get("caching").(string) + createOption := compute.DiskCreateOptionTypes(d.Get("create_option").(string)) - createOption, err := determineAzureDataDiskCreateOption(ctx, meta, expandedDisk) - if err != nil { - return fmt.Errorf("Error determining Create Option for Data Disk %q: %+v", name, err) - } - if createOption != nil { - expandedDisk.CreateOption = compute.DiskCreateOptionTypes(*createOption) + expandedDisk := compute.DataDisk{ + Name: utils.String(name), + Caching: compute.CachingTypes(caching), + CreateOption: createOption, + Lun: utils.Int32(lun), + ManagedDisk: &compute.ManagedDiskParameters{ + ID: utils.String(managedDiskId), + StorageAccountType: managedDisk.Sku.Name, + }, } disks := *virtualMachine.StorageProfile.DataDisks - if !d.IsNewResource() { - // find the existing disk, remove it from the array - dataDisks := make([]compute.DataDisk, 0) - for _, dataDisk := range disks { - if !strings.EqualFold(*dataDisk.Name, *expandedDisk.Name) { - disks = append(dataDisks, dataDisk) + if d.IsNewResource() { + disks = append(disks, expandedDisk) + } else { + // iterate over the disks and swap it out in-place + existingIndex := -1 + for i, disk := range disks { + if *disk.Name == name { + existingIndex = i + break } } - disks = dataDisks + + if existingIndex == -1 { + return fmt.Errorf("Unable to find Disk %q attached to Virtual Machine %q (Resource Group %q)", name, virtualMachineName, resourceGroup) + } + + disks[existingIndex] = expandedDisk } - disks = append(disks, expandedDisk) virtualMachine.StorageProfile.DataDisks = &disks + // TODO: verify a test case when a VM hits the `max data disks` limit (0 with an A0, 1 with an A1 etc) future, err := client.CreateOrUpdate(ctx, resourceGroup, virtualMachineName, virtualMachine) if err != nil { - return fmt.Errorf("Error updating Virtual Machine %q (Resource Group %q) with Disk %q: %+v", virtualMachineName, resourceGroup, *expandedDisk.Name, err) + return fmt.Errorf("Error updating Virtual Machine %q (Resource Group %q) with Disk %q: %+v", virtualMachineName, resourceGroup, name, err) } err = future.WaitForCompletion(ctx, client.Client) if err != nil { - return fmt.Errorf("Error waiting for Virtual Machine %q (Resource Group %q) to finish updating Disk %q: %+v", virtualMachineName, resourceGroup, *expandedDisk.Name, err) + return fmt.Errorf("Error waiting for Virtual Machine %q (Resource Group %q) to finish updating Disk %q: %+v", virtualMachineName, resourceGroup, name, err) } - d.SetId(fmt.Sprintf("%s/dataDisks/%s", virtualMachineId, *expandedDisk.Name)) + d.SetId(fmt.Sprintf("%s/dataDisks/%s", virtualMachineId, name)) return resourceArmVirtualMachineDataDiskAttachmentRead(d, meta) } @@ -203,7 +179,8 @@ func resourceArmVirtualMachineDataDiskAttachmentRead(d *schema.ResourceData, met if profile := virtualMachine.StorageProfile; profile != nil { if dataDisks := profile.DataDisks; dataDisks != nil { for _, dataDisk := range *dataDisks { - if strings.EqualFold(*dataDisk.Name, name) { + // since this field isn't (and shouldn't be) case-sensitive; we're deliberately not using `strings.Equals` + if *dataDisk.Name == name { disk = &dataDisk break } @@ -212,27 +189,19 @@ func resourceArmVirtualMachineDataDiskAttachmentRead(d *schema.ResourceData, met } if disk == nil { - log.Printf("[DEBUG] Disk %q was not found on Virtual Machine %q (Resource Group %q) - removing from state", name, virtualMachineName, resourceGroup) + log.Printf("[DEBUG] Data Disk %q was not found on Virtual Machine %q (Resource Group %q) - removing from state", name, virtualMachineName, resourceGroup) d.SetId("") return nil } - d.Set("name", name) d.Set("virtual_machine_id", virtualMachine.ID) - - if vhd := disk.Vhd; vhd != nil { - d.Set("vhd_uri", vhd.URI) - } + d.Set("caching", string(disk.Caching)) + d.Set("create_option", string(disk.CreateOption)) if managedDisk := disk.ManagedDisk; managedDisk != nil { d.Set("managed_disk_id", managedDisk.ID) - d.Set("managed_disk_type", string(managedDisk.StorageAccountType)) } - d.Set("caching", string(disk.Caching)) - if diskSizeGb := disk.DiskSizeGB; diskSizeGb != nil { - d.Set("disk_size_gb", int(*diskSizeGb)) - } if lun := disk.Lun; lun != nil { d.Set("lun", int(*lun)) } @@ -267,7 +236,8 @@ func resourceArmVirtualMachineDataDiskAttachmentDelete(d *schema.ResourceData, m dataDisks := make([]compute.DataDisk, 0) for _, dataDisk := range *virtualMachine.StorageProfile.DataDisks { - if !strings.EqualFold(*dataDisk.Name, name) { + // since this field isn't (and shouldn't be) case-sensitive; we're deliberately not using `strings.Equals` + if *dataDisk.Name != name { dataDisks = append(dataDisks, dataDisk) } } @@ -287,53 +257,25 @@ func resourceArmVirtualMachineDataDiskAttachmentDelete(d *schema.ResourceData, m return nil } -func determineAzureDataDiskCreateOption(ctx context.Context, meta interface{}, disk compute.DataDisk) (*string, error) { - attach := string(compute.DiskCreateOptionTypesAttach) - - if disk.ManagedDisk != nil && disk.ManagedDisk.ID != nil { - diskId := *disk.ManagedDisk.ID - id, err := parseAzureResourceID(diskId) - if err != nil { - return nil, fmt.Errorf("Error parsing Managed Disk Resource ID %q: %+v", diskId, err) - } - - client := meta.(*ArmClient).diskClient - resourceGroup := id.ResourceGroup - name := id.Path["disks"] - - _, err = client.Get(ctx, resourceGroup, name) - if err != nil { - return nil, fmt.Errorf("Error loading Data Disk %q (Resource Group %q): %+v", name, resourceGroup, err) - } +func retrieveDataDiskAttachmentManagedDisk(meta interface{}, id string) (*compute.Disk, error) { + client := meta.(*ArmClient).diskClient + ctx := meta.(*ArmClient).StopContext - return &attach, nil + parsedId, err := parseAzureResourceID(id) + if err != nil { + return nil, fmt.Errorf("Error parsing Managed Disk ID %q: %+v", id, err) } + resourceGroup := parsedId.ResourceGroup + name := parsedId.Path["disks"] - if disk.Vhd != nil && disk.Vhd.URI != nil { - diskId := *disk.Vhd.URI - metadata, err := storageAccountNameForUnmanagedDisk(diskId, meta) - if err != nil { - return nil, fmt.Errorf("Error locating Storage Account for Unmanaged Disk %q: %+v", diskId, err) - } - - client := meta.(*ArmClient) - storageClient, _, err := client.getBlobStorageClientForStorageAccount(ctx, metadata.ResourceGroupName, metadata.StorageAccountName) - if err != nil { - return nil, fmt.Errorf("Error getting Blob Storage Client for Account %q (Resource Group %q): %+v", metadata.StorageAccountName, metadata.ResourceGroupName, err) - } - - container := storageClient.GetContainerReference(metadata.StorageContainerName) - blob := container.GetBlobReference(metadata.BlobName) - exists, err := blob.Exists() - if err != nil { - return nil, fmt.Errorf("Error locating Blob for Unmanaged Disk %q: %+v", diskId, err) + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil, fmt.Errorf("Error Managed Disk %q (Resource Group %q) was not found!", name, resourceGroup) } - if exists { - return &attach, nil - } + return nil, fmt.Errorf("Error making Read request on Azure Managed Disk %q (Resource Group %q): %+v", name, resourceGroup, err) } - empty := string(compute.DiskCreateOptionTypesEmpty) - return &empty, nil + return &resp, nil } diff --git a/azurerm/resource_arm_virtual_machine_data_disk_attachment_test.go b/azurerm/resource_arm_virtual_machine_data_disk_attachment_test.go index 7e34c5c18e808..d83bc1ceb0698 100644 --- a/azurerm/resource_arm_virtual_machine_data_disk_attachment_test.go +++ b/azurerm/resource_arm_virtual_machine_data_disk_attachment_test.go @@ -12,11 +12,11 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func TestAccAzureRMVirtualMachineDataDiskAttachment_singleVHD(t *testing.T) { +func TestAccAzureRMVirtualMachineDataDiskAttachment_basic(t *testing.T) { resourceName := "azurerm_virtual_machine_data_disk_attachment.test" ri := acctest.RandInt() location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_singleVHD(ri, location) + config := testAccAzureRMVirtualMachineDataDiskAttachment_basic(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -26,17 +26,23 @@ func TestAccAzureRMVirtualMachineDataDiskAttachment_singleVHD(t *testing.T) { Config: config, Check: resource.ComposeTestCheckFunc( testCheckAzureRMVirtualMachineDataDiskAttachmentExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "virtual_machine_id"), + resource.TestCheckResourceAttrSet(resourceName, "managed_disk_id"), + resource.TestCheckResourceAttr(resourceName, "lun", "0"), + resource.TestCheckResourceAttr(resourceName, "caching", "None"), ), }, }, }) } -func TestAccAzureRMVirtualMachineDataDiskAttachment_singleManagedDisk(t *testing.T) { - resourceName := "azurerm_virtual_machine_data_disk_attachment.test" +func TestAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(t *testing.T) { + firstResourceName := "azurerm_virtual_machine_data_disk_attachment.first" + secondResourceName := "azurerm_virtual_machine_data_disk_attachment.second" ri := acctest.RandInt() location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_singleManagedDisk(ri, location) + config := testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -45,89 +51,53 @@ func TestAccAzureRMVirtualMachineDataDiskAttachment_singleManagedDisk(t *testing { Config: config, Check: resource.ComposeTestCheckFunc( - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(resourceName), + testCheckAzureRMVirtualMachineDataDiskAttachmentExists(firstResourceName), + resource.TestCheckResourceAttrSet(firstResourceName, "name"), + resource.TestCheckResourceAttrSet(firstResourceName, "virtual_machine_id"), + resource.TestCheckResourceAttrSet(firstResourceName, "managed_disk_id"), + resource.TestCheckResourceAttr(firstResourceName, "lun", "10"), + resource.TestCheckResourceAttr(firstResourceName, "caching", "None"), + + testCheckAzureRMVirtualMachineDataDiskAttachmentExists(secondResourceName), + resource.TestCheckResourceAttrSet(secondResourceName, "name"), + resource.TestCheckResourceAttrSet(secondResourceName, "virtual_machine_id"), + resource.TestCheckResourceAttrSet(secondResourceName, "managed_disk_id"), + resource.TestCheckResourceAttr(secondResourceName, "lun", "20"), + resource.TestCheckResourceAttr(secondResourceName, "caching", "ReadOnly"), ), }, }, }) } -func TestAccAzureRMVirtualMachineDataDiskAttachment_existingManagedDisk(t *testing.T) { +func TestAccAzureRMVirtualMachineDataDiskAttachment_updatingCaching(t *testing.T) { resourceName := "azurerm_virtual_machine_data_disk_attachment.test" ri := acctest.RandInt() location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_existingManagedDisk(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testCheckAzureRMVirtualMachineDataDiskAttachmentDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMVirtualMachineDataDiskAttachment_basic(ri, location), Check: resource.ComposeTestCheckFunc( testCheckAzureRMVirtualMachineDataDiskAttachmentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "caching", "None"), ), }, - }, - }) -} - -func TestAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(t *testing.T) { - firstResourceName := "azurerm_virtual_machine_data_disk_attachment.first" - secondResourceName := "azurerm_virtual_machine_data_disk_attachment.second" - ri := acctest.RandInt() - location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(ri, location, 1, 2) - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMVirtualMachineDataDiskAttachmentDestroy, - Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMVirtualMachineDataDiskAttachment_readOnly(ri, location), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(firstResourceName), - resource.TestCheckResourceAttr(firstResourceName, "disk_size_gb", "10"), - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(secondResourceName), - resource.TestCheckResourceAttr(secondResourceName, "disk_size_gb", "20"), - ), - }, - }, - }) -} - -func TestAccAzureRMVirtualMachineDataDiskAttachment_multipleDisksUpdate(t *testing.T) { - firstResourceName := "azurerm_virtual_machine_data_disk_attachment.first" - secondResourceName := "azurerm_virtual_machine_data_disk_attachment.second" - ri := acctest.RandInt() - location := testLocation() - config := testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(ri, location, 1, 2) - updatedConfig := testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(ri, location, 3, 2) - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMVirtualMachineDataDiskAttachmentDestroy, - Steps: []resource.TestStep{ - { - Config: config, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(firstResourceName), - resource.TestCheckResourceAttr(firstResourceName, "disk_size_gb", "10"), - resource.TestCheckResourceAttr(firstResourceName, "lun", "1"), - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(secondResourceName), - resource.TestCheckResourceAttr(secondResourceName, "disk_size_gb", "20"), - resource.TestCheckResourceAttr(secondResourceName, "lun", "2"), + testCheckAzureRMVirtualMachineDataDiskAttachmentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "caching", "ReadOnly"), ), }, { - Config: updatedConfig, + Config: testAccAzureRMVirtualMachineDataDiskAttachment_readWrite(ri, location), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(firstResourceName), - resource.TestCheckResourceAttr(firstResourceName, "disk_size_gb", "10"), - resource.TestCheckResourceAttr(firstResourceName, "lun", "3"), - testCheckAzureRMVirtualMachineDataDiskAttachmentExists(secondResourceName), - resource.TestCheckResourceAttr(secondResourceName, "disk_size_gb", "20"), - resource.TestCheckResourceAttr(secondResourceName, "lun", "2"), + testCheckAzureRMVirtualMachineDataDiskAttachmentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "caching", "ReadWrite"), ), }, }, @@ -216,259 +186,79 @@ func testCheckAzureRMVirtualMachineDataDiskAttachmentDestroy(s *terraform.State) return nil } -func testAccAzureRMVirtualMachineDataDiskAttachment_singleVHD(rInt int, location string) string { +func testAccAzureRMVirtualMachineDataDiskAttachment_basic(rInt int, location string) string { + template := testAccAzureRMVirtualMachineDataDiskAttachment_template(rInt, location) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - 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_network_interface" "test" { - name = "acctni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "dynamic" - } -} - -resource "azurerm_storage_account" "test" { - name = "accsa%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "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" "test" { - name = "acctvm-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - vm_size = "Standard_F2" - - storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } - - storage_os_disk { - name = "osd-%d" - vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd" - caching = "ReadWrite" - create_option = "FromImage" - disk_size_gb = "45" - } - - os_profile { - computer_name = "hn%d" - admin_username = "testadmin" - admin_password = "Password1234!" - } - - os_profile_linux_config { - disable_password_authentication = false - } -} +%s resource "azurerm_virtual_machine_data_disk_attachment" "test" { - name = "disk1-%d" + managed_disk_id = "${azurerm_managed_disk.test.id}" virtual_machine_id = "${azurerm_virtual_machine.test.id}" - vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/mydatadisk1.vhd" - disk_size_gb = 10 - lun = 1 + lun = "0" + caching = "None" } -`, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt) +`, template) } -func testAccAzureRMVirtualMachineDataDiskAttachment_singleManagedDisk(rInt int, location string) string { +func testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(rInt int, location string) string { + template := testAccAzureRMVirtualMachineDataDiskAttachment_template(rInt, location) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - 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" -} +%s -resource "azurerm_network_interface" "test" { - name = "acctni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "dynamic" - } +resource "azurerm_virtual_machine_data_disk_attachment" "first" { + managed_disk_id = "${azurerm_managed_disk.test.id}" + virtual_machine_id = "${azurerm_virtual_machine.test.id}" + lun = "10" + caching = "None" } -resource "azurerm_virtual_machine" "test" { - name = "acctvm-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - vm_size = "Standard_F2" - - storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } - - storage_os_disk { - name = "osd-%d" - caching = "ReadWrite" - create_option = "FromImage" - disk_size_gb = "50" - managed_disk_type = "Standard_LRS" - } - - os_profile { - computer_name = "hn%d" - admin_username = "testadmin" - admin_password = "Password1234!" - } - - os_profile_linux_config { - disable_password_authentication = false - } +resource "azurerm_managed_disk" "second" { + name = "%d-disk2" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_type = "Standard_LRS" + create_option = "Empty" + disk_size_gb = 10 } -resource "azurerm_virtual_machine_data_disk_attachment" "test" { - name = "disk1-%d" +resource "azurerm_virtual_machine_data_disk_attachment" "second" { + managed_disk_id = "${azurerm_managed_disk.second.id}" virtual_machine_id = "${azurerm_virtual_machine.test.id}" - managed_disk_type = "Standard_LRS" - disk_size_gb = 10 - lun = 1 + lun = "20" + caching = "ReadOnly" } -`, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt, rInt) +`, template, rInt) } -func testAccAzureRMVirtualMachineDataDiskAttachment_existingManagedDisk(rInt int, location string) string { +func testAccAzureRMVirtualMachineDataDiskAttachment_readOnly(rInt int, location string) string { + template := testAccAzureRMVirtualMachineDataDiskAttachment_template(rInt, location) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - 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_network_interface" "test" { - name = "acctni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +%s - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "dynamic" - } +resource "azurerm_virtual_machine_data_disk_attachment" "test" { + managed_disk_id = "${azurerm_managed_disk.test.id}" + virtual_machine_id = "${azurerm_virtual_machine.test.id}" + lun = "0" + caching = "ReadOnly" } - -resource "azurerm_virtual_machine" "test" { - name = "acctvm-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - vm_size = "Standard_F2" - - storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } - - storage_os_disk { - name = "osd-%d" - caching = "ReadWrite" - create_option = "FromImage" - disk_size_gb = "50" - managed_disk_type = "Standard_LRS" - } - - os_profile { - computer_name = "hn%d" - admin_username = "testadmin" - admin_password = "Password1234!" - } - - os_profile_linux_config { - disable_password_authentication = false - } +`, template) } -resource "azurerm_managed_disk" "test" { - name = "acctestd-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = 10 -} +func testAccAzureRMVirtualMachineDataDiskAttachment_readWrite(rInt int, location string) string { + template := testAccAzureRMVirtualMachineDataDiskAttachment_template(rInt, location) + return fmt.Sprintf(` +%s resource "azurerm_virtual_machine_data_disk_attachment" "test" { - name = "${azurerm_managed_disk.test.name}" - virtual_machine_id = "${azurerm_virtual_machine.test.id}" managed_disk_id = "${azurerm_managed_disk.test.id}" - managed_disk_type = "Standard_LRS" - lun = 1 + virtual_machine_id = "${azurerm_virtual_machine.test.id}" + lun = "0" + caching = "ReadWrite" } -`, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt, rInt) +`, template) } -func testAccAzureRMVirtualMachineDataDiskAttachment_multipleDisks(rInt int, location string, firstDiskLun int, secondDiskLun int) string { +func testAccAzureRMVirtualMachineDataDiskAttachment_template(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -516,10 +306,9 @@ resource "azurerm_virtual_machine" "test" { } storage_os_disk { - name = "osd-%d" - caching = "ReadWrite" - create_option = "FromImage" - disk_size_gb = "50" + name = "myosdisk1" + caching = "ReadWrite" + create_option = "FromImage" managed_disk_type = "Standard_LRS" } @@ -534,20 +323,13 @@ resource "azurerm_virtual_machine" "test" { } } -resource "azurerm_virtual_machine_data_disk_attachment" "first" { - name = "disk1-%d" - virtual_machine_id = "${azurerm_virtual_machine.test.id}" - managed_disk_type = "Standard_LRS" - disk_size_gb = 10 - lun = %d -} - -resource "azurerm_virtual_machine_data_disk_attachment" "second" { - name = "disk2-%d" - virtual_machine_id = "${azurerm_virtual_machine.test.id}" - managed_disk_type = "Standard_LRS" - disk_size_gb = 20 - lun = %d +resource "azurerm_managed_disk" "test" { + name = "%d-disk1" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_type = "Standard_LRS" + create_option = "Empty" + disk_size_gb = 10 } -`, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt, rInt, firstDiskLun, rInt, secondDiskLun) +`, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt) } diff --git a/website/docs/r/virtual_machine_data_disk_attachment.html.markdown b/website/docs/r/virtual_machine_data_disk_attachment.html.markdown index 82179ba3b24b8..835c3a0c1f86f 100644 --- a/website/docs/r/virtual_machine_data_disk_attachment.html.markdown +++ b/website/docs/r/virtual_machine_data_disk_attachment.html.markdown @@ -12,6 +12,8 @@ Manages attaching a Disk to a Virtual Machine. ~> **NOTE:** Data Disks can be attached either directly on the `azurerm_virtual_machine` resource, or using the `azurerm_virtual_machine_data_disk_attachment` resource - but the two cannot be used together. If both are used against the same Virtual Machine, spurious changes will occur. +-> **Please Note:** only Managed Disks are supported via this separate resource, Unmanaged Disks can be attached using the `storage_data_disk` block in the `azurerm_virtual_machine` resource. + ## Example Usage ```hcl @@ -86,13 +88,20 @@ resource "azurerm_virtual_machine" "test" { } } +resource "azurerm_managed_disk" "test" { + name = "${local.vm_name}-disk1" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_type = "Standard_LRS" + create_option = "Empty" + disk_size_gb = 10 +} + resource "azurerm_virtual_machine_data_disk_attachment" "test" { - name = "${local.vm_name}-data1" - virtual_machine_id = "${azurerm_virtual_machine.main.id}" - create_option = "Empty" - managed_disk_type = "Standard_LRS" - disk_size_gb = 10 - lun = 1 + managed_disk_id = "${azurerm_managed_disk.test.id}" + virtual_machine_id = "${azurerm_virtual_machine.windows.id}" + lun = "10" + caching = "ReadWrite" } ``` @@ -100,23 +109,15 @@ resource "azurerm_virtual_machine_data_disk_attachment" "test" { The following arguments are supported: -* `name` - (Required) The name of this Disk Attachment, which needs to be unique within the Virtual Machine. Changing this forces a new resource to be created. - * `virtual_machine_id` - (Required) The ID of the Virtual Machine to which the Data Disk should be attached. Changing this forces a new resource to be created. -* `create_option` - (Required) The Create Option of the Data Disk, such as `Empty` or `Attach`. Changing this forces a new resource to be created. +* `managed_disk_id` - (Required) The ID of an existing Managed Disk which should be attached. Changing this forces a new resource to be created. -* `lun` - (Required) The Logical Unit Number of the Data Disk, which needs to be unique within the Virtual Machine. +* `lun` - (Required) The Logical Unit Number of the Data Disk, which needs to be unique within the Virtual Machine. Changing this forces a new resource to be created. -* `vhd_uri` - (Optional) The URI of a Blob in a Storage Account where the VHD for this Disk should be placed. Cannot be specified when `managed_disk_id` or `managed_disk_type` is specified. +* `caching` - (Required) Specifies the caching requirements for this Data Disk. Possible values include `None`, `ReadOnly` and `ReadWrite`. -* `managed_disk_id` - (Optional) The ID of an existing Managed Disk which should be attached. When set, `create_option` should be set to `Attach`. - -* `managed_disk_type` - (Optional) Specifies the type of managed disk to create. Value you must be either `Standard_LRS` or `Premium_LRS`. Cannot be used when `vhd_uri` is specified. - -* `caching` - (Optional) Specifies the caching requirements for this Data Disk, such as `ReadWrite`. - -* `disk_size_gb` - (Optional) Specifies the size of the Data Disk in GB. +* `create_option` - (Optional) The Create Option of the Data Disk, such as `Empty` or `Attach`. Defaults to `Attach`. Changing this forces a new resource to be created. ## Attributes Reference @@ -131,3 +132,5 @@ Virtual Machines Data Disk Attachments can be imported using the `resource id`, ```hcl terraform import azurerm_virtual_machine_data_disk_attachment.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/microsoft.compute/virtualMachines/machine1/dataDisks/disk1 ``` + +-> **Please Note:** This is a Terraform Unique ID matching the format: `{virtualMachineID}/dataDisks/{diskName}` \ No newline at end of file