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