github.com/peterbale/terraform@v0.9.0-beta2.0.20170315142748-5723acd55547/builtin/providers/azurerm/resource_arm_virtual_machine.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"net/url"
     9  	"strings"
    10  
    11  	"github.com/Azure/azure-sdk-for-go/arm/compute"
    12  	"github.com/hashicorp/terraform/helper/hashcode"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  	riviera "github.com/jen20/riviera/azure"
    15  )
    16  
    17  func resourceArmVirtualMachine() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceArmVirtualMachineCreate,
    20  		Read:   resourceArmVirtualMachineRead,
    21  		Update: resourceArmVirtualMachineCreate,
    22  		Delete: resourceArmVirtualMachineDelete,
    23  		Importer: &schema.ResourceImporter{
    24  			State: schema.ImportStatePassthrough,
    25  		},
    26  
    27  		Schema: map[string]*schema.Schema{
    28  			"name": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  
    34  			"location": locationSchema(),
    35  
    36  			"resource_group_name": {
    37  				Type:     schema.TypeString,
    38  				Required: true,
    39  				ForceNew: true,
    40  			},
    41  
    42  			"plan": {
    43  				Type:     schema.TypeSet,
    44  				Optional: true,
    45  				MaxItems: 1,
    46  				Elem: &schema.Resource{
    47  					Schema: map[string]*schema.Schema{
    48  						"name": {
    49  							Type:     schema.TypeString,
    50  							Required: true,
    51  						},
    52  
    53  						"publisher": {
    54  							Type:     schema.TypeString,
    55  							Required: true,
    56  						},
    57  
    58  						"product": {
    59  							Type:     schema.TypeString,
    60  							Required: true,
    61  						},
    62  					},
    63  				},
    64  				Set: resourceArmVirtualMachinePlanHash,
    65  			},
    66  
    67  			"availability_set_id": {
    68  				Type:     schema.TypeString,
    69  				Optional: true,
    70  				Computed: true,
    71  				ForceNew: true,
    72  				StateFunc: func(id interface{}) string {
    73  					return strings.ToLower(id.(string))
    74  				},
    75  			},
    76  
    77  			"license_type": {
    78  				Type:         schema.TypeString,
    79  				Optional:     true,
    80  				Computed:     true,
    81  				ValidateFunc: validateLicenseType,
    82  			},
    83  
    84  			"vm_size": {
    85  				Type:     schema.TypeString,
    86  				Required: true,
    87  			},
    88  
    89  			"storage_image_reference": {
    90  				Type:     schema.TypeSet,
    91  				Optional: true,
    92  				Computed: true,
    93  				ForceNew: true,
    94  				MaxItems: 1,
    95  				Elem: &schema.Resource{
    96  					Schema: map[string]*schema.Schema{
    97  						"publisher": {
    98  							Type:     schema.TypeString,
    99  							Required: true,
   100  							ForceNew: true,
   101  						},
   102  
   103  						"offer": {
   104  							Type:     schema.TypeString,
   105  							Required: true,
   106  							ForceNew: true,
   107  						},
   108  
   109  						"sku": {
   110  							Type:     schema.TypeString,
   111  							Required: true,
   112  							ForceNew: true,
   113  						},
   114  
   115  						"version": {
   116  							Type:     schema.TypeString,
   117  							Optional: true,
   118  							Computed: true,
   119  							ForceNew: true,
   120  						},
   121  					},
   122  				},
   123  				Set: resourceArmVirtualMachineStorageImageReferenceHash,
   124  			},
   125  
   126  			"storage_os_disk": {
   127  				Type:     schema.TypeSet,
   128  				Required: true,
   129  				MaxItems: 1,
   130  				Elem: &schema.Resource{
   131  					Schema: map[string]*schema.Schema{
   132  						"os_type": {
   133  							Type:     schema.TypeString,
   134  							Optional: true,
   135  						},
   136  
   137  						"name": {
   138  							Type:     schema.TypeString,
   139  							Required: true,
   140  						},
   141  
   142  						"vhd_uri": {
   143  							Type:     schema.TypeString,
   144  							Required: true,
   145  							ForceNew: true,
   146  						},
   147  
   148  						"image_uri": {
   149  							Type:     schema.TypeString,
   150  							Optional: true,
   151  						},
   152  
   153  						"caching": {
   154  							Type:     schema.TypeString,
   155  							Optional: true,
   156  							Computed: true,
   157  						},
   158  
   159  						"create_option": {
   160  							Type:     schema.TypeString,
   161  							Required: true,
   162  						},
   163  
   164  						"disk_size_gb": {
   165  							Type:         schema.TypeInt,
   166  							Optional:     true,
   167  							ValidateFunc: validateDiskSizeGB,
   168  						},
   169  					},
   170  				},
   171  				Set: resourceArmVirtualMachineStorageOsDiskHash,
   172  			},
   173  
   174  			"delete_os_disk_on_termination": {
   175  				Type:     schema.TypeBool,
   176  				Optional: true,
   177  				Default:  false,
   178  			},
   179  
   180  			"storage_data_disk": {
   181  				Type:     schema.TypeList,
   182  				Optional: true,
   183  				Elem: &schema.Resource{
   184  					Schema: map[string]*schema.Schema{
   185  						"name": {
   186  							Type:     schema.TypeString,
   187  							Required: true,
   188  						},
   189  
   190  						"vhd_uri": {
   191  							Type:     schema.TypeString,
   192  							Required: true,
   193  						},
   194  
   195  						"create_option": {
   196  							Type:     schema.TypeString,
   197  							Required: true,
   198  						},
   199  
   200  						"caching": {
   201  							Type:     schema.TypeString,
   202  							Optional: true,
   203  							Computed: true,
   204  						},
   205  
   206  						"disk_size_gb": {
   207  							Type:     schema.TypeInt,
   208  							Optional: true,
   209  							Computed: true,
   210  						},
   211  
   212  						"lun": {
   213  							Type:     schema.TypeInt,
   214  							Required: true,
   215  						},
   216  					},
   217  				},
   218  			},
   219  
   220  			"delete_data_disks_on_termination": {
   221  				Type:     schema.TypeBool,
   222  				Optional: true,
   223  				Default:  false,
   224  			},
   225  
   226  			"diagnostics_profile": {
   227  				Type:          schema.TypeSet,
   228  				Optional:      true,
   229  				MaxItems:      1,
   230  				ConflictsWith: []string{"boot_diagnostics"},
   231  				Deprecated:    "Use field boot_diagnostics instead",
   232  				Elem: &schema.Resource{
   233  					Schema: map[string]*schema.Schema{
   234  						"boot_diagnostics": {
   235  							Type:     schema.TypeSet,
   236  							Required: true,
   237  							MaxItems: 1,
   238  							Elem: &schema.Resource{
   239  								Schema: map[string]*schema.Schema{
   240  									"enabled": {
   241  										Type:     schema.TypeBool,
   242  										Required: true,
   243  									},
   244  
   245  									"storage_uri": {
   246  										Type:     schema.TypeString,
   247  										Required: true,
   248  									},
   249  								},
   250  							},
   251  						},
   252  					},
   253  				},
   254  			},
   255  
   256  			"boot_diagnostics": {
   257  				Type:     schema.TypeList,
   258  				Optional: true,
   259  				MaxItems: 1,
   260  				Elem: &schema.Resource{
   261  					Schema: map[string]*schema.Schema{
   262  						"enabled": {
   263  							Type:     schema.TypeBool,
   264  							Required: true,
   265  						},
   266  
   267  						"storage_uri": {
   268  							Type:     schema.TypeString,
   269  							Required: true,
   270  						},
   271  					},
   272  				},
   273  			},
   274  
   275  			"os_profile": {
   276  				Type:     schema.TypeSet,
   277  				Required: true,
   278  				MaxItems: 1,
   279  				Elem: &schema.Resource{
   280  					Schema: map[string]*schema.Schema{
   281  						"computer_name": {
   282  							Type:     schema.TypeString,
   283  							ForceNew: true,
   284  							Required: true,
   285  						},
   286  
   287  						"admin_username": {
   288  							Type:     schema.TypeString,
   289  							Required: true,
   290  						},
   291  
   292  						"admin_password": {
   293  							Type:     schema.TypeString,
   294  							Required: true,
   295  						},
   296  
   297  						"custom_data": {
   298  							Type:      schema.TypeString,
   299  							Optional:  true,
   300  							Computed:  true,
   301  							StateFunc: userDataStateFunc,
   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  		result["custom_data"] = *osProfile.CustomData
   891  	}
   892  
   893  	return []interface{}{result}
   894  }
   895  
   896  func flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(config *compute.WindowsConfiguration) []interface{} {
   897  	result := make(map[string]interface{})
   898  
   899  	if config.ProvisionVMAgent != nil {
   900  		result["provision_vm_agent"] = *config.ProvisionVMAgent
   901  	}
   902  
   903  	if config.EnableAutomaticUpdates != nil {
   904  		result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates
   905  	}
   906  
   907  	if config.WinRM != nil {
   908  		listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners))
   909  		for _, i := range *config.WinRM.Listeners {
   910  			listener := make(map[string]interface{})
   911  			listener["protocol"] = i.Protocol
   912  
   913  			if i.CertificateURL != nil {
   914  				listener["certificate_url"] = *i.CertificateURL
   915  			}
   916  
   917  			listeners = append(listeners, listener)
   918  		}
   919  
   920  		result["winrm"] = listeners
   921  	}
   922  
   923  	if config.AdditionalUnattendContent != nil {
   924  		content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent))
   925  		for _, i := range *config.AdditionalUnattendContent {
   926  			c := make(map[string]interface{})
   927  			c["pass"] = i.PassName
   928  			c["component"] = i.ComponentName
   929  			c["setting_name"] = i.SettingName
   930  
   931  			if i.Content != nil {
   932  				c["content"] = *i.Content
   933  			}
   934  
   935  			content = append(content, c)
   936  		}
   937  
   938  		result["additional_unattend_config"] = content
   939  	}
   940  
   941  	return []interface{}{result}
   942  }
   943  
   944  func flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(config *compute.LinuxConfiguration) []interface{} {
   945  
   946  	result := make(map[string]interface{})
   947  	result["disable_password_authentication"] = *config.DisablePasswordAuthentication
   948  
   949  	if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 {
   950  		ssh_keys := make([]map[string]interface{}, len(*config.SSH.PublicKeys))
   951  		for _, i := range *config.SSH.PublicKeys {
   952  			key := make(map[string]interface{})
   953  			key["path"] = *i.Path
   954  
   955  			if i.KeyData != nil {
   956  				key["key_data"] = *i.KeyData
   957  			}
   958  
   959  			ssh_keys = append(ssh_keys, key)
   960  		}
   961  
   962  		result["ssh_keys"] = ssh_keys
   963  	}
   964  
   965  	return []interface{}{result}
   966  }
   967  
   968  func flattenAzureRmVirtualMachineOsDisk(disk *compute.OSDisk) []interface{} {
   969  	result := make(map[string]interface{})
   970  	result["name"] = *disk.Name
   971  	result["vhd_uri"] = *disk.Vhd.URI
   972  	result["create_option"] = disk.CreateOption
   973  	result["caching"] = disk.Caching
   974  	if disk.DiskSizeGB != nil {
   975  		result["disk_size_gb"] = *disk.DiskSizeGB
   976  	}
   977  
   978  	return []interface{}{result}
   979  }
   980  
   981  func expandAzureRmVirtualMachinePlan(d *schema.ResourceData) (*compute.Plan, error) {
   982  	planConfigs := d.Get("plan").(*schema.Set).List()
   983  
   984  	planConfig := planConfigs[0].(map[string]interface{})
   985  
   986  	publisher := planConfig["publisher"].(string)
   987  	name := planConfig["name"].(string)
   988  	product := planConfig["product"].(string)
   989  
   990  	return &compute.Plan{
   991  		Publisher: &publisher,
   992  		Name:      &name,
   993  		Product:   &product,
   994  	}, nil
   995  }
   996  
   997  func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSProfile, error) {
   998  	osProfiles := d.Get("os_profile").(*schema.Set).List()
   999  
  1000  	osProfile := osProfiles[0].(map[string]interface{})
  1001  
  1002  	adminUsername := osProfile["admin_username"].(string)
  1003  	adminPassword := osProfile["admin_password"].(string)
  1004  	computerName := osProfile["computer_name"].(string)
  1005  
  1006  	profile := &compute.OSProfile{
  1007  		AdminUsername: &adminUsername,
  1008  		ComputerName:  &computerName,
  1009  	}
  1010  
  1011  	if adminPassword != "" {
  1012  		profile.AdminPassword = &adminPassword
  1013  	}
  1014  
  1015  	if _, ok := d.GetOk("os_profile_windows_config"); ok {
  1016  		winConfig, err := expandAzureRmVirtualMachineOsProfileWindowsConfig(d)
  1017  		if err != nil {
  1018  			return nil, err
  1019  		}
  1020  		if winConfig != nil {
  1021  			profile.WindowsConfiguration = winConfig
  1022  		}
  1023  	}
  1024  
  1025  	if _, ok := d.GetOk("os_profile_linux_config"); ok {
  1026  		linuxConfig, err := expandAzureRmVirtualMachineOsProfileLinuxConfig(d)
  1027  		if err != nil {
  1028  			return nil, err
  1029  		}
  1030  		if linuxConfig != nil {
  1031  			profile.LinuxConfiguration = linuxConfig
  1032  		}
  1033  	}
  1034  
  1035  	if _, ok := d.GetOk("os_profile_secrets"); ok {
  1036  		secrets := expandAzureRmVirtualMachineOsProfileSecrets(d)
  1037  		if secrets != nil {
  1038  			profile.Secrets = secrets
  1039  		}
  1040  	}
  1041  
  1042  	if v := osProfile["custom_data"].(string); v != "" {
  1043  		v = base64Encode(v)
  1044  		profile.CustomData = &v
  1045  	}
  1046  
  1047  	return profile, nil
  1048  }
  1049  
  1050  func expandAzureRmVirtualMachineOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup {
  1051  	secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List()
  1052  	secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig))
  1053  
  1054  	for _, secretConfig := range secretsConfig {
  1055  		config := secretConfig.(map[string]interface{})
  1056  		sourceVaultId := config["source_vault_id"].(string)
  1057  
  1058  		vaultSecretGroup := compute.VaultSecretGroup{
  1059  			SourceVault: &compute.SubResource{
  1060  				ID: &sourceVaultId,
  1061  			},
  1062  		}
  1063  
  1064  		if v := config["vault_certificates"]; v != nil {
  1065  			certsConfig := v.([]interface{})
  1066  			certs := make([]compute.VaultCertificate, 0, len(certsConfig))
  1067  			for _, certConfig := range certsConfig {
  1068  				config := certConfig.(map[string]interface{})
  1069  
  1070  				certUrl := config["certificate_url"].(string)
  1071  				cert := compute.VaultCertificate{
  1072  					CertificateURL: &certUrl,
  1073  				}
  1074  				if v := config["certificate_store"].(string); v != "" {
  1075  					cert.CertificateStore = &v
  1076  				}
  1077  
  1078  				certs = append(certs, cert)
  1079  			}
  1080  			vaultSecretGroup.VaultCertificates = &certs
  1081  		}
  1082  
  1083  		secrets = append(secrets, vaultSecretGroup)
  1084  	}
  1085  
  1086  	return &secrets
  1087  }
  1088  
  1089  func expandAzureRmVirtualMachineOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) {
  1090  	osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List()
  1091  
  1092  	linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{})
  1093  	disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool)
  1094  
  1095  	config := &compute.LinuxConfiguration{
  1096  		DisablePasswordAuthentication: &disablePasswordAuth,
  1097  	}
  1098  
  1099  	linuxKeys := linuxConfig["ssh_keys"].([]interface{})
  1100  	sshPublicKeys := []compute.SSHPublicKey{}
  1101  	for _, key := range linuxKeys {
  1102  
  1103  		sshKey, ok := key.(map[string]interface{})
  1104  		if !ok {
  1105  			continue
  1106  		}
  1107  		path := sshKey["path"].(string)
  1108  		keyData := sshKey["key_data"].(string)
  1109  
  1110  		sshPublicKey := compute.SSHPublicKey{
  1111  			Path:    &path,
  1112  			KeyData: &keyData,
  1113  		}
  1114  
  1115  		sshPublicKeys = append(sshPublicKeys, sshPublicKey)
  1116  	}
  1117  
  1118  	if len(sshPublicKeys) > 0 {
  1119  		config.SSH = &compute.SSHConfiguration{
  1120  			PublicKeys: &sshPublicKeys,
  1121  		}
  1122  	}
  1123  
  1124  	return config, nil
  1125  }
  1126  
  1127  func expandAzureRmVirtualMachineOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) {
  1128  	osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List()
  1129  
  1130  	osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{})
  1131  	config := &compute.WindowsConfiguration{}
  1132  
  1133  	if v := osProfileConfig["provision_vm_agent"]; v != nil {
  1134  		provision := v.(bool)
  1135  		config.ProvisionVMAgent = &provision
  1136  	}
  1137  
  1138  	if v := osProfileConfig["enable_automatic_upgrades"]; v != nil {
  1139  		update := v.(bool)
  1140  		config.EnableAutomaticUpdates = &update
  1141  	}
  1142  
  1143  	if v := osProfileConfig["winrm"]; v != nil {
  1144  		winRm := v.([]interface{})
  1145  		if len(winRm) > 0 {
  1146  			winRmListners := make([]compute.WinRMListener, 0, len(winRm))
  1147  			for _, winRmConfig := range winRm {
  1148  				config := winRmConfig.(map[string]interface{})
  1149  
  1150  				protocol := config["protocol"].(string)
  1151  				winRmListner := compute.WinRMListener{
  1152  					Protocol: compute.ProtocolTypes(protocol),
  1153  				}
  1154  				if v := config["certificate_url"].(string); v != "" {
  1155  					winRmListner.CertificateURL = &v
  1156  				}
  1157  
  1158  				winRmListners = append(winRmListners, winRmListner)
  1159  			}
  1160  			config.WinRM = &compute.WinRMConfiguration{
  1161  				Listeners: &winRmListners,
  1162  			}
  1163  		}
  1164  	}
  1165  	if v := osProfileConfig["additional_unattend_config"]; v != nil {
  1166  		additionalConfig := v.([]interface{})
  1167  		if len(additionalConfig) > 0 {
  1168  			additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig))
  1169  			for _, addConfig := range additionalConfig {
  1170  				config := addConfig.(map[string]interface{})
  1171  				pass := config["pass"].(string)
  1172  				component := config["component"].(string)
  1173  				settingName := config["setting_name"].(string)
  1174  				content := config["content"].(string)
  1175  
  1176  				addContent := compute.AdditionalUnattendContent{
  1177  					PassName:      compute.PassNames(pass),
  1178  					ComponentName: compute.ComponentNames(component),
  1179  					SettingName:   compute.SettingNames(settingName),
  1180  					Content:       &content,
  1181  				}
  1182  
  1183  				additionalConfigContent = append(additionalConfigContent, addContent)
  1184  			}
  1185  			config.AdditionalUnattendContent = &additionalConfigContent
  1186  		}
  1187  	}
  1188  	return config, nil
  1189  }
  1190  
  1191  func expandAzureRmVirtualMachineDataDisk(d *schema.ResourceData) ([]compute.DataDisk, error) {
  1192  	disks := d.Get("storage_data_disk").([]interface{})
  1193  	data_disks := make([]compute.DataDisk, 0, len(disks))
  1194  	for _, disk_config := range disks {
  1195  		config := disk_config.(map[string]interface{})
  1196  
  1197  		name := config["name"].(string)
  1198  		vhd := config["vhd_uri"].(string)
  1199  		createOption := config["create_option"].(string)
  1200  		lun := int32(config["lun"].(int))
  1201  
  1202  		data_disk := compute.DataDisk{
  1203  			Name: &name,
  1204  			Vhd: &compute.VirtualHardDisk{
  1205  				URI: &vhd,
  1206  			},
  1207  			Lun:          &lun,
  1208  			CreateOption: compute.DiskCreateOptionTypes(createOption),
  1209  		}
  1210  
  1211  		if v := config["caching"].(string); v != "" {
  1212  			data_disk.Caching = compute.CachingTypes(v)
  1213  		}
  1214  
  1215  		if v := config["disk_size_gb"]; v != nil {
  1216  			diskSize := int32(config["disk_size_gb"].(int))
  1217  			data_disk.DiskSizeGB = &diskSize
  1218  		}
  1219  
  1220  		data_disks = append(data_disks, data_disk)
  1221  	}
  1222  
  1223  	return data_disks, nil
  1224  }
  1225  
  1226  func expandAzureRmVirtualMachineDiagnosticsProfile(d *schema.ResourceData) *compute.DiagnosticsProfile {
  1227  	bootDiagnostics := d.Get("boot_diagnostics").([]interface{})
  1228  
  1229  	diagnosticsProfile := &compute.DiagnosticsProfile{}
  1230  	if len(bootDiagnostics) > 0 {
  1231  		bootDiagnostic := bootDiagnostics[0].(map[string]interface{})
  1232  
  1233  		diagnostic := &compute.BootDiagnostics{
  1234  			Enabled:    riviera.Bool(bootDiagnostic["enabled"].(bool)),
  1235  			StorageURI: riviera.String(bootDiagnostic["storage_uri"].(string)),
  1236  		}
  1237  
  1238  		diagnosticsProfile.BootDiagnostics = diagnostic
  1239  
  1240  		return diagnosticsProfile
  1241  	}
  1242  
  1243  	return nil
  1244  }
  1245  
  1246  func expandAzureRmVirtualMachineImageReference(d *schema.ResourceData) (*compute.ImageReference, error) {
  1247  	storageImageRefs := d.Get("storage_image_reference").(*schema.Set).List()
  1248  
  1249  	storageImageRef := storageImageRefs[0].(map[string]interface{})
  1250  
  1251  	publisher := storageImageRef["publisher"].(string)
  1252  	offer := storageImageRef["offer"].(string)
  1253  	sku := storageImageRef["sku"].(string)
  1254  	version := storageImageRef["version"].(string)
  1255  
  1256  	return &compute.ImageReference{
  1257  		Publisher: &publisher,
  1258  		Offer:     &offer,
  1259  		Sku:       &sku,
  1260  		Version:   &version,
  1261  	}, nil
  1262  }
  1263  
  1264  func expandAzureRmVirtualMachineNetworkProfile(d *schema.ResourceData) compute.NetworkProfile {
  1265  	nicIds := d.Get("network_interface_ids").(*schema.Set).List()
  1266  	network_interfaces := make([]compute.NetworkInterfaceReference, 0, len(nicIds))
  1267  
  1268  	network_profile := compute.NetworkProfile{}
  1269  
  1270  	for _, nic := range nicIds {
  1271  		id := nic.(string)
  1272  		network_interface := compute.NetworkInterfaceReference{
  1273  			ID: &id,
  1274  		}
  1275  		network_interfaces = append(network_interfaces, network_interface)
  1276  	}
  1277  
  1278  	network_profile.NetworkInterfaces = &network_interfaces
  1279  
  1280  	return network_profile
  1281  }
  1282  
  1283  func expandAzureRmVirtualMachineOsDisk(d *schema.ResourceData) (*compute.OSDisk, error) {
  1284  	disks := d.Get("storage_os_disk").(*schema.Set).List()
  1285  
  1286  	disk := disks[0].(map[string]interface{})
  1287  
  1288  	name := disk["name"].(string)
  1289  	vhdURI := disk["vhd_uri"].(string)
  1290  	imageURI := disk["image_uri"].(string)
  1291  	createOption := disk["create_option"].(string)
  1292  
  1293  	osDisk := &compute.OSDisk{
  1294  		Name: &name,
  1295  		Vhd: &compute.VirtualHardDisk{
  1296  			URI: &vhdURI,
  1297  		},
  1298  		CreateOption: compute.DiskCreateOptionTypes(createOption),
  1299  	}
  1300  
  1301  	if v := disk["image_uri"].(string); v != "" {
  1302  		osDisk.Image = &compute.VirtualHardDisk{
  1303  			URI: &imageURI,
  1304  		}
  1305  	}
  1306  
  1307  	if v := disk["os_type"].(string); v != "" {
  1308  		if v == "linux" {
  1309  			osDisk.OsType = compute.Linux
  1310  		} else if v == "windows" {
  1311  			osDisk.OsType = compute.Windows
  1312  		} else {
  1313  			return nil, fmt.Errorf("[ERROR] os_type must be 'linux' or 'windows'")
  1314  		}
  1315  	}
  1316  
  1317  	if v := disk["caching"].(string); v != "" {
  1318  		osDisk.Caching = compute.CachingTypes(v)
  1319  	}
  1320  
  1321  	if v := disk["disk_size_gb"].(int); v != 0 {
  1322  		diskSize := int32(v)
  1323  		osDisk.DiskSizeGB = &diskSize
  1324  	}
  1325  
  1326  	return osDisk, nil
  1327  }
  1328  
  1329  func findStorageAccountResourceGroup(meta interface{}, storageAccountName string) (string, error) {
  1330  	client := meta.(*ArmClient).resourceFindClient
  1331  	filter := fmt.Sprintf("name eq '%s' and resourceType eq 'Microsoft.Storage/storageAccounts'", storageAccountName)
  1332  	expand := ""
  1333  	var pager *int32
  1334  
  1335  	rf, err := client.List(filter, expand, pager)
  1336  	if err != nil {
  1337  		return "", fmt.Errorf("Error making resource request for query %s: %s", filter, err)
  1338  	}
  1339  
  1340  	results := *rf.Value
  1341  	if len(results) != 1 {
  1342  		return "", fmt.Errorf("Wrong number of results making resource request for query %s: %d", filter, len(results))
  1343  	}
  1344  
  1345  	id, err := parseAzureResourceID(*results[0].ID)
  1346  	if err != nil {
  1347  		return "", err
  1348  	}
  1349  
  1350  	return id.ResourceGroup, nil
  1351  }