github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  
     9  	"github.com/Azure/azure-sdk-for-go/arm/compute"
    10  	"github.com/hashicorp/terraform/helper/hashcode"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceArmVirtualMachineScaleSet() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceArmVirtualMachineScaleSetCreate,
    17  		Read:   resourceArmVirtualMachineScaleSetRead,
    18  		Update: resourceArmVirtualMachineScaleSetCreate,
    19  		Delete: resourceArmVirtualMachineScaleSetDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  
    28  			"location": locationSchema(),
    29  
    30  			"resource_group_name": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Required: true,
    33  				ForceNew: true,
    34  			},
    35  
    36  			"sku": &schema.Schema{
    37  				Type:     schema.TypeSet,
    38  				Required: true,
    39  				MaxItems: 1,
    40  				Elem: &schema.Resource{
    41  					Schema: map[string]*schema.Schema{
    42  						"name": &schema.Schema{
    43  							Type:     schema.TypeString,
    44  							Required: true,
    45  						},
    46  
    47  						"tier": &schema.Schema{
    48  							Type:     schema.TypeString,
    49  							Optional: true,
    50  							Computed: true,
    51  						},
    52  
    53  						"capacity": &schema.Schema{
    54  							Type:     schema.TypeInt,
    55  							Required: true,
    56  						},
    57  					},
    58  				},
    59  				Set: resourceArmVirtualMachineScaleSetSkuHash,
    60  			},
    61  
    62  			"upgrade_policy_mode": &schema.Schema{
    63  				Type:     schema.TypeString,
    64  				Required: true,
    65  			},
    66  
    67  			"os_profile": &schema.Schema{
    68  				Type:     schema.TypeSet,
    69  				Required: true,
    70  				MaxItems: 1,
    71  				Elem: &schema.Resource{
    72  					Schema: map[string]*schema.Schema{
    73  						"computer_name_prefix": &schema.Schema{
    74  							Type:     schema.TypeString,
    75  							Required: true,
    76  						},
    77  
    78  						"admin_username": &schema.Schema{
    79  							Type:     schema.TypeString,
    80  							Required: true,
    81  						},
    82  
    83  						"admin_password": &schema.Schema{
    84  							Type:     schema.TypeString,
    85  							Required: true,
    86  						},
    87  
    88  						"custom_data": &schema.Schema{
    89  							Type:     schema.TypeString,
    90  							Optional: true,
    91  						},
    92  					},
    93  				},
    94  				Set: resourceArmVirtualMachineScaleSetsOsProfileHash,
    95  			},
    96  
    97  			"os_profile_secrets": &schema.Schema{
    98  				Type:     schema.TypeSet,
    99  				Optional: true,
   100  				Elem: &schema.Resource{
   101  					Schema: map[string]*schema.Schema{
   102  						"source_vault_id": &schema.Schema{
   103  							Type:     schema.TypeString,
   104  							Required: true,
   105  						},
   106  
   107  						"vault_certificates": &schema.Schema{
   108  							Type:     schema.TypeList,
   109  							Optional: true,
   110  							Elem: &schema.Resource{
   111  								Schema: map[string]*schema.Schema{
   112  									"certificate_url": &schema.Schema{
   113  										Type:     schema.TypeString,
   114  										Required: true,
   115  									},
   116  									"certificate_store": &schema.Schema{
   117  										Type:     schema.TypeString,
   118  										Optional: true,
   119  									},
   120  								},
   121  							},
   122  						},
   123  					},
   124  				},
   125  			},
   126  
   127  			"os_profile_windows_config": &schema.Schema{
   128  				Type:     schema.TypeSet,
   129  				Optional: true,
   130  				MaxItems: 1,
   131  				Elem: &schema.Resource{
   132  					Schema: map[string]*schema.Schema{
   133  						"provision_vm_agent": &schema.Schema{
   134  							Type:     schema.TypeBool,
   135  							Optional: true,
   136  						},
   137  						"enable_automatic_upgrades": &schema.Schema{
   138  							Type:     schema.TypeBool,
   139  							Optional: true,
   140  						},
   141  						"winrm": &schema.Schema{
   142  							Type:     schema.TypeSet,
   143  							Optional: true,
   144  							Elem: &schema.Resource{
   145  								Schema: map[string]*schema.Schema{
   146  									"protocol": &schema.Schema{
   147  										Type:     schema.TypeString,
   148  										Required: true,
   149  									},
   150  									"certificate_url": &schema.Schema{
   151  										Type:     schema.TypeString,
   152  										Optional: true,
   153  									},
   154  								},
   155  							},
   156  						},
   157  						"additional_unattend_config": &schema.Schema{
   158  							Type:     schema.TypeSet,
   159  							Optional: true,
   160  							Elem: &schema.Resource{
   161  								Schema: map[string]*schema.Schema{
   162  									"pass": &schema.Schema{
   163  										Type:     schema.TypeString,
   164  										Required: true,
   165  									},
   166  									"component": &schema.Schema{
   167  										Type:     schema.TypeString,
   168  										Required: true,
   169  									},
   170  									"setting_name": &schema.Schema{
   171  										Type:     schema.TypeString,
   172  										Required: true,
   173  									},
   174  									"content": &schema.Schema{
   175  										Type:     schema.TypeString,
   176  										Required: true,
   177  									},
   178  								},
   179  							},
   180  						},
   181  					},
   182  				},
   183  				Set: resourceArmVirtualMachineScaleSetOsProfileLWindowsConfigHash,
   184  			},
   185  
   186  			"os_profile_linux_config": &schema.Schema{
   187  				Type:     schema.TypeSet,
   188  				Optional: true,
   189  				Computed: true,
   190  				MaxItems: 1,
   191  				Elem: &schema.Resource{
   192  					Schema: map[string]*schema.Schema{
   193  						"disable_password_authentication": &schema.Schema{
   194  							Type:     schema.TypeBool,
   195  							Optional: true,
   196  							Default:  false,
   197  							ForceNew: true,
   198  						},
   199  						"ssh_keys": &schema.Schema{
   200  							Type:     schema.TypeList,
   201  							Optional: true,
   202  							Elem: &schema.Resource{
   203  								Schema: map[string]*schema.Schema{
   204  									"path": &schema.Schema{
   205  										Type:     schema.TypeString,
   206  										Required: true,
   207  									},
   208  									"key_data": &schema.Schema{
   209  										Type:     schema.TypeString,
   210  										Optional: true,
   211  									},
   212  								},
   213  							},
   214  						},
   215  					},
   216  				},
   217  				Set: resourceArmVirtualMachineScaleSetOsProfileLinuxConfigHash,
   218  			},
   219  
   220  			"network_profile": &schema.Schema{
   221  				Type:     schema.TypeSet,
   222  				Required: true,
   223  				Elem: &schema.Resource{
   224  					Schema: map[string]*schema.Schema{
   225  						"name": &schema.Schema{
   226  							Type:     schema.TypeString,
   227  							Required: true,
   228  						},
   229  
   230  						"primary": &schema.Schema{
   231  							Type:     schema.TypeBool,
   232  							Required: true,
   233  						},
   234  
   235  						"ip_configuration": &schema.Schema{
   236  							Type:     schema.TypeList,
   237  							Required: true,
   238  							Elem: &schema.Resource{
   239  								Schema: map[string]*schema.Schema{
   240  									"name": &schema.Schema{
   241  										Type:     schema.TypeString,
   242  										Required: true,
   243  									},
   244  
   245  									"subnet_id": &schema.Schema{
   246  										Type:     schema.TypeString,
   247  										Required: true,
   248  									},
   249  
   250  									"load_balancer_backend_address_pool_ids": &schema.Schema{
   251  										Type:     schema.TypeSet,
   252  										Optional: true,
   253  										Computed: true,
   254  										Elem:     &schema.Schema{Type: schema.TypeString},
   255  										Set:      schema.HashString,
   256  									},
   257  								},
   258  							},
   259  						},
   260  					},
   261  				},
   262  				Set: resourceArmVirtualMachineScaleSetNetworkConfigurationHash,
   263  			},
   264  
   265  			"storage_profile_os_disk": &schema.Schema{
   266  				Type:     schema.TypeSet,
   267  				Required: true,
   268  				MaxItems: 1,
   269  				Elem: &schema.Resource{
   270  					Schema: map[string]*schema.Schema{
   271  						"name": &schema.Schema{
   272  							Type:     schema.TypeString,
   273  							Required: true,
   274  						},
   275  
   276  						"image": &schema.Schema{
   277  							Type:     schema.TypeString,
   278  							Optional: true,
   279  							Computed: true,
   280  						},
   281  
   282  						"vhd_containers": &schema.Schema{
   283  							Type:     schema.TypeSet,
   284  							Required: true,
   285  							Elem:     &schema.Schema{Type: schema.TypeString},
   286  							Set:      schema.HashString,
   287  						},
   288  
   289  						"caching": &schema.Schema{
   290  							Type:     schema.TypeString,
   291  							Required: true,
   292  						},
   293  
   294  						"os_type": &schema.Schema{
   295  							Type:     schema.TypeString,
   296  							Optional: true,
   297  							Computed: true,
   298  						},
   299  
   300  						"create_option": &schema.Schema{
   301  							Type:     schema.TypeString,
   302  							Required: true,
   303  						},
   304  					},
   305  				},
   306  				Set: resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash,
   307  			},
   308  
   309  			"storage_profile_image_reference": &schema.Schema{
   310  				Type:     schema.TypeSet,
   311  				Optional: true,
   312  				Computed: true,
   313  				MaxItems: 1,
   314  				Elem: &schema.Resource{
   315  					Schema: map[string]*schema.Schema{
   316  						"publisher": &schema.Schema{
   317  							Type:     schema.TypeString,
   318  							Required: true,
   319  						},
   320  
   321  						"offer": &schema.Schema{
   322  							Type:     schema.TypeString,
   323  							Required: true,
   324  						},
   325  
   326  						"sku": &schema.Schema{
   327  							Type:     schema.TypeString,
   328  							Required: true,
   329  						},
   330  
   331  						"version": &schema.Schema{
   332  							Type:     schema.TypeString,
   333  							Required: true,
   334  						},
   335  					},
   336  				},
   337  				Set: resourceArmVirtualMachineScaleSetStorageProfileImageReferenceHash,
   338  			},
   339  
   340  			"tags": tagsSchema(),
   341  		},
   342  	}
   343  }
   344  
   345  func resourceArmVirtualMachineScaleSetCreate(d *schema.ResourceData, meta interface{}) error {
   346  	client := meta.(*ArmClient)
   347  	vmScaleSetClient := client.vmScaleSetClient
   348  
   349  	log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine Scale Set creation.")
   350  
   351  	name := d.Get("name").(string)
   352  	location := d.Get("location").(string)
   353  	resGroup := d.Get("resource_group_name").(string)
   354  	tags := d.Get("tags").(map[string]interface{})
   355  
   356  	sku, err := expandVirtualMachineScaleSetSku(d)
   357  	if err != nil {
   358  		return err
   359  	}
   360  
   361  	storageProfile := compute.VirtualMachineScaleSetStorageProfile{}
   362  	osDisk, err := expandAzureRMVirtualMachineScaleSetsStorageProfileOsDisk(d)
   363  	if err != nil {
   364  		return err
   365  	}
   366  	storageProfile.OsDisk = osDisk
   367  	if _, ok := d.GetOk("storage_profile_image_reference"); ok {
   368  		imageRef, err := expandAzureRmVirtualMachineScaleSetStorageProfileImageReference(d)
   369  		if err != nil {
   370  			return err
   371  		}
   372  		storageProfile.ImageReference = imageRef
   373  	}
   374  
   375  	osProfile, err := expandAzureRMVirtualMachineScaleSetsOsProfile(d)
   376  	if err != nil {
   377  		return err
   378  	}
   379  
   380  	updatePolicy := d.Get("upgrade_policy_mode").(string)
   381  	scaleSetProps := compute.VirtualMachineScaleSetProperties{
   382  		UpgradePolicy: &compute.UpgradePolicy{
   383  			Mode: compute.UpgradeMode(updatePolicy),
   384  		},
   385  		VirtualMachineProfile: &compute.VirtualMachineScaleSetVMProfile{
   386  			NetworkProfile: expandAzureRmVirtualMachineScaleSetNetworkProfile(d),
   387  			StorageProfile: &storageProfile,
   388  			OsProfile:      osProfile,
   389  		},
   390  	}
   391  
   392  	scaleSetParams := compute.VirtualMachineScaleSet{
   393  		Name:     &name,
   394  		Location: &location,
   395  		Tags:     expandTags(tags),
   396  		Sku:      sku,
   397  		VirtualMachineScaleSetProperties: &scaleSetProps,
   398  	}
   399  	_, vmErr := vmScaleSetClient.CreateOrUpdate(resGroup, name, scaleSetParams, make(chan struct{}))
   400  	if vmErr != nil {
   401  		return vmErr
   402  	}
   403  
   404  	read, err := vmScaleSetClient.Get(resGroup, name)
   405  	if err != nil {
   406  		return err
   407  	}
   408  	if read.ID == nil {
   409  		return fmt.Errorf("Cannot read Virtual Machine Scale Set %s (resource group %s) ID", name, resGroup)
   410  	}
   411  
   412  	d.SetId(*read.ID)
   413  
   414  	return resourceArmVirtualMachineScaleSetRead(d, meta)
   415  }
   416  
   417  func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interface{}) error {
   418  	vmScaleSetClient := meta.(*ArmClient).vmScaleSetClient
   419  
   420  	id, err := parseAzureResourceID(d.Id())
   421  	if err != nil {
   422  		return err
   423  	}
   424  	resGroup := id.ResourceGroup
   425  	name := id.Path["virtualMachineScaleSets"]
   426  
   427  	resp, err := vmScaleSetClient.Get(resGroup, name)
   428  	if err != nil {
   429  		if resp.StatusCode == http.StatusNotFound {
   430  			log.Printf("[INFO] AzureRM Virtual Machine Scale Set (%s) Not Found. Removing from State", name)
   431  			d.SetId("")
   432  			return nil
   433  		}
   434  		return fmt.Errorf("Error making Read request on Azure Virtual Machine Scale Set %s: %s", name, err)
   435  	}
   436  
   437  	d.Set("location", resp.Location)
   438  	d.Set("name", resp.Name)
   439  
   440  	if err := d.Set("sku", flattenAzureRmVirtualMachineScaleSetSku(resp.Sku)); err != nil {
   441  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Sku error: %#v", err)
   442  	}
   443  
   444  	properties := resp.VirtualMachineScaleSetProperties
   445  
   446  	d.Set("upgrade_policy_mode", properties.UpgradePolicy.Mode)
   447  
   448  	if err := d.Set("os_profile", flattenAzureRMVirtualMachineScaleSetOsProfile(properties.VirtualMachineProfile.OsProfile)); err != nil {
   449  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile error: %#v", err)
   450  	}
   451  
   452  	if properties.VirtualMachineProfile.OsProfile.Secrets != nil {
   453  		if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineScaleSetOsProfileSecrets(properties.VirtualMachineProfile.OsProfile.Secrets)); err != nil {
   454  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Secrets error: %#v", err)
   455  		}
   456  	}
   457  
   458  	if properties.VirtualMachineProfile.OsProfile.WindowsConfiguration != nil {
   459  		if err := d.Set("os_profile_windows_config", flattenAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(properties.VirtualMachineProfile.OsProfile.WindowsConfiguration)); err != nil {
   460  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Windows config error: %#v", err)
   461  		}
   462  	}
   463  
   464  	if properties.VirtualMachineProfile.OsProfile.LinuxConfiguration != nil {
   465  		if err := d.Set("os_profile_linux_config", flattenAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(properties.VirtualMachineProfile.OsProfile.LinuxConfiguration)); err != nil {
   466  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Windows config error: %#v", err)
   467  		}
   468  	}
   469  
   470  	if err := d.Set("network_profile", flattenAzureRmVirtualMachineScaleSetNetworkProfile(properties.VirtualMachineProfile.NetworkProfile)); err != nil {
   471  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Network Profile error: %#v", err)
   472  	}
   473  
   474  	if properties.VirtualMachineProfile.StorageProfile.ImageReference != nil {
   475  		if err := d.Set("storage_profile_image_reference", flattenAzureRmVirtualMachineScaleSetStorageProfileImageReference(properties.VirtualMachineProfile.StorageProfile.ImageReference)); err != nil {
   476  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile Image Reference error: %#v", err)
   477  		}
   478  	}
   479  
   480  	if err := d.Set("storage_profile_os_disk", flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(properties.VirtualMachineProfile.StorageProfile.OsDisk)); err != nil {
   481  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile OS Disk error: %#v", err)
   482  	}
   483  
   484  	flattenAndSetTags(d, resp.Tags)
   485  
   486  	return nil
   487  }
   488  
   489  func resourceArmVirtualMachineScaleSetDelete(d *schema.ResourceData, meta interface{}) error {
   490  	vmScaleSetClient := meta.(*ArmClient).vmScaleSetClient
   491  
   492  	id, err := parseAzureResourceID(d.Id())
   493  	if err != nil {
   494  		return err
   495  	}
   496  	resGroup := id.ResourceGroup
   497  	name := id.Path["virtualMachineScaleSets"]
   498  
   499  	_, err = vmScaleSetClient.Delete(resGroup, name, make(chan struct{}))
   500  
   501  	return err
   502  }
   503  
   504  func flattenAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(config *compute.LinuxConfiguration) []interface{} {
   505  	result := make(map[string]interface{})
   506  	result["disable_password_authentication"] = *config.DisablePasswordAuthentication
   507  
   508  	if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 {
   509  		ssh_keys := make([]map[string]interface{}, len(*config.SSH.PublicKeys))
   510  		for _, i := range *config.SSH.PublicKeys {
   511  			key := make(map[string]interface{})
   512  			key["path"] = *i.Path
   513  
   514  			if i.KeyData != nil {
   515  				key["key_data"] = *i.KeyData
   516  			}
   517  
   518  			ssh_keys = append(ssh_keys, key)
   519  		}
   520  
   521  		result["ssh_keys"] = ssh_keys
   522  	}
   523  
   524  	return []interface{}{result}
   525  }
   526  
   527  func flattenAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(config *compute.WindowsConfiguration) []interface{} {
   528  	result := make(map[string]interface{})
   529  
   530  	if config.ProvisionVMAgent != nil {
   531  		result["provision_vm_agent"] = *config.ProvisionVMAgent
   532  	}
   533  
   534  	if config.EnableAutomaticUpdates != nil {
   535  		result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates
   536  	}
   537  
   538  	if config.WinRM != nil {
   539  		listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners))
   540  		for _, i := range *config.WinRM.Listeners {
   541  			listener := make(map[string]interface{})
   542  			listener["protocol"] = i.Protocol
   543  
   544  			if i.CertificateURL != nil {
   545  				listener["certificate_url"] = *i.CertificateURL
   546  			}
   547  
   548  			listeners = append(listeners, listener)
   549  		}
   550  
   551  		result["winrm"] = listeners
   552  	}
   553  
   554  	if config.AdditionalUnattendContent != nil {
   555  		content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent))
   556  		for _, i := range *config.AdditionalUnattendContent {
   557  			c := make(map[string]interface{})
   558  			c["pass"] = i.PassName
   559  			c["component"] = i.ComponentName
   560  			c["setting_name"] = i.SettingName
   561  			c["content"] = *i.Content
   562  
   563  			content = append(content, c)
   564  		}
   565  
   566  		result["additional_unattend_config"] = content
   567  	}
   568  
   569  	return []interface{}{result}
   570  }
   571  
   572  func flattenAzureRmVirtualMachineScaleSetOsProfileSecrets(secrets *[]compute.VaultSecretGroup) []map[string]interface{} {
   573  	result := make([]map[string]interface{}, 0, len(*secrets))
   574  	for _, secret := range *secrets {
   575  		s := map[string]interface{}{
   576  			"source_vault_id": *secret.SourceVault.ID,
   577  		}
   578  
   579  		if secret.VaultCertificates != nil {
   580  			certs := make([]map[string]interface{}, 0, len(*secret.VaultCertificates))
   581  			for _, cert := range *secret.VaultCertificates {
   582  				vaultCert := make(map[string]interface{})
   583  				vaultCert["certificate_url"] = *cert.CertificateURL
   584  
   585  				if cert.CertificateStore != nil {
   586  					vaultCert["certificate_store"] = *cert.CertificateStore
   587  				}
   588  
   589  				certs = append(certs, vaultCert)
   590  			}
   591  
   592  			s["vault_certificates"] = certs
   593  		}
   594  
   595  		result = append(result, s)
   596  	}
   597  	return result
   598  }
   599  
   600  func flattenAzureRmVirtualMachineScaleSetNetworkProfile(profile *compute.VirtualMachineScaleSetNetworkProfile) []map[string]interface{} {
   601  	networkConfigurations := profile.NetworkInterfaceConfigurations
   602  	result := make([]map[string]interface{}, 0, len(*networkConfigurations))
   603  	for _, netConfig := range *networkConfigurations {
   604  		s := map[string]interface{}{
   605  			"name":    *netConfig.Name,
   606  			"primary": *netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.Primary,
   607  		}
   608  
   609  		if netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.IPConfigurations != nil {
   610  			ipConfigs := make([]map[string]interface{}, 0, len(*netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.IPConfigurations))
   611  			for _, ipConfig := range *netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.IPConfigurations {
   612  				config := make(map[string]interface{})
   613  				config["name"] = *ipConfig.Name
   614  
   615  				properties := ipConfig.VirtualMachineScaleSetIPConfigurationProperties
   616  
   617  				if ipConfig.VirtualMachineScaleSetIPConfigurationProperties.Subnet != nil {
   618  					config["subnet_id"] = *properties.Subnet.ID
   619  				}
   620  
   621  				if properties.LoadBalancerBackendAddressPools != nil {
   622  					addressPools := make([]string, 0, len(*properties.LoadBalancerBackendAddressPools))
   623  					for _, pool := range *properties.LoadBalancerBackendAddressPools {
   624  						addressPools = append(addressPools, *pool.ID)
   625  					}
   626  					config["load_balancer_backend_address_pool_ids"] = addressPools
   627  				}
   628  			}
   629  
   630  			s["ip_configuration"] = ipConfigs
   631  		}
   632  
   633  		result = append(result, s)
   634  	}
   635  
   636  	return result
   637  }
   638  
   639  func flattenAzureRMVirtualMachineScaleSetOsProfile(profile *compute.VirtualMachineScaleSetOSProfile) []interface{} {
   640  	result := make(map[string]interface{})
   641  
   642  	result["computer_name_prefix"] = *profile.ComputerNamePrefix
   643  	result["admin_username"] = *profile.AdminUsername
   644  
   645  	if profile.CustomData != nil {
   646  		result["custom_data"] = *profile.CustomData
   647  	}
   648  
   649  	return []interface{}{result}
   650  }
   651  
   652  func flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(profile *compute.VirtualMachineScaleSetOSDisk) []interface{} {
   653  	result := make(map[string]interface{})
   654  	result["name"] = *profile.Name
   655  	if profile.Image != nil {
   656  		result["image"] = *profile.Image.URI
   657  	}
   658  
   659  	containers := make([]interface{}, 0, len(*profile.VhdContainers))
   660  	for _, container := range *profile.VhdContainers {
   661  		containers = append(containers, container)
   662  	}
   663  	result["vhd_containers"] = schema.NewSet(schema.HashString, containers)
   664  
   665  	result["caching"] = profile.Caching
   666  	result["create_option"] = profile.CreateOption
   667  
   668  	return []interface{}{result}
   669  }
   670  
   671  func flattenAzureRmVirtualMachineScaleSetStorageProfileImageReference(profile *compute.ImageReference) []interface{} {
   672  	result := make(map[string]interface{})
   673  	result["publisher"] = *profile.Publisher
   674  	result["offer"] = *profile.Offer
   675  	result["sku"] = *profile.Sku
   676  	result["version"] = *profile.Version
   677  
   678  	return []interface{}{result}
   679  }
   680  
   681  func flattenAzureRmVirtualMachineScaleSetSku(sku *compute.Sku) []interface{} {
   682  	result := make(map[string]interface{})
   683  	result["name"] = *sku.Name
   684  	result["capacity"] = *sku.Capacity
   685  
   686  	if *sku.Tier != "" {
   687  		result["tier"] = *sku.Tier
   688  	}
   689  
   690  	return []interface{}{result}
   691  }
   692  
   693  func resourceArmVirtualMachineScaleSetStorageProfileImageReferenceHash(v interface{}) int {
   694  	var buf bytes.Buffer
   695  	m := v.(map[string]interface{})
   696  	buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string)))
   697  	buf.WriteString(fmt.Sprintf("%s-", m["offer"].(string)))
   698  	buf.WriteString(fmt.Sprintf("%s-", m["sku"].(string)))
   699  	buf.WriteString(fmt.Sprintf("%s-", m["version"].(string)))
   700  
   701  	return hashcode.String(buf.String())
   702  }
   703  
   704  func resourceArmVirtualMachineScaleSetSkuHash(v interface{}) int {
   705  	var buf bytes.Buffer
   706  	m := v.(map[string]interface{})
   707  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   708  	if m["tier"] != nil {
   709  		buf.WriteString(fmt.Sprintf("%s-", m["tier"].(string)))
   710  	}
   711  	buf.WriteString(fmt.Sprintf("%d-", m["capacity"].(int)))
   712  
   713  	return hashcode.String(buf.String())
   714  }
   715  
   716  func resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash(v interface{}) int {
   717  	var buf bytes.Buffer
   718  	m := v.(map[string]interface{})
   719  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   720  
   721  	if m["image"] != nil {
   722  		buf.WriteString(fmt.Sprintf("%s-", m["image"].(string)))
   723  	}
   724  	if m["os_type"] != nil {
   725  		buf.WriteString(fmt.Sprintf("%s-", m["os_type"].(string)))
   726  	}
   727  
   728  	return hashcode.String(buf.String())
   729  }
   730  
   731  func resourceArmVirtualMachineScaleSetNetworkConfigurationHash(v interface{}) int {
   732  	var buf bytes.Buffer
   733  	m := v.(map[string]interface{})
   734  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   735  	buf.WriteString(fmt.Sprintf("%t-", m["primary"].(bool)))
   736  	return hashcode.String(buf.String())
   737  }
   738  
   739  func resourceArmVirtualMachineScaleSetsOsProfileHash(v interface{}) int {
   740  	var buf bytes.Buffer
   741  	m := v.(map[string]interface{})
   742  	buf.WriteString(fmt.Sprintf("%s-", m["computer_name_prefix"].(string)))
   743  	buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string)))
   744  	if m["custom_data"] != nil {
   745  		buf.WriteString(fmt.Sprintf("%s-", m["custom_data"].(string)))
   746  	}
   747  	return hashcode.String(buf.String())
   748  }
   749  
   750  func resourceArmVirtualMachineScaleSetOsProfileLinuxConfigHash(v interface{}) int {
   751  	var buf bytes.Buffer
   752  	m := v.(map[string]interface{})
   753  	buf.WriteString(fmt.Sprintf("%t-", m["disable_password_authentication"].(bool)))
   754  
   755  	return hashcode.String(buf.String())
   756  }
   757  
   758  func resourceArmVirtualMachineScaleSetOsProfileLWindowsConfigHash(v interface{}) int {
   759  	var buf bytes.Buffer
   760  	m := v.(map[string]interface{})
   761  	if m["provision_vm_agent"] != nil {
   762  		buf.WriteString(fmt.Sprintf("%t-", m["provision_vm_agent"].(bool)))
   763  	}
   764  	if m["enable_automatic_upgrades"] != nil {
   765  		buf.WriteString(fmt.Sprintf("%t-", m["enable_automatic_upgrades"].(bool)))
   766  	}
   767  	return hashcode.String(buf.String())
   768  }
   769  
   770  func expandVirtualMachineScaleSetSku(d *schema.ResourceData) (*compute.Sku, error) {
   771  	skuConfig := d.Get("sku").(*schema.Set).List()
   772  
   773  	config := skuConfig[0].(map[string]interface{})
   774  
   775  	name := config["name"].(string)
   776  	tier := config["tier"].(string)
   777  	capacity := int64(config["capacity"].(int))
   778  
   779  	sku := &compute.Sku{
   780  		Name:     &name,
   781  		Capacity: &capacity,
   782  	}
   783  
   784  	if tier != "" {
   785  		sku.Tier = &tier
   786  	}
   787  
   788  	return sku, nil
   789  }
   790  
   791  func expandAzureRmVirtualMachineScaleSetNetworkProfile(d *schema.ResourceData) *compute.VirtualMachineScaleSetNetworkProfile {
   792  	scaleSetNetworkProfileConfigs := d.Get("network_profile").(*schema.Set).List()
   793  	networkProfileConfig := make([]compute.VirtualMachineScaleSetNetworkConfiguration, 0, len(scaleSetNetworkProfileConfigs))
   794  
   795  	for _, npProfileConfig := range scaleSetNetworkProfileConfigs {
   796  		config := npProfileConfig.(map[string]interface{})
   797  
   798  		name := config["name"].(string)
   799  		primary := config["primary"].(bool)
   800  
   801  		ipConfigurationConfigs := config["ip_configuration"].([]interface{})
   802  		ipConfigurations := make([]compute.VirtualMachineScaleSetIPConfiguration, 0, len(ipConfigurationConfigs))
   803  		for _, ipConfigConfig := range ipConfigurationConfigs {
   804  			ipconfig := ipConfigConfig.(map[string]interface{})
   805  			name := ipconfig["name"].(string)
   806  			subnetId := ipconfig["subnet_id"].(string)
   807  
   808  			ipConfiguration := compute.VirtualMachineScaleSetIPConfiguration{
   809  				Name: &name,
   810  				VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{
   811  					Subnet: &compute.APIEntityReference{
   812  						ID: &subnetId,
   813  					},
   814  				},
   815  			}
   816  			//TODO: Add the support for the load balancers when it drops
   817  			//if v := ipconfig["load_balancer_backend_address_pool_ids"]; v != nil {
   818  			//
   819  			//}
   820  
   821  			ipConfigurations = append(ipConfigurations, ipConfiguration)
   822  		}
   823  
   824  		nProfile := compute.VirtualMachineScaleSetNetworkConfiguration{
   825  			Name: &name,
   826  			VirtualMachineScaleSetNetworkConfigurationProperties: &compute.VirtualMachineScaleSetNetworkConfigurationProperties{
   827  				Primary:          &primary,
   828  				IPConfigurations: &ipConfigurations,
   829  			},
   830  		}
   831  
   832  		networkProfileConfig = append(networkProfileConfig, nProfile)
   833  	}
   834  
   835  	return &compute.VirtualMachineScaleSetNetworkProfile{
   836  		NetworkInterfaceConfigurations: &networkProfileConfig,
   837  	}
   838  }
   839  
   840  func expandAzureRMVirtualMachineScaleSetsOsProfile(d *schema.ResourceData) (*compute.VirtualMachineScaleSetOSProfile, error) {
   841  	osProfileConfigs := d.Get("os_profile").(*schema.Set).List()
   842  
   843  	osProfileConfig := osProfileConfigs[0].(map[string]interface{})
   844  	namePrefix := osProfileConfig["computer_name_prefix"].(string)
   845  	username := osProfileConfig["admin_username"].(string)
   846  	password := osProfileConfig["admin_password"].(string)
   847  	customData := osProfileConfig["custom_data"].(string)
   848  
   849  	osProfile := &compute.VirtualMachineScaleSetOSProfile{
   850  		ComputerNamePrefix: &namePrefix,
   851  		AdminUsername:      &username,
   852  	}
   853  
   854  	if password != "" {
   855  		osProfile.AdminPassword = &password
   856  	}
   857  
   858  	if customData != "" {
   859  		osProfile.CustomData = &customData
   860  	}
   861  
   862  	if _, ok := d.GetOk("os_profile_secrets"); ok {
   863  		secrets := expandAzureRmVirtualMachineScaleSetOsProfileSecrets(d)
   864  		if secrets != nil {
   865  			osProfile.Secrets = secrets
   866  		}
   867  	}
   868  
   869  	if _, ok := d.GetOk("os_profile_linux_config"); ok {
   870  		linuxConfig, err := expandAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(d)
   871  		if err != nil {
   872  			return nil, err
   873  		}
   874  		osProfile.LinuxConfiguration = linuxConfig
   875  	}
   876  
   877  	if _, ok := d.GetOk("os_profile_windows_config"); ok {
   878  		winConfig, err := expandAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(d)
   879  		if err != nil {
   880  			return nil, err
   881  		}
   882  		if winConfig != nil {
   883  			osProfile.WindowsConfiguration = winConfig
   884  		}
   885  	}
   886  
   887  	return osProfile, nil
   888  }
   889  
   890  func expandAzureRMVirtualMachineScaleSetsStorageProfileOsDisk(d *schema.ResourceData) (*compute.VirtualMachineScaleSetOSDisk, error) {
   891  	osDiskConfigs := d.Get("storage_profile_os_disk").(*schema.Set).List()
   892  
   893  	osDiskConfig := osDiskConfigs[0].(map[string]interface{})
   894  	name := osDiskConfig["name"].(string)
   895  	image := osDiskConfig["image"].(string)
   896  	caching := osDiskConfig["caching"].(string)
   897  	osType := osDiskConfig["os_type"].(string)
   898  	createOption := osDiskConfig["create_option"].(string)
   899  
   900  	var vhdContainers []string
   901  	containers := osDiskConfig["vhd_containers"].(*schema.Set).List()
   902  	for _, v := range containers {
   903  		str := v.(string)
   904  		vhdContainers = append(vhdContainers, str)
   905  	}
   906  
   907  	osDisk := &compute.VirtualMachineScaleSetOSDisk{
   908  		Name:          &name,
   909  		Caching:       compute.CachingTypes(caching),
   910  		OsType:        compute.OperatingSystemTypes(osType),
   911  		CreateOption:  compute.DiskCreateOptionTypes(createOption),
   912  		VhdContainers: &vhdContainers,
   913  	}
   914  
   915  	if image != "" {
   916  		osDisk.Image = &compute.VirtualHardDisk{
   917  			URI: &image,
   918  		}
   919  	}
   920  
   921  	return osDisk, nil
   922  
   923  }
   924  
   925  func expandAzureRmVirtualMachineScaleSetStorageProfileImageReference(d *schema.ResourceData) (*compute.ImageReference, error) {
   926  	storageImageRefs := d.Get("storage_profile_image_reference").(*schema.Set).List()
   927  
   928  	storageImageRef := storageImageRefs[0].(map[string]interface{})
   929  
   930  	publisher := storageImageRef["publisher"].(string)
   931  	offer := storageImageRef["offer"].(string)
   932  	sku := storageImageRef["sku"].(string)
   933  	version := storageImageRef["version"].(string)
   934  
   935  	return &compute.ImageReference{
   936  		Publisher: &publisher,
   937  		Offer:     &offer,
   938  		Sku:       &sku,
   939  		Version:   &version,
   940  	}, nil
   941  }
   942  
   943  func expandAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) {
   944  	osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List()
   945  
   946  	linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{})
   947  	disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool)
   948  
   949  	config := &compute.LinuxConfiguration{
   950  		DisablePasswordAuthentication: &disablePasswordAuth,
   951  	}
   952  	linuxKeys := linuxConfig["ssh_keys"].([]interface{})
   953  	sshPublicKeys := make([]compute.SSHPublicKey, 0, len(linuxKeys))
   954  	for _, key := range linuxKeys {
   955  		sshKey := key.(map[string]interface{})
   956  		path := sshKey["path"].(string)
   957  		keyData := sshKey["key_data"].(string)
   958  
   959  		sshPublicKey := compute.SSHPublicKey{
   960  			Path:    &path,
   961  			KeyData: &keyData,
   962  		}
   963  
   964  		sshPublicKeys = append(sshPublicKeys, sshPublicKey)
   965  	}
   966  
   967  	config.SSH = &compute.SSHConfiguration{
   968  		PublicKeys: &sshPublicKeys,
   969  	}
   970  
   971  	return config, nil
   972  }
   973  
   974  func expandAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) {
   975  	osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List()
   976  
   977  	osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{})
   978  	config := &compute.WindowsConfiguration{}
   979  
   980  	if v := osProfileConfig["provision_vm_agent"]; v != nil {
   981  		provision := v.(bool)
   982  		config.ProvisionVMAgent = &provision
   983  	}
   984  
   985  	if v := osProfileConfig["enable_automatic_upgrades"]; v != nil {
   986  		update := v.(bool)
   987  		config.EnableAutomaticUpdates = &update
   988  	}
   989  
   990  	if v := osProfileConfig["winrm"]; v != nil {
   991  		winRm := v.(*schema.Set).List()
   992  		if len(winRm) > 0 {
   993  			winRmListners := make([]compute.WinRMListener, 0, len(winRm))
   994  			for _, winRmConfig := range winRm {
   995  				config := winRmConfig.(map[string]interface{})
   996  
   997  				protocol := config["protocol"].(string)
   998  				winRmListner := compute.WinRMListener{
   999  					Protocol: compute.ProtocolTypes(protocol),
  1000  				}
  1001  				if v := config["certificate_url"].(string); v != "" {
  1002  					winRmListner.CertificateURL = &v
  1003  				}
  1004  
  1005  				winRmListners = append(winRmListners, winRmListner)
  1006  			}
  1007  			config.WinRM = &compute.WinRMConfiguration{
  1008  				Listeners: &winRmListners,
  1009  			}
  1010  		}
  1011  	}
  1012  	if v := osProfileConfig["additional_unattend_config"]; v != nil {
  1013  		additionalConfig := v.(*schema.Set).List()
  1014  		if len(additionalConfig) > 0 {
  1015  			additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig))
  1016  			for _, addConfig := range additionalConfig {
  1017  				config := addConfig.(map[string]interface{})
  1018  				pass := config["pass"].(string)
  1019  				component := config["component"].(string)
  1020  				settingName := config["setting_name"].(string)
  1021  				content := config["content"].(string)
  1022  
  1023  				addContent := compute.AdditionalUnattendContent{
  1024  					PassName:      compute.PassNames(pass),
  1025  					ComponentName: compute.ComponentNames(component),
  1026  					SettingName:   compute.SettingNames(settingName),
  1027  					Content:       &content,
  1028  				}
  1029  
  1030  				additionalConfigContent = append(additionalConfigContent, addContent)
  1031  			}
  1032  			config.AdditionalUnattendContent = &additionalConfigContent
  1033  		}
  1034  	}
  1035  	return config, nil
  1036  }
  1037  
  1038  func expandAzureRmVirtualMachineScaleSetOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup {
  1039  	secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List()
  1040  	secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig))
  1041  
  1042  	for _, secretConfig := range secretsConfig {
  1043  		config := secretConfig.(map[string]interface{})
  1044  		sourceVaultId := config["source_vault_id"].(string)
  1045  
  1046  		vaultSecretGroup := compute.VaultSecretGroup{
  1047  			SourceVault: &compute.SubResource{
  1048  				ID: &sourceVaultId,
  1049  			},
  1050  		}
  1051  
  1052  		if v := config["vault_certificates"]; v != nil {
  1053  			certsConfig := v.([]interface{})
  1054  			certs := make([]compute.VaultCertificate, 0, len(certsConfig))
  1055  			for _, certConfig := range certsConfig {
  1056  				config := certConfig.(map[string]interface{})
  1057  
  1058  				certUrl := config["certificate_url"].(string)
  1059  				cert := compute.VaultCertificate{
  1060  					CertificateURL: &certUrl,
  1061  				}
  1062  				if v := config["certificate_store"].(string); v != "" {
  1063  					cert.CertificateStore = &v
  1064  				}
  1065  
  1066  				certs = append(certs, cert)
  1067  			}
  1068  			vaultSecretGroup.VaultCertificates = &certs
  1069  		}
  1070  
  1071  		secrets = append(secrets, vaultSecretGroup)
  1072  	}
  1073  
  1074  	return &secrets
  1075  }