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