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

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