github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/azurerm/resource_arm_virtual_machine.go (about)

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