github.com/bpineau/terraform@v0.8.0-rc1.0.20161126184705-a8886012d185/builtin/providers/azurerm/resource_arm_virtual_machine.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"net/url"
     9  	"strings"
    10  
    11  	"github.com/Azure/azure-sdk-for-go/arm/compute"
    12  	"github.com/hashicorp/terraform/helper/hashcode"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  	riviera "github.com/jen20/riviera/azure"
    15  )
    16  
    17  func resourceArmVirtualMachine() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceArmVirtualMachineCreate,
    20  		Read:   resourceArmVirtualMachineRead,
    21  		Update: resourceArmVirtualMachineCreate,
    22  		Delete: resourceArmVirtualMachineDelete,
    23  		Importer: &schema.ResourceImporter{
    24  			State: schema.ImportStatePassthrough,
    25  		},
    26  
    27  		Schema: map[string]*schema.Schema{
    28  			"name": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  
    34  			"location": {
    35  				Type:      schema.TypeString,
    36  				Required:  true,
    37  				ForceNew:  true,
    38  				StateFunc: azureRMNormalizeLocation,
    39  			},
    40  
    41  			"resource_group_name": {
    42  				Type:     schema.TypeString,
    43  				Required: true,
    44  				ForceNew: true,
    45  			},
    46  
    47  			"plan": {
    48  				Type:     schema.TypeSet,
    49  				Optional: true,
    50  				MaxItems: 1,
    51  				Elem: &schema.Resource{
    52  					Schema: map[string]*schema.Schema{
    53  						"name": {
    54  							Type:     schema.TypeString,
    55  							Required: true,
    56  						},
    57  
    58  						"publisher": {
    59  							Type:     schema.TypeString,
    60  							Required: true,
    61  						},
    62  
    63  						"product": {
    64  							Type:     schema.TypeString,
    65  							Required: true,
    66  						},
    67  					},
    68  				},
    69  				Set: resourceArmVirtualMachinePlanHash,
    70  			},
    71  
    72  			"availability_set_id": {
    73  				Type:     schema.TypeString,
    74  				Optional: true,
    75  				Computed: true,
    76  				ForceNew: true,
    77  				StateFunc: func(id interface{}) string {
    78  					return strings.ToLower(id.(string))
    79  				},
    80  			},
    81  
    82  			"license_type": {
    83  				Type:     schema.TypeString,
    84  				Optional: true,
    85  				Computed: true,
    86  			},
    87  
    88  			"vm_size": {
    89  				Type:     schema.TypeString,
    90  				Required: true,
    91  			},
    92  
    93  			"storage_image_reference": {
    94  				Type:     schema.TypeSet,
    95  				Optional: true,
    96  				Computed: true,
    97  				ForceNew: true,
    98  				MaxItems: 1,
    99  				Elem: &schema.Resource{
   100  					Schema: map[string]*schema.Schema{
   101  						"publisher": {
   102  							Type:     schema.TypeString,
   103  							Required: true,
   104  							ForceNew: true,
   105  						},
   106  
   107  						"offer": {
   108  							Type:     schema.TypeString,
   109  							Required: true,
   110  							ForceNew: true,
   111  						},
   112  
   113  						"sku": {
   114  							Type:     schema.TypeString,
   115  							Required: true,
   116  							ForceNew: true,
   117  						},
   118  
   119  						"version": {
   120  							Type:     schema.TypeString,
   121  							Optional: true,
   122  							Computed: true,
   123  							ForceNew: true,
   124  						},
   125  					},
   126  				},
   127  				Set: resourceArmVirtualMachineStorageImageReferenceHash,
   128  			},
   129  
   130  			"storage_os_disk": {
   131  				Type:     schema.TypeSet,
   132  				Required: true,
   133  				MaxItems: 1,
   134  				Elem: &schema.Resource{
   135  					Schema: map[string]*schema.Schema{
   136  						"os_type": {
   137  							Type:     schema.TypeString,
   138  							Optional: true,
   139  						},
   140  
   141  						"name": {
   142  							Type:     schema.TypeString,
   143  							Required: true,
   144  						},
   145  
   146  						"vhd_uri": {
   147  							Type:     schema.TypeString,
   148  							Required: true,
   149  							ForceNew: true,
   150  						},
   151  
   152  						"image_uri": {
   153  							Type:     schema.TypeString,
   154  							Optional: true,
   155  						},
   156  
   157  						"caching": {
   158  							Type:     schema.TypeString,
   159  							Optional: true,
   160  							Computed: true,
   161  						},
   162  
   163  						"create_option": {
   164  							Type:     schema.TypeString,
   165  							Required: true,
   166  						},
   167  
   168  						"disk_size_gb": {
   169  							Type:         schema.TypeInt,
   170  							Optional:     true,
   171  							ValidateFunc: validateDiskSizeGB,
   172  						},
   173  					},
   174  				},
   175  				Set: resourceArmVirtualMachineStorageOsDiskHash,
   176  			},
   177  
   178  			"delete_os_disk_on_termination": {
   179  				Type:     schema.TypeBool,
   180  				Optional: true,
   181  				Default:  false,
   182  			},
   183  
   184  			"storage_data_disk": {
   185  				Type:     schema.TypeList,
   186  				Optional: true,
   187  				Elem: &schema.Resource{
   188  					Schema: map[string]*schema.Schema{
   189  						"name": {
   190  							Type:     schema.TypeString,
   191  							Required: true,
   192  						},
   193  
   194  						"vhd_uri": {
   195  							Type:     schema.TypeString,
   196  							Required: true,
   197  						},
   198  
   199  						"create_option": {
   200  							Type:     schema.TypeString,
   201  							Required: true,
   202  						},
   203  
   204  						"disk_size_gb": {
   205  							Type:         schema.TypeInt,
   206  							Required:     true,
   207  							ValidateFunc: validateDiskSizeGB,
   208  						},
   209  
   210  						"lun": {
   211  							Type:     schema.TypeInt,
   212  							Required: true,
   213  						},
   214  					},
   215  				},
   216  			},
   217  
   218  			"delete_data_disks_on_termination": {
   219  				Type:     schema.TypeBool,
   220  				Optional: true,
   221  				Default:  false,
   222  			},
   223  
   224  			"diagnostics_profile": {
   225  				Type:          schema.TypeSet,
   226  				Optional:      true,
   227  				MaxItems:      1,
   228  				ConflictsWith: []string{"boot_diagnostics"},
   229  				Deprecated:    "Use field boot_diagnostics instead",
   230  				Elem: &schema.Resource{
   231  					Schema: map[string]*schema.Schema{
   232  						"boot_diagnostics": {
   233  							Type:     schema.TypeSet,
   234  							Required: true,
   235  							MaxItems: 1,
   236  							Elem: &schema.Resource{
   237  								Schema: map[string]*schema.Schema{
   238  									"enabled": {
   239  										Type:     schema.TypeBool,
   240  										Required: true,
   241  									},
   242  
   243  									"storage_uri": {
   244  										Type:     schema.TypeString,
   245  										Required: true,
   246  									},
   247  								},
   248  							},
   249  						},
   250  					},
   251  				},
   252  			},
   253  
   254  			"boot_diagnostics": {
   255  				Type:     schema.TypeList,
   256  				Optional: true,
   257  				MaxItems: 1,
   258  				Elem: &schema.Resource{
   259  					Schema: map[string]*schema.Schema{
   260  						"enabled": {
   261  							Type:     schema.TypeBool,
   262  							Required: true,
   263  						},
   264  
   265  						"storage_uri": {
   266  							Type:     schema.TypeString,
   267  							Required: true,
   268  						},
   269  					},
   270  				},
   271  			},
   272  
   273  			"os_profile": {
   274  				Type:     schema.TypeSet,
   275  				Required: true,
   276  				MaxItems: 1,
   277  				Elem: &schema.Resource{
   278  					Schema: map[string]*schema.Schema{
   279  						"computer_name": {
   280  							Type:     schema.TypeString,
   281  							ForceNew: true,
   282  							Required: true,
   283  						},
   284  
   285  						"admin_username": {
   286  							Type:     schema.TypeString,
   287  							Required: true,
   288  						},
   289  
   290  						"admin_password": {
   291  							Type:     schema.TypeString,
   292  							Required: true,
   293  						},
   294  
   295  						"custom_data": {
   296  							Type:     schema.TypeString,
   297  							Optional: true,
   298  							Computed: true,
   299  						},
   300  					},
   301  				},
   302  				Set: resourceArmVirtualMachineStorageOsProfileHash,
   303  			},
   304  
   305  			"os_profile_windows_config": {
   306  				Type:     schema.TypeSet,
   307  				Optional: true,
   308  				MaxItems: 1,
   309  				Elem: &schema.Resource{
   310  					Schema: map[string]*schema.Schema{
   311  						"provision_vm_agent": {
   312  							Type:     schema.TypeBool,
   313  							Optional: true,
   314  						},
   315  						"enable_automatic_upgrades": {
   316  							Type:     schema.TypeBool,
   317  							Optional: true,
   318  						},
   319  						"winrm": {
   320  							Type:     schema.TypeList,
   321  							Optional: true,
   322  							Elem: &schema.Resource{
   323  								Schema: map[string]*schema.Schema{
   324  									"protocol": {
   325  										Type:     schema.TypeString,
   326  										Required: true,
   327  									},
   328  									"certificate_url": {
   329  										Type:     schema.TypeString,
   330  										Optional: true,
   331  									},
   332  								},
   333  							},
   334  						},
   335  						"additional_unattend_config": {
   336  							Type:     schema.TypeList,
   337  							Optional: true,
   338  							Elem: &schema.Resource{
   339  								Schema: map[string]*schema.Schema{
   340  									"pass": {
   341  										Type:     schema.TypeString,
   342  										Required: true,
   343  									},
   344  									"component": {
   345  										Type:     schema.TypeString,
   346  										Required: true,
   347  									},
   348  									"setting_name": {
   349  										Type:     schema.TypeString,
   350  										Required: true,
   351  									},
   352  									"content": {
   353  										Type:     schema.TypeString,
   354  										Required: true,
   355  									},
   356  								},
   357  							},
   358  						},
   359  					},
   360  				},
   361  				Set: resourceArmVirtualMachineStorageOsProfileWindowsConfigHash,
   362  			},
   363  
   364  			"os_profile_linux_config": {
   365  				Type:     schema.TypeSet,
   366  				Optional: true,
   367  				MaxItems: 1,
   368  				Elem: &schema.Resource{
   369  					Schema: map[string]*schema.Schema{
   370  						"disable_password_authentication": {
   371  							Type:     schema.TypeBool,
   372  							Required: true,
   373  						},
   374  						"ssh_keys": {
   375  							Type:     schema.TypeList,
   376  							Optional: true,
   377  							Elem: &schema.Resource{
   378  								Schema: map[string]*schema.Schema{
   379  									"path": {
   380  										Type:     schema.TypeString,
   381  										Required: true,
   382  									},
   383  									"key_data": {
   384  										Type:     schema.TypeString,
   385  										Optional: true,
   386  									},
   387  								},
   388  							},
   389  						},
   390  					},
   391  				},
   392  				Set: resourceArmVirtualMachineStorageOsProfileLinuxConfigHash,
   393  			},
   394  
   395  			"os_profile_secrets": {
   396  				Type:     schema.TypeSet,
   397  				Optional: true,
   398  				Elem: &schema.Resource{
   399  					Schema: map[string]*schema.Schema{
   400  						"source_vault_id": {
   401  							Type:     schema.TypeString,
   402  							Required: true,
   403  						},
   404  
   405  						"vault_certificates": {
   406  							Type:     schema.TypeList,
   407  							Optional: true,
   408  							Elem: &schema.Resource{
   409  								Schema: map[string]*schema.Schema{
   410  									"certificate_url": {
   411  										Type:     schema.TypeString,
   412  										Required: true,
   413  									},
   414  									"certificate_store": {
   415  										Type:     schema.TypeString,
   416  										Optional: true,
   417  									},
   418  								},
   419  							},
   420  						},
   421  					},
   422  				},
   423  			},
   424  
   425  			"network_interface_ids": {
   426  				Type:     schema.TypeSet,
   427  				Required: true,
   428  				Elem: &schema.Schema{
   429  					Type: schema.TypeString,
   430  				},
   431  				Set: schema.HashString,
   432  			},
   433  
   434  			"tags": tagsSchema(),
   435  		},
   436  	}
   437  }
   438  
   439  func validateDiskSizeGB(v interface{}, k string) (ws []string, errors []error) {
   440  	value := v.(int)
   441  	if value < 1 || value > 1023 {
   442  		errors = append(errors, fmt.Errorf(
   443  			"The `disk_size_gb` can only be between 1 and 1023"))
   444  	}
   445  	return
   446  }
   447  
   448  func resourceArmVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error {
   449  	client := meta.(*ArmClient)
   450  	vmClient := client.vmClient
   451  
   452  	log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine creation.")
   453  
   454  	name := d.Get("name").(string)
   455  	location := d.Get("location").(string)
   456  	resGroup := d.Get("resource_group_name").(string)
   457  	tags := d.Get("tags").(map[string]interface{})
   458  	expandedTags := expandTags(tags)
   459  
   460  	osDisk, err := expandAzureRmVirtualMachineOsDisk(d)
   461  	if err != nil {
   462  		return err
   463  	}
   464  	storageProfile := compute.StorageProfile{
   465  		OsDisk: osDisk,
   466  	}
   467  
   468  	if _, ok := d.GetOk("storage_image_reference"); ok {
   469  		imageRef, err := expandAzureRmVirtualMachineImageReference(d)
   470  		if err != nil {
   471  			return err
   472  		}
   473  		storageProfile.ImageReference = imageRef
   474  	}
   475  
   476  	if _, ok := d.GetOk("storage_data_disk"); ok {
   477  		dataDisks, err := expandAzureRmVirtualMachineDataDisk(d)
   478  		if err != nil {
   479  			return err
   480  		}
   481  		storageProfile.DataDisks = &dataDisks
   482  	}
   483  
   484  	networkProfile := expandAzureRmVirtualMachineNetworkProfile(d)
   485  	vmSize := d.Get("vm_size").(string)
   486  	properties := compute.VirtualMachineProperties{
   487  		NetworkProfile: &networkProfile,
   488  		HardwareProfile: &compute.HardwareProfile{
   489  			VMSize: compute.VirtualMachineSizeTypes(vmSize),
   490  		},
   491  		StorageProfile: &storageProfile,
   492  	}
   493  
   494  	if _, ok := d.GetOk("boot_diagnostics"); ok {
   495  		diagnosticsProfile := expandAzureRmVirtualMachineDiagnosticsProfile(d)
   496  		if diagnosticsProfile != nil {
   497  			properties.DiagnosticsProfile = diagnosticsProfile
   498  		}
   499  	}
   500  
   501  	osProfile, err := expandAzureRmVirtualMachineOsProfile(d)
   502  	if err != nil {
   503  		return err
   504  	}
   505  	properties.OsProfile = osProfile
   506  
   507  	if v, ok := d.GetOk("availability_set_id"); ok {
   508  		availabilitySet := v.(string)
   509  		availSet := compute.SubResource{
   510  			ID: &availabilitySet,
   511  		}
   512  
   513  		properties.AvailabilitySet = &availSet
   514  	}
   515  
   516  	vm := compute.VirtualMachine{
   517  		Name:       &name,
   518  		Location:   &location,
   519  		Properties: &properties,
   520  		Tags:       expandedTags,
   521  	}
   522  
   523  	if _, ok := d.GetOk("plan"); ok {
   524  		plan, err := expandAzureRmVirtualMachinePlan(d)
   525  		if err != nil {
   526  			return err
   527  		}
   528  
   529  		vm.Plan = plan
   530  	}
   531  
   532  	_, vmErr := vmClient.CreateOrUpdate(resGroup, name, vm, make(chan struct{}))
   533  	if vmErr != nil {
   534  		return vmErr
   535  	}
   536  
   537  	read, err := vmClient.Get(resGroup, name, "")
   538  	if err != nil {
   539  		return err
   540  	}
   541  	if read.ID == nil {
   542  		return fmt.Errorf("Cannot read Virtual Machine %s (resource group %s) ID", name, resGroup)
   543  	}
   544  
   545  	d.SetId(*read.ID)
   546  
   547  	return resourceArmVirtualMachineRead(d, meta)
   548  }
   549  
   550  func resourceArmVirtualMachineRead(d *schema.ResourceData, meta interface{}) error {
   551  	vmClient := meta.(*ArmClient).vmClient
   552  
   553  	id, err := parseAzureResourceID(d.Id())
   554  	if err != nil {
   555  		return err
   556  	}
   557  	resGroup := id.ResourceGroup
   558  	name := id.Path["virtualMachines"]
   559  
   560  	resp, err := vmClient.Get(resGroup, name, "")
   561  
   562  	if err != nil {
   563  		if resp.StatusCode == http.StatusNotFound {
   564  			d.SetId("")
   565  			return nil
   566  		}
   567  		return fmt.Errorf("Error making Read request on Azure Virtual Machine %s: %s", name, err)
   568  	}
   569  
   570  	d.Set("name", resp.Name)
   571  	d.Set("resource_group_name", resGroup)
   572  	d.Set("location", resp.Location)
   573  
   574  	if resp.Plan != nil {
   575  		if err := d.Set("plan", flattenAzureRmVirtualMachinePlan(resp.Plan)); err != nil {
   576  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Plan error: %#v", err)
   577  		}
   578  	}
   579  
   580  	if resp.Properties.AvailabilitySet != nil {
   581  		d.Set("availability_set_id", strings.ToLower(*resp.Properties.AvailabilitySet.ID))
   582  	}
   583  
   584  	d.Set("vm_size", resp.Properties.HardwareProfile.VMSize)
   585  
   586  	if resp.Properties.StorageProfile.ImageReference != nil {
   587  		if err := d.Set("storage_image_reference", schema.NewSet(resourceArmVirtualMachineStorageImageReferenceHash, flattenAzureRmVirtualMachineImageReference(resp.Properties.StorageProfile.ImageReference))); err != nil {
   588  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Image Reference error: %#v", err)
   589  		}
   590  	}
   591  
   592  	if err := d.Set("storage_os_disk", schema.NewSet(resourceArmVirtualMachineStorageOsDiskHash, flattenAzureRmVirtualMachineOsDisk(resp.Properties.StorageProfile.OsDisk))); err != nil {
   593  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Disk error: %#v", err)
   594  	}
   595  
   596  	if resp.Properties.StorageProfile.DataDisks != nil {
   597  		if err := d.Set("storage_data_disk", flattenAzureRmVirtualMachineDataDisk(resp.Properties.StorageProfile.DataDisks)); err != nil {
   598  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Data Disks error: %#v", err)
   599  		}
   600  	}
   601  
   602  	if err := d.Set("os_profile", schema.NewSet(resourceArmVirtualMachineStorageOsProfileHash, flattenAzureRmVirtualMachineOsProfile(resp.Properties.OsProfile))); err != nil {
   603  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile: %#v", err)
   604  	}
   605  
   606  	if resp.Properties.OsProfile.WindowsConfiguration != nil {
   607  		if err := d.Set("os_profile_windows_config", flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(resp.Properties.OsProfile.WindowsConfiguration)); err != nil {
   608  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Windows Configuration: %#v", err)
   609  		}
   610  	}
   611  
   612  	if resp.Properties.OsProfile.LinuxConfiguration != nil {
   613  		if err := d.Set("os_profile_linux_config", flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(resp.Properties.OsProfile.LinuxConfiguration)); err != nil {
   614  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Linux Configuration: %#v", err)
   615  		}
   616  	}
   617  
   618  	if resp.Properties.OsProfile.Secrets != nil {
   619  		if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineOsProfileSecrets(resp.Properties.OsProfile.Secrets)); err != nil {
   620  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Secrets: %#v", err)
   621  		}
   622  	}
   623  
   624  	if resp.Properties.DiagnosticsProfile != nil && resp.Properties.DiagnosticsProfile.BootDiagnostics != nil {
   625  		if err := d.Set("boot_diagnostics", flattenAzureRmVirtualMachineDiagnosticsProfile(resp.Properties.DiagnosticsProfile.BootDiagnostics)); err != nil {
   626  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Diagnostics Profile: %#v", err)
   627  		}
   628  	}
   629  
   630  	if resp.Properties.NetworkProfile != nil {
   631  		if err := d.Set("network_interface_ids", flattenAzureRmVirtualMachineNetworkInterfaces(resp.Properties.NetworkProfile)); err != nil {
   632  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Network Interfaces: %#v", err)
   633  		}
   634  	}
   635  
   636  	flattenAndSetTags(d, resp.Tags)
   637  
   638  	return nil
   639  }
   640  
   641  func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error {
   642  	vmClient := meta.(*ArmClient).vmClient
   643  
   644  	id, err := parseAzureResourceID(d.Id())
   645  	if err != nil {
   646  		return err
   647  	}
   648  	resGroup := id.ResourceGroup
   649  	name := id.Path["virtualMachines"]
   650  
   651  	if _, err = vmClient.Delete(resGroup, name, make(chan struct{})); err != nil {
   652  		return err
   653  	}
   654  
   655  	// delete OS Disk if opted in
   656  	if deleteOsDisk := d.Get("delete_os_disk_on_termination").(bool); deleteOsDisk {
   657  		log.Printf("[INFO] delete_os_disk_on_termination is enabled, deleting")
   658  
   659  		osDisk, err := expandAzureRmVirtualMachineOsDisk(d)
   660  		if err != nil {
   661  			return fmt.Errorf("Error expanding OS Disk: %s", err)
   662  		}
   663  
   664  		if err = resourceArmVirtualMachineDeleteVhd(*osDisk.Vhd.URI, meta); err != nil {
   665  			return fmt.Errorf("Error deleting OS Disk VHD: %s", err)
   666  		}
   667  	}
   668  
   669  	// delete Data disks if opted in
   670  	if deleteDataDisks := d.Get("delete_data_disks_on_termination").(bool); deleteDataDisks {
   671  		log.Printf("[INFO] delete_data_disks_on_termination is enabled, deleting each data disk")
   672  
   673  		disks, err := expandAzureRmVirtualMachineDataDisk(d)
   674  		if err != nil {
   675  			return fmt.Errorf("Error expanding Data Disks: %s", err)
   676  		}
   677  
   678  		for _, disk := range disks {
   679  			if err = resourceArmVirtualMachineDeleteVhd(*disk.Vhd.URI, meta); err != nil {
   680  				return fmt.Errorf("Error deleting Data Disk VHD: %s", err)
   681  			}
   682  		}
   683  	}
   684  
   685  	return nil
   686  }
   687  
   688  func resourceArmVirtualMachineDeleteVhd(uri string, meta interface{}) error {
   689  	vhdURL, err := url.Parse(uri)
   690  	if err != nil {
   691  		return fmt.Errorf("Cannot parse Disk VHD URI: %s", err)
   692  	}
   693  
   694  	// VHD URI is in the form: https://storageAccountName.blob.core.windows.net/containerName/blobName
   695  	storageAccountName := strings.Split(vhdURL.Host, ".")[0]
   696  	path := strings.Split(strings.TrimPrefix(vhdURL.Path, "/"), "/")
   697  	containerName := path[0]
   698  	blobName := path[1]
   699  
   700  	storageAccountResourceGroupName, err := findStorageAccountResourceGroup(meta, storageAccountName)
   701  	if err != nil {
   702  		return fmt.Errorf("Error finding resource group for storage account %s: %s", storageAccountName, err)
   703  	}
   704  
   705  	blobClient, saExists, err := meta.(*ArmClient).getBlobStorageClientForStorageAccount(storageAccountResourceGroupName, storageAccountName)
   706  	if err != nil {
   707  		return fmt.Errorf("Error creating blob store client for VHD deletion: %s", err)
   708  	}
   709  
   710  	if !saExists {
   711  		log.Printf("[INFO] Storage Account %q in resource group %q doesn't exist so the VHD blob won't exist", storageAccountName, storageAccountResourceGroupName)
   712  		return nil
   713  	}
   714  
   715  	log.Printf("[INFO] Deleting VHD blob %s", blobName)
   716  	_, err = blobClient.DeleteBlobIfExists(containerName, blobName, nil)
   717  	if err != nil {
   718  		return fmt.Errorf("Error deleting VHD blob: %s", err)
   719  	}
   720  
   721  	return nil
   722  }
   723  
   724  func resourceArmVirtualMachinePlanHash(v interface{}) int {
   725  	var buf bytes.Buffer
   726  	m := v.(map[string]interface{})
   727  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   728  	buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string)))
   729  	buf.WriteString(fmt.Sprintf("%s-", m["product"].(string)))
   730  
   731  	return hashcode.String(buf.String())
   732  }
   733  
   734  func resourceArmVirtualMachineStorageImageReferenceHash(v interface{}) int {
   735  	var buf bytes.Buffer
   736  	m := v.(map[string]interface{})
   737  	buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string)))
   738  	buf.WriteString(fmt.Sprintf("%s-", m["offer"].(string)))
   739  	buf.WriteString(fmt.Sprintf("%s-", m["sku"].(string)))
   740  
   741  	return hashcode.String(buf.String())
   742  }
   743  
   744  func resourceArmVirtualMachineStorageOsProfileHash(v interface{}) int {
   745  	var buf bytes.Buffer
   746  	m := v.(map[string]interface{})
   747  	buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string)))
   748  	buf.WriteString(fmt.Sprintf("%s-", m["computer_name"].(string)))
   749  	return hashcode.String(buf.String())
   750  }
   751  
   752  func resourceArmVirtualMachineStorageOsDiskHash(v interface{}) int {
   753  	var buf bytes.Buffer
   754  	m := v.(map[string]interface{})
   755  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   756  	buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string)))
   757  
   758  	return hashcode.String(buf.String())
   759  }
   760  
   761  func resourceArmVirtualMachineStorageOsProfileLinuxConfigHash(v interface{}) int {
   762  	var buf bytes.Buffer
   763  	m := v.(map[string]interface{})
   764  	buf.WriteString(fmt.Sprintf("%t-", m["disable_password_authentication"].(bool)))
   765  
   766  	return hashcode.String(buf.String())
   767  }
   768  
   769  func resourceArmVirtualMachineStorageOsProfileWindowsConfigHash(v interface{}) int {
   770  	var buf bytes.Buffer
   771  	m := v.(map[string]interface{})
   772  	if m["provision_vm_agent"] != nil {
   773  		buf.WriteString(fmt.Sprintf("%t-", m["provision_vm_agent"].(bool)))
   774  	}
   775  	if m["enable_automatic_upgrades"] != nil {
   776  		buf.WriteString(fmt.Sprintf("%t-", m["enable_automatic_upgrades"].(bool)))
   777  	}
   778  	return hashcode.String(buf.String())
   779  }
   780  
   781  func flattenAzureRmVirtualMachinePlan(plan *compute.Plan) map[string]interface{} {
   782  	result := make(map[string]interface{})
   783  	result["name"] = *plan.Name
   784  	result["publisher"] = *plan.Publisher
   785  	result["product"] = *plan.Product
   786  
   787  	return result
   788  }
   789  
   790  func flattenAzureRmVirtualMachineImageReference(image *compute.ImageReference) []interface{} {
   791  	result := make(map[string]interface{})
   792  	result["offer"] = *image.Offer
   793  	result["publisher"] = *image.Publisher
   794  	result["sku"] = *image.Sku
   795  
   796  	if image.Version != nil {
   797  		result["version"] = *image.Version
   798  	}
   799  
   800  	return []interface{}{result}
   801  }
   802  
   803  func flattenAzureRmVirtualMachineDiagnosticsProfile(profile *compute.BootDiagnostics) []interface{} {
   804  	result := make(map[string]interface{})
   805  
   806  	result["enabled"] = *profile.Enabled
   807  	if profile.StorageURI != nil {
   808  		result["storage_uri"] = *profile.StorageURI
   809  	}
   810  
   811  	return []interface{}{result}
   812  }
   813  
   814  func flattenAzureRmVirtualMachineNetworkInterfaces(profile *compute.NetworkProfile) []string {
   815  	result := make([]string, 0, len(*profile.NetworkInterfaces))
   816  	for _, nic := range *profile.NetworkInterfaces {
   817  		result = append(result, *nic.ID)
   818  	}
   819  	return result
   820  }
   821  
   822  func flattenAzureRmVirtualMachineOsProfileSecrets(secrets *[]compute.VaultSecretGroup) []map[string]interface{} {
   823  	result := make([]map[string]interface{}, 0, len(*secrets))
   824  	for _, secret := range *secrets {
   825  		s := map[string]interface{}{
   826  			"source_vault_id": *secret.SourceVault.ID,
   827  		}
   828  
   829  		if secret.VaultCertificates != nil {
   830  			certs := make([]map[string]interface{}, 0, len(*secret.VaultCertificates))
   831  			for _, cert := range *secret.VaultCertificates {
   832  				vaultCert := make(map[string]interface{})
   833  				vaultCert["certificate_url"] = *cert.CertificateURL
   834  
   835  				if cert.CertificateStore != nil {
   836  					vaultCert["certificate_store"] = *cert.CertificateStore
   837  				}
   838  
   839  				certs = append(certs, vaultCert)
   840  			}
   841  
   842  			s["vault_certificates"] = certs
   843  		}
   844  
   845  		result = append(result, s)
   846  	}
   847  	return result
   848  }
   849  
   850  func flattenAzureRmVirtualMachineDataDisk(disks *[]compute.DataDisk) interface{} {
   851  	result := make([]interface{}, len(*disks))
   852  	for i, disk := range *disks {
   853  		l := make(map[string]interface{})
   854  		l["name"] = *disk.Name
   855  		l["vhd_uri"] = *disk.Vhd.URI
   856  		l["create_option"] = disk.CreateOption
   857  		l["disk_size_gb"] = *disk.DiskSizeGB
   858  		l["lun"] = *disk.Lun
   859  
   860  		result[i] = l
   861  	}
   862  	return result
   863  }
   864  
   865  func flattenAzureRmVirtualMachineOsProfile(osProfile *compute.OSProfile) []interface{} {
   866  	result := make(map[string]interface{})
   867  	result["computer_name"] = *osProfile.ComputerName
   868  	result["admin_username"] = *osProfile.AdminUsername
   869  	if osProfile.CustomData != nil {
   870  		result["custom_data"] = *osProfile.CustomData
   871  	}
   872  
   873  	return []interface{}{result}
   874  }
   875  
   876  func flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(config *compute.WindowsConfiguration) []interface{} {
   877  	result := make(map[string]interface{})
   878  
   879  	if config.ProvisionVMAgent != nil {
   880  		result["provision_vm_agent"] = *config.ProvisionVMAgent
   881  	}
   882  
   883  	if config.EnableAutomaticUpdates != nil {
   884  		result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates
   885  	}
   886  
   887  	if config.WinRM != nil {
   888  		listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners))
   889  		for _, i := range *config.WinRM.Listeners {
   890  			listener := make(map[string]interface{})
   891  			listener["protocol"] = i.Protocol
   892  
   893  			if i.CertificateURL != nil {
   894  				listener["certificate_url"] = *i.CertificateURL
   895  			}
   896  
   897  			listeners = append(listeners, listener)
   898  		}
   899  
   900  		result["winrm"] = listeners
   901  	}
   902  
   903  	if config.AdditionalUnattendContent != nil {
   904  		content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent))
   905  		for _, i := range *config.AdditionalUnattendContent {
   906  			c := make(map[string]interface{})
   907  			c["pass"] = i.PassName
   908  			c["component"] = i.ComponentName
   909  			c["setting_name"] = i.SettingName
   910  
   911  			if i.Content != nil {
   912  				c["content"] = *i.Content
   913  			}
   914  
   915  			content = append(content, c)
   916  		}
   917  
   918  		result["additional_unattend_config"] = content
   919  	}
   920  
   921  	return []interface{}{result}
   922  }
   923  
   924  func flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(config *compute.LinuxConfiguration) []interface{} {
   925  
   926  	result := make(map[string]interface{})
   927  	result["disable_password_authentication"] = *config.DisablePasswordAuthentication
   928  
   929  	if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 {
   930  		ssh_keys := make([]map[string]interface{}, len(*config.SSH.PublicKeys))
   931  		for _, i := range *config.SSH.PublicKeys {
   932  			key := make(map[string]interface{})
   933  			key["path"] = *i.Path
   934  
   935  			if i.KeyData != nil {
   936  				key["key_data"] = *i.KeyData
   937  			}
   938  
   939  			ssh_keys = append(ssh_keys, key)
   940  		}
   941  
   942  		result["ssh_keys"] = ssh_keys
   943  	}
   944  
   945  	return []interface{}{result}
   946  }
   947  
   948  func flattenAzureRmVirtualMachineOsDisk(disk *compute.OSDisk) []interface{} {
   949  	result := make(map[string]interface{})
   950  	result["name"] = *disk.Name
   951  	result["vhd_uri"] = *disk.Vhd.URI
   952  	result["create_option"] = disk.CreateOption
   953  	result["caching"] = disk.Caching
   954  	if disk.DiskSizeGB != nil {
   955  		result["disk_size_gb"] = *disk.DiskSizeGB
   956  	}
   957  
   958  	return []interface{}{result}
   959  }
   960  
   961  func expandAzureRmVirtualMachinePlan(d *schema.ResourceData) (*compute.Plan, error) {
   962  	planConfigs := d.Get("plan").(*schema.Set).List()
   963  
   964  	planConfig := planConfigs[0].(map[string]interface{})
   965  
   966  	publisher := planConfig["publisher"].(string)
   967  	name := planConfig["name"].(string)
   968  	product := planConfig["product"].(string)
   969  
   970  	return &compute.Plan{
   971  		Publisher: &publisher,
   972  		Name:      &name,
   973  		Product:   &product,
   974  	}, nil
   975  }
   976  
   977  func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSProfile, error) {
   978  	osProfiles := d.Get("os_profile").(*schema.Set).List()
   979  
   980  	osProfile := osProfiles[0].(map[string]interface{})
   981  
   982  	adminUsername := osProfile["admin_username"].(string)
   983  	adminPassword := osProfile["admin_password"].(string)
   984  	computerName := osProfile["computer_name"].(string)
   985  
   986  	profile := &compute.OSProfile{
   987  		AdminUsername: &adminUsername,
   988  		ComputerName:  &computerName,
   989  	}
   990  
   991  	if adminPassword != "" {
   992  		profile.AdminPassword = &adminPassword
   993  	}
   994  
   995  	if _, ok := d.GetOk("os_profile_windows_config"); ok {
   996  		winConfig, err := expandAzureRmVirtualMachineOsProfileWindowsConfig(d)
   997  		if err != nil {
   998  			return nil, err
   999  		}
  1000  		if winConfig != nil {
  1001  			profile.WindowsConfiguration = winConfig
  1002  		}
  1003  	}
  1004  
  1005  	if _, ok := d.GetOk("os_profile_linux_config"); ok {
  1006  		linuxConfig, err := expandAzureRmVirtualMachineOsProfileLinuxConfig(d)
  1007  		if err != nil {
  1008  			return nil, err
  1009  		}
  1010  		if linuxConfig != nil {
  1011  			profile.LinuxConfiguration = linuxConfig
  1012  		}
  1013  	}
  1014  
  1015  	if _, ok := d.GetOk("os_profile_secrets"); ok {
  1016  		secrets := expandAzureRmVirtualMachineOsProfileSecrets(d)
  1017  		if secrets != nil {
  1018  			profile.Secrets = secrets
  1019  		}
  1020  	}
  1021  
  1022  	if v := osProfile["custom_data"].(string); v != "" {
  1023  		profile.CustomData = &v
  1024  	}
  1025  
  1026  	return profile, nil
  1027  }
  1028  
  1029  func expandAzureRmVirtualMachineOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup {
  1030  	secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List()
  1031  	secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig))
  1032  
  1033  	for _, secretConfig := range secretsConfig {
  1034  		config := secretConfig.(map[string]interface{})
  1035  		sourceVaultId := config["source_vault_id"].(string)
  1036  
  1037  		vaultSecretGroup := compute.VaultSecretGroup{
  1038  			SourceVault: &compute.SubResource{
  1039  				ID: &sourceVaultId,
  1040  			},
  1041  		}
  1042  
  1043  		if v := config["vault_certificates"]; v != nil {
  1044  			certsConfig := v.([]interface{})
  1045  			certs := make([]compute.VaultCertificate, 0, len(certsConfig))
  1046  			for _, certConfig := range certsConfig {
  1047  				config := certConfig.(map[string]interface{})
  1048  
  1049  				certUrl := config["certificate_url"].(string)
  1050  				cert := compute.VaultCertificate{
  1051  					CertificateURL: &certUrl,
  1052  				}
  1053  				if v := config["certificate_store"].(string); v != "" {
  1054  					cert.CertificateStore = &v
  1055  				}
  1056  
  1057  				certs = append(certs, cert)
  1058  			}
  1059  			vaultSecretGroup.VaultCertificates = &certs
  1060  		}
  1061  
  1062  		secrets = append(secrets, vaultSecretGroup)
  1063  	}
  1064  
  1065  	return &secrets
  1066  }
  1067  
  1068  func expandAzureRmVirtualMachineOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) {
  1069  	osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List()
  1070  
  1071  	linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{})
  1072  	disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool)
  1073  
  1074  	config := &compute.LinuxConfiguration{
  1075  		DisablePasswordAuthentication: &disablePasswordAuth,
  1076  	}
  1077  
  1078  	linuxKeys := linuxConfig["ssh_keys"].([]interface{})
  1079  	sshPublicKeys := []compute.SSHPublicKey{}
  1080  	for _, key := range linuxKeys {
  1081  
  1082  		sshKey, ok := key.(map[string]interface{})
  1083  		if !ok {
  1084  			continue
  1085  		}
  1086  		path := sshKey["path"].(string)
  1087  		keyData := sshKey["key_data"].(string)
  1088  
  1089  		sshPublicKey := compute.SSHPublicKey{
  1090  			Path:    &path,
  1091  			KeyData: &keyData,
  1092  		}
  1093  
  1094  		sshPublicKeys = append(sshPublicKeys, sshPublicKey)
  1095  	}
  1096  
  1097  	config.SSH = &compute.SSHConfiguration{
  1098  		PublicKeys: &sshPublicKeys,
  1099  	}
  1100  
  1101  	return config, nil
  1102  }
  1103  
  1104  func expandAzureRmVirtualMachineOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) {
  1105  	osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List()
  1106  
  1107  	osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{})
  1108  	config := &compute.WindowsConfiguration{}
  1109  
  1110  	if v := osProfileConfig["provision_vm_agent"]; v != nil {
  1111  		provision := v.(bool)
  1112  		config.ProvisionVMAgent = &provision
  1113  	}
  1114  
  1115  	if v := osProfileConfig["enable_automatic_upgrades"]; v != nil {
  1116  		update := v.(bool)
  1117  		config.EnableAutomaticUpdates = &update
  1118  	}
  1119  
  1120  	if v := osProfileConfig["winrm"]; v != nil {
  1121  		winRm := v.([]interface{})
  1122  		if len(winRm) > 0 {
  1123  			winRmListners := make([]compute.WinRMListener, 0, len(winRm))
  1124  			for _, winRmConfig := range winRm {
  1125  				config := winRmConfig.(map[string]interface{})
  1126  
  1127  				protocol := config["protocol"].(string)
  1128  				winRmListner := compute.WinRMListener{
  1129  					Protocol: compute.ProtocolTypes(protocol),
  1130  				}
  1131  				if v := config["certificate_url"].(string); v != "" {
  1132  					winRmListner.CertificateURL = &v
  1133  				}
  1134  
  1135  				winRmListners = append(winRmListners, winRmListner)
  1136  			}
  1137  			config.WinRM = &compute.WinRMConfiguration{
  1138  				Listeners: &winRmListners,
  1139  			}
  1140  		}
  1141  	}
  1142  	if v := osProfileConfig["additional_unattend_config"]; v != nil {
  1143  		additionalConfig := v.([]interface{})
  1144  		if len(additionalConfig) > 0 {
  1145  			additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig))
  1146  			for _, addConfig := range additionalConfig {
  1147  				config := addConfig.(map[string]interface{})
  1148  				pass := config["pass"].(string)
  1149  				component := config["component"].(string)
  1150  				settingName := config["setting_name"].(string)
  1151  				content := config["content"].(string)
  1152  
  1153  				addContent := compute.AdditionalUnattendContent{
  1154  					PassName:      compute.PassNames(pass),
  1155  					ComponentName: compute.ComponentNames(component),
  1156  					SettingName:   compute.SettingNames(settingName),
  1157  					Content:       &content,
  1158  				}
  1159  
  1160  				additionalConfigContent = append(additionalConfigContent, addContent)
  1161  			}
  1162  			config.AdditionalUnattendContent = &additionalConfigContent
  1163  		}
  1164  	}
  1165  	return config, nil
  1166  }
  1167  
  1168  func expandAzureRmVirtualMachineDataDisk(d *schema.ResourceData) ([]compute.DataDisk, error) {
  1169  	disks := d.Get("storage_data_disk").([]interface{})
  1170  	data_disks := make([]compute.DataDisk, 0, len(disks))
  1171  	for _, disk_config := range disks {
  1172  		config := disk_config.(map[string]interface{})
  1173  
  1174  		name := config["name"].(string)
  1175  		vhd := config["vhd_uri"].(string)
  1176  		createOption := config["create_option"].(string)
  1177  		lun := int32(config["lun"].(int))
  1178  		disk_size := int32(config["disk_size_gb"].(int))
  1179  
  1180  		data_disk := compute.DataDisk{
  1181  			Name: &name,
  1182  			Vhd: &compute.VirtualHardDisk{
  1183  				URI: &vhd,
  1184  			},
  1185  			Lun:          &lun,
  1186  			DiskSizeGB:   &disk_size,
  1187  			CreateOption: compute.DiskCreateOptionTypes(createOption),
  1188  		}
  1189  
  1190  		data_disks = append(data_disks, data_disk)
  1191  	}
  1192  
  1193  	return data_disks, nil
  1194  }
  1195  
  1196  func expandAzureRmVirtualMachineDiagnosticsProfile(d *schema.ResourceData) *compute.DiagnosticsProfile {
  1197  	bootDiagnostics := d.Get("boot_diagnostics").([]interface{})
  1198  
  1199  	diagnosticsProfile := &compute.DiagnosticsProfile{}
  1200  	if len(bootDiagnostics) > 0 {
  1201  		bootDiagnostic := bootDiagnostics[0].(map[string]interface{})
  1202  
  1203  		diagnostic := &compute.BootDiagnostics{
  1204  			Enabled:    riviera.Bool(bootDiagnostic["enabled"].(bool)),
  1205  			StorageURI: riviera.String(bootDiagnostic["storage_uri"].(string)),
  1206  		}
  1207  
  1208  		diagnosticsProfile.BootDiagnostics = diagnostic
  1209  
  1210  		return diagnosticsProfile
  1211  	}
  1212  
  1213  	return nil
  1214  }
  1215  
  1216  func expandAzureRmVirtualMachineImageReference(d *schema.ResourceData) (*compute.ImageReference, error) {
  1217  	storageImageRefs := d.Get("storage_image_reference").(*schema.Set).List()
  1218  
  1219  	storageImageRef := storageImageRefs[0].(map[string]interface{})
  1220  
  1221  	publisher := storageImageRef["publisher"].(string)
  1222  	offer := storageImageRef["offer"].(string)
  1223  	sku := storageImageRef["sku"].(string)
  1224  	version := storageImageRef["version"].(string)
  1225  
  1226  	return &compute.ImageReference{
  1227  		Publisher: &publisher,
  1228  		Offer:     &offer,
  1229  		Sku:       &sku,
  1230  		Version:   &version,
  1231  	}, nil
  1232  }
  1233  
  1234  func expandAzureRmVirtualMachineNetworkProfile(d *schema.ResourceData) compute.NetworkProfile {
  1235  	nicIds := d.Get("network_interface_ids").(*schema.Set).List()
  1236  	network_interfaces := make([]compute.NetworkInterfaceReference, 0, len(nicIds))
  1237  
  1238  	network_profile := compute.NetworkProfile{}
  1239  
  1240  	for _, nic := range nicIds {
  1241  		id := nic.(string)
  1242  		network_interface := compute.NetworkInterfaceReference{
  1243  			ID: &id,
  1244  		}
  1245  		network_interfaces = append(network_interfaces, network_interface)
  1246  	}
  1247  
  1248  	network_profile.NetworkInterfaces = &network_interfaces
  1249  
  1250  	return network_profile
  1251  }
  1252  
  1253  func expandAzureRmVirtualMachineOsDisk(d *schema.ResourceData) (*compute.OSDisk, error) {
  1254  	disks := d.Get("storage_os_disk").(*schema.Set).List()
  1255  
  1256  	disk := disks[0].(map[string]interface{})
  1257  
  1258  	name := disk["name"].(string)
  1259  	vhdURI := disk["vhd_uri"].(string)
  1260  	imageURI := disk["image_uri"].(string)
  1261  	createOption := disk["create_option"].(string)
  1262  
  1263  	osDisk := &compute.OSDisk{
  1264  		Name: &name,
  1265  		Vhd: &compute.VirtualHardDisk{
  1266  			URI: &vhdURI,
  1267  		},
  1268  		CreateOption: compute.DiskCreateOptionTypes(createOption),
  1269  	}
  1270  
  1271  	if v := disk["image_uri"].(string); v != "" {
  1272  		osDisk.Image = &compute.VirtualHardDisk{
  1273  			URI: &imageURI,
  1274  		}
  1275  	}
  1276  
  1277  	if v := disk["os_type"].(string); v != "" {
  1278  		if v == "linux" {
  1279  			osDisk.OsType = compute.Linux
  1280  		} else if v == "windows" {
  1281  			osDisk.OsType = compute.Windows
  1282  		} else {
  1283  			return nil, fmt.Errorf("[ERROR] os_type must be 'linux' or 'windows'")
  1284  		}
  1285  	}
  1286  
  1287  	if v := disk["caching"].(string); v != "" {
  1288  		osDisk.Caching = compute.CachingTypes(v)
  1289  	}
  1290  
  1291  	if v := disk["disk_size_gb"].(int); v != 0 {
  1292  		diskSize := int32(v)
  1293  		osDisk.DiskSizeGB = &diskSize
  1294  	}
  1295  
  1296  	return osDisk, nil
  1297  }
  1298  
  1299  func findStorageAccountResourceGroup(meta interface{}, storageAccountName string) (string, error) {
  1300  	client := meta.(*ArmClient).resourceFindClient
  1301  	filter := fmt.Sprintf("name eq '%s' and resourceType eq 'Microsoft.Storage/storageAccounts'", storageAccountName)
  1302  	expand := ""
  1303  	var pager *int32
  1304  
  1305  	rf, err := client.List(filter, expand, pager)
  1306  	if err != nil {
  1307  		return "", fmt.Errorf("Error making resource request for query %s: %s", filter, err)
  1308  	}
  1309  
  1310  	results := *rf.Value
  1311  	if len(results) != 1 {
  1312  		return "", fmt.Errorf("Wrong number of results making resource request for query %s: %d", filter, len(results))
  1313  	}
  1314  
  1315  	id, err := parseAzureResourceID(*results[0].ID)
  1316  	if err != nil {
  1317  		return "", err
  1318  	}
  1319  
  1320  	return id.ResourceGroup, nil
  1321  }