github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/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  	"strings"
     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  	"github.com/hashicorp/terraform/helper/structure"
    14  	"github.com/hashicorp/terraform/helper/validation"
    15  )
    16  
    17  func resourceArmVirtualMachineScaleSet() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceArmVirtualMachineScaleSetCreate,
    20  		Read:   resourceArmVirtualMachineScaleSetRead,
    21  		Update: resourceArmVirtualMachineScaleSetCreate,
    22  		Delete: resourceArmVirtualMachineScaleSetDelete,
    23  		Importer: &schema.ResourceImporter{
    24  			State: schema.ImportStatePassthrough,
    25  		},
    26  
    27  		Schema: map[string]*schema.Schema{
    28  			"name": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  
    34  			"location": locationSchema(),
    35  
    36  			"resource_group_name": {
    37  				Type:     schema.TypeString,
    38  				Required: true,
    39  				ForceNew: true,
    40  			},
    41  
    42  			"sku": {
    43  				Type:     schema.TypeSet,
    44  				Required: true,
    45  				MaxItems: 1,
    46  				Elem: &schema.Resource{
    47  					Schema: map[string]*schema.Schema{
    48  						"name": {
    49  							Type:     schema.TypeString,
    50  							Required: true,
    51  						},
    52  
    53  						"tier": {
    54  							Type:             schema.TypeString,
    55  							Optional:         true,
    56  							Computed:         true,
    57  							DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
    58  						},
    59  
    60  						"capacity": {
    61  							Type:     schema.TypeInt,
    62  							Required: true,
    63  						},
    64  					},
    65  				},
    66  				Set: resourceArmVirtualMachineScaleSetSkuHash,
    67  			},
    68  
    69  			"upgrade_policy_mode": {
    70  				Type:     schema.TypeString,
    71  				Required: true,
    72  			},
    73  
    74  			"overprovision": {
    75  				Type:     schema.TypeBool,
    76  				Optional: true,
    77  			},
    78  
    79  			"single_placement_group": {
    80  				Type:     schema.TypeBool,
    81  				Optional: true,
    82  				Default:  true,
    83  				ForceNew: true,
    84  			},
    85  
    86  			"os_profile": {
    87  				Type:     schema.TypeSet,
    88  				Required: true,
    89  				MaxItems: 1,
    90  				Elem: &schema.Resource{
    91  					Schema: map[string]*schema.Schema{
    92  						"computer_name_prefix": {
    93  							Type:     schema.TypeString,
    94  							Required: true,
    95  						},
    96  
    97  						"admin_username": {
    98  							Type:     schema.TypeString,
    99  							Required: true,
   100  						},
   101  
   102  						"admin_password": {
   103  							Type:      schema.TypeString,
   104  							Required:  true,
   105  							Sensitive: true,
   106  						},
   107  
   108  						"custom_data": {
   109  							Type:      schema.TypeString,
   110  							Optional:  true,
   111  							ForceNew:  true,
   112  							StateFunc: userDataStateFunc,
   113  						},
   114  					},
   115  				},
   116  				Set: resourceArmVirtualMachineScaleSetsOsProfileHash,
   117  			},
   118  
   119  			"os_profile_secrets": {
   120  				Type:     schema.TypeSet,
   121  				Optional: true,
   122  				Elem: &schema.Resource{
   123  					Schema: map[string]*schema.Schema{
   124  						"source_vault_id": {
   125  							Type:     schema.TypeString,
   126  							Required: true,
   127  						},
   128  
   129  						"vault_certificates": {
   130  							Type:     schema.TypeList,
   131  							Optional: true,
   132  							Elem: &schema.Resource{
   133  								Schema: map[string]*schema.Schema{
   134  									"certificate_url": {
   135  										Type:     schema.TypeString,
   136  										Required: true,
   137  									},
   138  									"certificate_store": {
   139  										Type:     schema.TypeString,
   140  										Optional: true,
   141  									},
   142  								},
   143  							},
   144  						},
   145  					},
   146  				},
   147  			},
   148  
   149  			"os_profile_windows_config": {
   150  				Type:     schema.TypeSet,
   151  				Optional: true,
   152  				MaxItems: 1,
   153  				Elem: &schema.Resource{
   154  					Schema: map[string]*schema.Schema{
   155  						"provision_vm_agent": {
   156  							Type:     schema.TypeBool,
   157  							Optional: true,
   158  						},
   159  						"enable_automatic_upgrades": {
   160  							Type:     schema.TypeBool,
   161  							Optional: true,
   162  						},
   163  						"winrm": {
   164  							Type:     schema.TypeSet,
   165  							Optional: true,
   166  							Elem: &schema.Resource{
   167  								Schema: map[string]*schema.Schema{
   168  									"protocol": {
   169  										Type:     schema.TypeString,
   170  										Required: true,
   171  									},
   172  									"certificate_url": {
   173  										Type:     schema.TypeString,
   174  										Optional: true,
   175  									},
   176  								},
   177  							},
   178  						},
   179  						"additional_unattend_config": {
   180  							Type:     schema.TypeSet,
   181  							Optional: true,
   182  							Elem: &schema.Resource{
   183  								Schema: map[string]*schema.Schema{
   184  									"pass": {
   185  										Type:     schema.TypeString,
   186  										Required: true,
   187  									},
   188  									"component": {
   189  										Type:     schema.TypeString,
   190  										Required: true,
   191  									},
   192  									"setting_name": {
   193  										Type:     schema.TypeString,
   194  										Required: true,
   195  									},
   196  									"content": {
   197  										Type:     schema.TypeString,
   198  										Required: true,
   199  									},
   200  								},
   201  							},
   202  						},
   203  					},
   204  				},
   205  				Set: resourceArmVirtualMachineScaleSetOsProfileLWindowsConfigHash,
   206  			},
   207  
   208  			"os_profile_linux_config": {
   209  				Type:     schema.TypeSet,
   210  				Optional: true,
   211  				Computed: true,
   212  				MaxItems: 1,
   213  				Elem: &schema.Resource{
   214  					Schema: map[string]*schema.Schema{
   215  						"disable_password_authentication": {
   216  							Type:     schema.TypeBool,
   217  							Optional: true,
   218  							Default:  false,
   219  							ForceNew: true,
   220  						},
   221  						"ssh_keys": {
   222  							Type:     schema.TypeList,
   223  							Optional: true,
   224  							Elem: &schema.Resource{
   225  								Schema: map[string]*schema.Schema{
   226  									"path": {
   227  										Type:     schema.TypeString,
   228  										Required: true,
   229  									},
   230  									"key_data": {
   231  										Type:     schema.TypeString,
   232  										Optional: true,
   233  									},
   234  								},
   235  							},
   236  						},
   237  					},
   238  				},
   239  				Set: resourceArmVirtualMachineScaleSetOsProfileLinuxConfigHash,
   240  			},
   241  
   242  			"network_profile": {
   243  				Type:     schema.TypeSet,
   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  						"primary": {
   253  							Type:     schema.TypeBool,
   254  							Required: true,
   255  						},
   256  
   257  						"ip_configuration": {
   258  							Type:     schema.TypeList,
   259  							Required: true,
   260  							Elem: &schema.Resource{
   261  								Schema: map[string]*schema.Schema{
   262  									"name": {
   263  										Type:     schema.TypeString,
   264  										Required: true,
   265  									},
   266  
   267  									"subnet_id": {
   268  										Type:     schema.TypeString,
   269  										Required: true,
   270  									},
   271  
   272  									"load_balancer_backend_address_pool_ids": {
   273  										Type:     schema.TypeSet,
   274  										Optional: true,
   275  										Elem:     &schema.Schema{Type: schema.TypeString},
   276  										Set:      schema.HashString,
   277  									},
   278  
   279  									"load_balancer_inbound_nat_rules_ids": {
   280  										Type:     schema.TypeSet,
   281  										Optional: true,
   282  										Computed: true,
   283  										Elem:     &schema.Schema{Type: schema.TypeString},
   284  										Set:      schema.HashString,
   285  									},
   286  								},
   287  							},
   288  						},
   289  					},
   290  				},
   291  				Set: resourceArmVirtualMachineScaleSetNetworkConfigurationHash,
   292  			},
   293  
   294  			"storage_profile_os_disk": {
   295  				Type:     schema.TypeSet,
   296  				Required: true,
   297  				MaxItems: 1,
   298  				Elem: &schema.Resource{
   299  					Schema: map[string]*schema.Schema{
   300  						"name": {
   301  							Type:     schema.TypeString,
   302  							Required: true,
   303  						},
   304  
   305  						"image": {
   306  							Type:     schema.TypeString,
   307  							Optional: true,
   308  						},
   309  
   310  						"vhd_containers": {
   311  							Type:     schema.TypeSet,
   312  							Optional: true,
   313  							Elem:     &schema.Schema{Type: schema.TypeString},
   314  							Set:      schema.HashString,
   315  						},
   316  
   317  						"managed_disk_type": {
   318  							Type:          schema.TypeString,
   319  							Optional:      true,
   320  							Computed:      true,
   321  							ConflictsWith: []string{"storage_profile_os_disk.vhd_containers"},
   322  							ValidateFunc: validation.StringInSlice([]string{
   323  								string(compute.PremiumLRS),
   324  								string(compute.StandardLRS),
   325  							}, true),
   326  						},
   327  
   328  						"caching": {
   329  							Type:     schema.TypeString,
   330  							Optional: true,
   331  							Computed: true,
   332  						},
   333  
   334  						"os_type": {
   335  							Type:     schema.TypeString,
   336  							Optional: true,
   337  						},
   338  
   339  						"create_option": {
   340  							Type:     schema.TypeString,
   341  							Required: true,
   342  						},
   343  					},
   344  				},
   345  				Set: resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash,
   346  			},
   347  
   348  			"storage_profile_data_disk": {
   349  				Type:     schema.TypeList,
   350  				Optional: true,
   351  				Elem: &schema.Resource{
   352  					Schema: map[string]*schema.Schema{
   353  						"lun": {
   354  							Type:     schema.TypeInt,
   355  							Required: true,
   356  						},
   357  
   358  						"create_option": {
   359  							Type:     schema.TypeString,
   360  							Required: true,
   361  						},
   362  
   363  						"caching": {
   364  							Type:     schema.TypeString,
   365  							Optional: true,
   366  							Computed: true,
   367  						},
   368  
   369  						"disk_size_gb": {
   370  							Type:         schema.TypeInt,
   371  							Optional:     true,
   372  							Computed:     true,
   373  							ValidateFunc: validateDiskSizeGB,
   374  						},
   375  
   376  						"managed_disk_type": {
   377  							Type:     schema.TypeString,
   378  							Optional: true,
   379  							Computed: true,
   380  							ValidateFunc: validation.StringInSlice([]string{
   381  								string(compute.PremiumLRS),
   382  								string(compute.StandardLRS),
   383  							}, true),
   384  						},
   385  					},
   386  				},
   387  			},
   388  
   389  			"storage_profile_image_reference": {
   390  				Type:     schema.TypeSet,
   391  				Optional: true,
   392  				Computed: true,
   393  				MaxItems: 1,
   394  				Elem: &schema.Resource{
   395  					Schema: map[string]*schema.Schema{
   396  						"publisher": {
   397  							Type:     schema.TypeString,
   398  							Required: true,
   399  						},
   400  
   401  						"offer": {
   402  							Type:     schema.TypeString,
   403  							Required: true,
   404  						},
   405  
   406  						"sku": {
   407  							Type:     schema.TypeString,
   408  							Required: true,
   409  						},
   410  
   411  						"version": {
   412  							Type:     schema.TypeString,
   413  							Required: true,
   414  						},
   415  					},
   416  				},
   417  				Set: resourceArmVirtualMachineScaleSetStorageProfileImageReferenceHash,
   418  			},
   419  
   420  			"extension": {
   421  				Type:     schema.TypeSet,
   422  				Optional: true,
   423  				Elem: &schema.Resource{
   424  					Schema: map[string]*schema.Schema{
   425  						"name": {
   426  							Type:     schema.TypeString,
   427  							Required: true,
   428  						},
   429  
   430  						"publisher": {
   431  							Type:     schema.TypeString,
   432  							Required: true,
   433  						},
   434  
   435  						"type": {
   436  							Type:     schema.TypeString,
   437  							Required: true,
   438  						},
   439  
   440  						"type_handler_version": {
   441  							Type:     schema.TypeString,
   442  							Required: true,
   443  						},
   444  
   445  						"auto_upgrade_minor_version": {
   446  							Type:     schema.TypeBool,
   447  							Optional: true,
   448  						},
   449  
   450  						"settings": {
   451  							Type:             schema.TypeString,
   452  							Optional:         true,
   453  							ValidateFunc:     validation.ValidateJsonString,
   454  							DiffSuppressFunc: structure.SuppressJsonDiff,
   455  						},
   456  
   457  						"protected_settings": {
   458  							Type:             schema.TypeString,
   459  							Optional:         true,
   460  							Sensitive:        true,
   461  							ValidateFunc:     validation.ValidateJsonString,
   462  							DiffSuppressFunc: structure.SuppressJsonDiff,
   463  						},
   464  					},
   465  				},
   466  				Set: resourceArmVirtualMachineScaleSetExtensionHash,
   467  			},
   468  
   469  			"tags": tagsSchema(),
   470  		},
   471  	}
   472  }
   473  
   474  func resourceArmVirtualMachineScaleSetCreate(d *schema.ResourceData, meta interface{}) error {
   475  	client := meta.(*ArmClient)
   476  	vmScaleSetClient := client.vmScaleSetClient
   477  
   478  	log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine Scale Set creation.")
   479  
   480  	name := d.Get("name").(string)
   481  	location := d.Get("location").(string)
   482  	resGroup := d.Get("resource_group_name").(string)
   483  	tags := d.Get("tags").(map[string]interface{})
   484  
   485  	sku, err := expandVirtualMachineScaleSetSku(d)
   486  	if err != nil {
   487  		return err
   488  	}
   489  
   490  	storageProfile := compute.VirtualMachineScaleSetStorageProfile{}
   491  	osDisk, err := expandAzureRMVirtualMachineScaleSetsStorageProfileOsDisk(d)
   492  	if err != nil {
   493  		return err
   494  	}
   495  	storageProfile.OsDisk = osDisk
   496  
   497  	if _, ok := d.GetOk("storage_profile_data_disk"); ok {
   498  		dataDisks, err := expandAzureRMVirtualMachineScaleSetsStorageProfileDataDisk(d)
   499  		if err != nil {
   500  			return err
   501  		}
   502  		storageProfile.DataDisks = &dataDisks
   503  	}
   504  
   505  	if _, ok := d.GetOk("storage_profile_image_reference"); ok {
   506  		imageRef, err := expandAzureRmVirtualMachineScaleSetStorageProfileImageReference(d)
   507  		if err != nil {
   508  			return err
   509  		}
   510  		storageProfile.ImageReference = imageRef
   511  	}
   512  
   513  	osProfile, err := expandAzureRMVirtualMachineScaleSetsOsProfile(d)
   514  	if err != nil {
   515  		return err
   516  	}
   517  
   518  	extensions, err := expandAzureRMVirtualMachineScaleSetExtensions(d)
   519  	if err != nil {
   520  		return err
   521  	}
   522  
   523  	updatePolicy := d.Get("upgrade_policy_mode").(string)
   524  	overprovision := d.Get("overprovision").(bool)
   525  	singlePlacementGroup := d.Get("single_placement_group").(bool)
   526  
   527  	scaleSetProps := compute.VirtualMachineScaleSetProperties{
   528  		UpgradePolicy: &compute.UpgradePolicy{
   529  			Mode: compute.UpgradeMode(updatePolicy),
   530  		},
   531  		VirtualMachineProfile: &compute.VirtualMachineScaleSetVMProfile{
   532  			NetworkProfile:   expandAzureRmVirtualMachineScaleSetNetworkProfile(d),
   533  			StorageProfile:   &storageProfile,
   534  			OsProfile:        osProfile,
   535  			ExtensionProfile: extensions,
   536  		},
   537  		Overprovision:        &overprovision,
   538  		SinglePlacementGroup: &singlePlacementGroup,
   539  	}
   540  
   541  	scaleSetParams := compute.VirtualMachineScaleSet{
   542  		Name:     &name,
   543  		Location: &location,
   544  		Tags:     expandTags(tags),
   545  		Sku:      sku,
   546  		VirtualMachineScaleSetProperties: &scaleSetProps,
   547  	}
   548  	_, vmError := vmScaleSetClient.CreateOrUpdate(resGroup, name, scaleSetParams, make(chan struct{}))
   549  	vmErr := <-vmError
   550  	if vmErr != nil {
   551  		return vmErr
   552  	}
   553  
   554  	read, err := vmScaleSetClient.Get(resGroup, name)
   555  	if err != nil {
   556  		return err
   557  	}
   558  	if read.ID == nil {
   559  		return fmt.Errorf("Cannot read Virtual Machine Scale Set %s (resource group %s) ID", name, resGroup)
   560  	}
   561  
   562  	d.SetId(*read.ID)
   563  
   564  	return resourceArmVirtualMachineScaleSetRead(d, meta)
   565  }
   566  
   567  func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interface{}) error {
   568  	vmScaleSetClient := meta.(*ArmClient).vmScaleSetClient
   569  
   570  	id, err := parseAzureResourceID(d.Id())
   571  	if err != nil {
   572  		return err
   573  	}
   574  	resGroup := id.ResourceGroup
   575  	name := id.Path["virtualMachineScaleSets"]
   576  
   577  	resp, err := vmScaleSetClient.Get(resGroup, name)
   578  	if err != nil {
   579  		if resp.StatusCode == http.StatusNotFound {
   580  			log.Printf("[INFO] AzureRM Virtual Machine Scale Set (%s) Not Found. Removing from State", name)
   581  			d.SetId("")
   582  			return nil
   583  		}
   584  		return fmt.Errorf("Error making Read request on Azure Virtual Machine Scale Set %s: %s", name, err)
   585  	}
   586  
   587  	d.Set("name", resp.Name)
   588  	d.Set("resource_group_name", resGroup)
   589  	d.Set("location", azureRMNormalizeLocation(*resp.Location))
   590  
   591  	if err := d.Set("sku", flattenAzureRmVirtualMachineScaleSetSku(resp.Sku)); err != nil {
   592  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Sku error: %#v", err)
   593  	}
   594  
   595  	properties := resp.VirtualMachineScaleSetProperties
   596  
   597  	d.Set("upgrade_policy_mode", properties.UpgradePolicy.Mode)
   598  	d.Set("overprovision", properties.Overprovision)
   599  	d.Set("single_placement_group", properties.SinglePlacementGroup)
   600  
   601  	osProfile, err := flattenAzureRMVirtualMachineScaleSetOsProfile(properties.VirtualMachineProfile.OsProfile)
   602  	if err != nil {
   603  		return fmt.Errorf("[DEBUG] Error flattening Virtual Machine Scale Set OS Profile. Error: %#v", err)
   604  	}
   605  
   606  	if err := d.Set("os_profile", osProfile); err != nil {
   607  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile error: %#v", err)
   608  	}
   609  
   610  	if properties.VirtualMachineProfile.OsProfile.Secrets != nil {
   611  		if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineScaleSetOsProfileSecrets(properties.VirtualMachineProfile.OsProfile.Secrets)); err != nil {
   612  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Secrets error: %#v", err)
   613  		}
   614  	}
   615  
   616  	if properties.VirtualMachineProfile.OsProfile.WindowsConfiguration != nil {
   617  		if err := d.Set("os_profile_windows_config", flattenAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(properties.VirtualMachineProfile.OsProfile.WindowsConfiguration)); err != nil {
   618  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Windows config error: %#v", err)
   619  		}
   620  	}
   621  
   622  	if properties.VirtualMachineProfile.OsProfile.LinuxConfiguration != nil {
   623  		if err := d.Set("os_profile_linux_config", flattenAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(properties.VirtualMachineProfile.OsProfile.LinuxConfiguration)); err != nil {
   624  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set OS Profile Windows config error: %#v", err)
   625  		}
   626  	}
   627  
   628  	if err := d.Set("network_profile", flattenAzureRmVirtualMachineScaleSetNetworkProfile(properties.VirtualMachineProfile.NetworkProfile)); err != nil {
   629  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Network Profile error: %#v", err)
   630  	}
   631  
   632  	if properties.VirtualMachineProfile.StorageProfile.ImageReference != nil {
   633  		if err := d.Set("storage_profile_image_reference", flattenAzureRmVirtualMachineScaleSetStorageProfileImageReference(properties.VirtualMachineProfile.StorageProfile.ImageReference)); err != nil {
   634  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile Image Reference error: %#v", err)
   635  		}
   636  	}
   637  
   638  	if err := d.Set("storage_profile_os_disk", flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(properties.VirtualMachineProfile.StorageProfile.OsDisk)); err != nil {
   639  		return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile OS Disk error: %#v", err)
   640  	}
   641  
   642  	if resp.VirtualMachineProfile.StorageProfile.DataDisks != nil {
   643  		if err := d.Set("storage_profile_data_disk", flattenAzureRmVirtualMachineScaleSetStorageProfileDataDisk(properties.VirtualMachineProfile.StorageProfile.DataDisks)); err != nil {
   644  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile Data Disk error: %#v", err)
   645  		}
   646  	}
   647  
   648  	if properties.VirtualMachineProfile.ExtensionProfile != nil {
   649  		extension, err := flattenAzureRmVirtualMachineScaleSetExtensionProfile(properties.VirtualMachineProfile.ExtensionProfile)
   650  		if err != nil {
   651  			return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Extension Profile error: %#v", err)
   652  		}
   653  		d.Set("extension", extension)
   654  	}
   655  
   656  	flattenAndSetTags(d, resp.Tags)
   657  
   658  	return nil
   659  }
   660  
   661  func resourceArmVirtualMachineScaleSetDelete(d *schema.ResourceData, meta interface{}) error {
   662  	vmScaleSetClient := meta.(*ArmClient).vmScaleSetClient
   663  
   664  	id, err := parseAzureResourceID(d.Id())
   665  	if err != nil {
   666  		return err
   667  	}
   668  	resGroup := id.ResourceGroup
   669  	name := id.Path["virtualMachineScaleSets"]
   670  
   671  	_, error := vmScaleSetClient.Delete(resGroup, name, make(chan struct{}))
   672  	err = <-error
   673  
   674  	return err
   675  }
   676  
   677  func flattenAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(config *compute.LinuxConfiguration) []interface{} {
   678  	result := make(map[string]interface{})
   679  	result["disable_password_authentication"] = *config.DisablePasswordAuthentication
   680  
   681  	if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 {
   682  		ssh_keys := make([]map[string]interface{}, 0, len(*config.SSH.PublicKeys))
   683  		for _, i := range *config.SSH.PublicKeys {
   684  			key := make(map[string]interface{})
   685  			key["path"] = *i.Path
   686  
   687  			if i.KeyData != nil {
   688  				key["key_data"] = *i.KeyData
   689  			}
   690  
   691  			ssh_keys = append(ssh_keys, key)
   692  		}
   693  
   694  		result["ssh_keys"] = ssh_keys
   695  	}
   696  
   697  	return []interface{}{result}
   698  }
   699  
   700  func flattenAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(config *compute.WindowsConfiguration) []interface{} {
   701  	result := make(map[string]interface{})
   702  
   703  	if config.ProvisionVMAgent != nil {
   704  		result["provision_vm_agent"] = *config.ProvisionVMAgent
   705  	}
   706  
   707  	if config.EnableAutomaticUpdates != nil {
   708  		result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates
   709  	}
   710  
   711  	if config.WinRM != nil {
   712  		listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners))
   713  		for _, i := range *config.WinRM.Listeners {
   714  			listener := make(map[string]interface{})
   715  			listener["protocol"] = i.Protocol
   716  
   717  			if i.CertificateURL != nil {
   718  				listener["certificate_url"] = *i.CertificateURL
   719  			}
   720  
   721  			listeners = append(listeners, listener)
   722  		}
   723  
   724  		result["winrm"] = listeners
   725  	}
   726  
   727  	if config.AdditionalUnattendContent != nil {
   728  		content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent))
   729  		for _, i := range *config.AdditionalUnattendContent {
   730  			c := make(map[string]interface{})
   731  			c["pass"] = i.PassName
   732  			c["component"] = i.ComponentName
   733  			c["setting_name"] = i.SettingName
   734  			c["content"] = *i.Content
   735  
   736  			content = append(content, c)
   737  		}
   738  
   739  		result["additional_unattend_config"] = content
   740  	}
   741  
   742  	return []interface{}{result}
   743  }
   744  
   745  func flattenAzureRmVirtualMachineScaleSetOsProfileSecrets(secrets *[]compute.VaultSecretGroup) []map[string]interface{} {
   746  	result := make([]map[string]interface{}, 0, len(*secrets))
   747  	for _, secret := range *secrets {
   748  		s := map[string]interface{}{
   749  			"source_vault_id": *secret.SourceVault.ID,
   750  		}
   751  
   752  		if secret.VaultCertificates != nil {
   753  			certs := make([]map[string]interface{}, 0, len(*secret.VaultCertificates))
   754  			for _, cert := range *secret.VaultCertificates {
   755  				vaultCert := make(map[string]interface{})
   756  				vaultCert["certificate_url"] = *cert.CertificateURL
   757  
   758  				if cert.CertificateStore != nil {
   759  					vaultCert["certificate_store"] = *cert.CertificateStore
   760  				}
   761  
   762  				certs = append(certs, vaultCert)
   763  			}
   764  
   765  			s["vault_certificates"] = certs
   766  		}
   767  
   768  		result = append(result, s)
   769  	}
   770  	return result
   771  }
   772  
   773  func flattenAzureRmVirtualMachineScaleSetNetworkProfile(profile *compute.VirtualMachineScaleSetNetworkProfile) []map[string]interface{} {
   774  	networkConfigurations := profile.NetworkInterfaceConfigurations
   775  	result := make([]map[string]interface{}, 0, len(*networkConfigurations))
   776  	for _, netConfig := range *networkConfigurations {
   777  		s := map[string]interface{}{
   778  			"name":    *netConfig.Name,
   779  			"primary": *netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.Primary,
   780  		}
   781  
   782  		if netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.IPConfigurations != nil {
   783  			ipConfigs := make([]map[string]interface{}, 0, len(*netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.IPConfigurations))
   784  			for _, ipConfig := range *netConfig.VirtualMachineScaleSetNetworkConfigurationProperties.IPConfigurations {
   785  				config := make(map[string]interface{})
   786  				config["name"] = *ipConfig.Name
   787  
   788  				properties := ipConfig.VirtualMachineScaleSetIPConfigurationProperties
   789  
   790  				if ipConfig.VirtualMachineScaleSetIPConfigurationProperties.Subnet != nil {
   791  					config["subnet_id"] = *properties.Subnet.ID
   792  				}
   793  
   794  				if properties.LoadBalancerBackendAddressPools != nil {
   795  					addressPools := make([]interface{}, 0, len(*properties.LoadBalancerBackendAddressPools))
   796  					for _, pool := range *properties.LoadBalancerBackendAddressPools {
   797  						addressPools = append(addressPools, *pool.ID)
   798  					}
   799  					config["load_balancer_backend_address_pool_ids"] = schema.NewSet(schema.HashString, addressPools)
   800  				}
   801  
   802  				if properties.LoadBalancerInboundNatPools != nil {
   803  					inboundNatPools := make([]interface{}, 0, len(*properties.LoadBalancerInboundNatPools))
   804  					for _, rule := range *properties.LoadBalancerInboundNatPools {
   805  						inboundNatPools = append(inboundNatPools, *rule.ID)
   806  					}
   807  					config["load_balancer_inbound_nat_rules_ids"] = schema.NewSet(schema.HashString, inboundNatPools)
   808  				}
   809  
   810  				ipConfigs = append(ipConfigs, config)
   811  			}
   812  
   813  			s["ip_configuration"] = ipConfigs
   814  		}
   815  
   816  		result = append(result, s)
   817  	}
   818  
   819  	return result
   820  }
   821  
   822  func flattenAzureRMVirtualMachineScaleSetOsProfile(profile *compute.VirtualMachineScaleSetOSProfile) ([]interface{}, error) {
   823  	result := make(map[string]interface{})
   824  
   825  	result["computer_name_prefix"] = *profile.ComputerNamePrefix
   826  	result["admin_username"] = *profile.AdminUsername
   827  
   828  	if profile.CustomData != nil {
   829  		result["custom_data"] = *profile.CustomData
   830  	}
   831  
   832  	return []interface{}{result}, nil
   833  }
   834  
   835  func flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(profile *compute.VirtualMachineScaleSetOSDisk) []interface{} {
   836  	result := make(map[string]interface{})
   837  
   838  	if profile.Name != nil {
   839  		result["name"] = *profile.Name
   840  	}
   841  
   842  	if profile.Image != nil {
   843  		result["image"] = *profile.Image.URI
   844  	}
   845  
   846  	if profile.VhdContainers != nil {
   847  		containers := make([]interface{}, 0, len(*profile.VhdContainers))
   848  		for _, container := range *profile.VhdContainers {
   849  			containers = append(containers, container)
   850  		}
   851  		result["vhd_containers"] = schema.NewSet(schema.HashString, containers)
   852  	}
   853  
   854  	if profile.ManagedDisk != nil {
   855  		result["managed_disk_type"] = string(profile.ManagedDisk.StorageAccountType)
   856  	}
   857  
   858  	result["caching"] = profile.Caching
   859  	result["create_option"] = profile.CreateOption
   860  	result["os_type"] = profile.OsType
   861  
   862  	return []interface{}{result}
   863  }
   864  
   865  func flattenAzureRmVirtualMachineScaleSetStorageProfileDataDisk(disks *[]compute.VirtualMachineScaleSetDataDisk) interface{} {
   866  	result := make([]interface{}, len(*disks))
   867  	for i, disk := range *disks {
   868  		l := make(map[string]interface{})
   869  		if disk.ManagedDisk != nil {
   870  			l["managed_disk_type"] = string(disk.ManagedDisk.StorageAccountType)
   871  		}
   872  
   873  		l["create_option"] = disk.CreateOption
   874  		l["caching"] = string(disk.Caching)
   875  		if disk.DiskSizeGB != nil {
   876  			l["disk_size_gb"] = *disk.DiskSizeGB
   877  		}
   878  		l["lun"] = *disk.Lun
   879  
   880  		result[i] = l
   881  	}
   882  	return result
   883  }
   884  
   885  func flattenAzureRmVirtualMachineScaleSetStorageProfileImageReference(profile *compute.ImageReference) []interface{} {
   886  	result := make(map[string]interface{})
   887  	result["publisher"] = *profile.Publisher
   888  	result["offer"] = *profile.Offer
   889  	result["sku"] = *profile.Sku
   890  	result["version"] = *profile.Version
   891  
   892  	return []interface{}{result}
   893  }
   894  
   895  func flattenAzureRmVirtualMachineScaleSetSku(sku *compute.Sku) []interface{} {
   896  	result := make(map[string]interface{})
   897  	result["name"] = *sku.Name
   898  	result["capacity"] = *sku.Capacity
   899  
   900  	if *sku.Tier != "" {
   901  		result["tier"] = *sku.Tier
   902  	}
   903  
   904  	return []interface{}{result}
   905  }
   906  
   907  func flattenAzureRmVirtualMachineScaleSetExtensionProfile(profile *compute.VirtualMachineScaleSetExtensionProfile) ([]map[string]interface{}, error) {
   908  	if profile.Extensions == nil {
   909  		return nil, nil
   910  	}
   911  
   912  	result := make([]map[string]interface{}, 0, len(*profile.Extensions))
   913  	for _, extension := range *profile.Extensions {
   914  		e := make(map[string]interface{})
   915  		e["name"] = *extension.Name
   916  		properties := extension.VirtualMachineScaleSetExtensionProperties
   917  		if properties != nil {
   918  			e["publisher"] = *properties.Publisher
   919  			e["type"] = *properties.Type
   920  			e["type_handler_version"] = *properties.TypeHandlerVersion
   921  			if properties.AutoUpgradeMinorVersion != nil {
   922  				e["auto_upgrade_minor_version"] = *properties.AutoUpgradeMinorVersion
   923  			}
   924  
   925  			if properties.Settings != nil {
   926  				settings, err := structure.FlattenJsonToString(*properties.Settings)
   927  				if err != nil {
   928  					return nil, err
   929  				}
   930  				e["settings"] = settings
   931  			}
   932  		}
   933  
   934  		result = append(result, e)
   935  	}
   936  
   937  	return result, nil
   938  }
   939  
   940  func resourceArmVirtualMachineScaleSetStorageProfileImageReferenceHash(v interface{}) int {
   941  	var buf bytes.Buffer
   942  	m := v.(map[string]interface{})
   943  	buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string)))
   944  	buf.WriteString(fmt.Sprintf("%s-", m["offer"].(string)))
   945  	buf.WriteString(fmt.Sprintf("%s-", m["sku"].(string)))
   946  	buf.WriteString(fmt.Sprintf("%s-", m["version"].(string)))
   947  
   948  	return hashcode.String(buf.String())
   949  }
   950  
   951  func resourceArmVirtualMachineScaleSetSkuHash(v interface{}) int {
   952  	var buf bytes.Buffer
   953  	m := v.(map[string]interface{})
   954  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   955  	if m["tier"] != nil {
   956  		buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["tier"].(string))))
   957  	}
   958  	buf.WriteString(fmt.Sprintf("%d-", m["capacity"].(int)))
   959  
   960  	return hashcode.String(buf.String())
   961  }
   962  
   963  func resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash(v interface{}) int {
   964  	var buf bytes.Buffer
   965  	m := v.(map[string]interface{})
   966  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   967  
   968  	if m["vhd_containers"] != nil {
   969  		buf.WriteString(fmt.Sprintf("%s-", m["vhd_containers"].(*schema.Set).List()))
   970  	}
   971  
   972  	return hashcode.String(buf.String())
   973  }
   974  
   975  func resourceArmVirtualMachineScaleSetNetworkConfigurationHash(v interface{}) int {
   976  	var buf bytes.Buffer
   977  	m := v.(map[string]interface{})
   978  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   979  	buf.WriteString(fmt.Sprintf("%t-", m["primary"].(bool)))
   980  	return hashcode.String(buf.String())
   981  }
   982  
   983  func resourceArmVirtualMachineScaleSetsOsProfileHash(v interface{}) int {
   984  	var buf bytes.Buffer
   985  	m := v.(map[string]interface{})
   986  	buf.WriteString(fmt.Sprintf("%s-", m["computer_name_prefix"].(string)))
   987  	buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string)))
   988  	if m["custom_data"] != nil {
   989  		customData := m["custom_data"].(string)
   990  		if !isBase64Encoded(customData) {
   991  			customData = base64Encode(customData)
   992  		}
   993  		buf.WriteString(fmt.Sprintf("%s-", customData))
   994  	}
   995  	return hashcode.String(buf.String())
   996  }
   997  
   998  func resourceArmVirtualMachineScaleSetOsProfileLinuxConfigHash(v interface{}) int {
   999  	var buf bytes.Buffer
  1000  	m := v.(map[string]interface{})
  1001  	buf.WriteString(fmt.Sprintf("%t-", m["disable_password_authentication"].(bool)))
  1002  
  1003  	return hashcode.String(buf.String())
  1004  }
  1005  
  1006  func resourceArmVirtualMachineScaleSetOsProfileLWindowsConfigHash(v interface{}) int {
  1007  	var buf bytes.Buffer
  1008  	m := v.(map[string]interface{})
  1009  	if m["provision_vm_agent"] != nil {
  1010  		buf.WriteString(fmt.Sprintf("%t-", m["provision_vm_agent"].(bool)))
  1011  	}
  1012  	if m["enable_automatic_upgrades"] != nil {
  1013  		buf.WriteString(fmt.Sprintf("%t-", m["enable_automatic_upgrades"].(bool)))
  1014  	}
  1015  	return hashcode.String(buf.String())
  1016  }
  1017  
  1018  func resourceArmVirtualMachineScaleSetExtensionHash(v interface{}) int {
  1019  	var buf bytes.Buffer
  1020  	m := v.(map[string]interface{})
  1021  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
  1022  	buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string)))
  1023  	buf.WriteString(fmt.Sprintf("%s-", m["type"].(string)))
  1024  	buf.WriteString(fmt.Sprintf("%s-", m["type_handler_version"].(string)))
  1025  	if m["auto_upgrade_minor_version"] != nil {
  1026  		buf.WriteString(fmt.Sprintf("%t-", m["auto_upgrade_minor_version"].(bool)))
  1027  	}
  1028  
  1029  	return hashcode.String(buf.String())
  1030  }
  1031  
  1032  func expandVirtualMachineScaleSetSku(d *schema.ResourceData) (*compute.Sku, error) {
  1033  	skuConfig := d.Get("sku").(*schema.Set).List()
  1034  
  1035  	config := skuConfig[0].(map[string]interface{})
  1036  
  1037  	name := config["name"].(string)
  1038  	tier := config["tier"].(string)
  1039  	capacity := int64(config["capacity"].(int))
  1040  
  1041  	sku := &compute.Sku{
  1042  		Name:     &name,
  1043  		Capacity: &capacity,
  1044  	}
  1045  
  1046  	if tier != "" {
  1047  		sku.Tier = &tier
  1048  	}
  1049  
  1050  	return sku, nil
  1051  }
  1052  
  1053  func expandAzureRmVirtualMachineScaleSetNetworkProfile(d *schema.ResourceData) *compute.VirtualMachineScaleSetNetworkProfile {
  1054  	scaleSetNetworkProfileConfigs := d.Get("network_profile").(*schema.Set).List()
  1055  	networkProfileConfig := make([]compute.VirtualMachineScaleSetNetworkConfiguration, 0, len(scaleSetNetworkProfileConfigs))
  1056  
  1057  	for _, npProfileConfig := range scaleSetNetworkProfileConfigs {
  1058  		config := npProfileConfig.(map[string]interface{})
  1059  
  1060  		name := config["name"].(string)
  1061  		primary := config["primary"].(bool)
  1062  
  1063  		ipConfigurationConfigs := config["ip_configuration"].([]interface{})
  1064  		ipConfigurations := make([]compute.VirtualMachineScaleSetIPConfiguration, 0, len(ipConfigurationConfigs))
  1065  		for _, ipConfigConfig := range ipConfigurationConfigs {
  1066  			ipconfig := ipConfigConfig.(map[string]interface{})
  1067  			name := ipconfig["name"].(string)
  1068  			subnetId := ipconfig["subnet_id"].(string)
  1069  
  1070  			ipConfiguration := compute.VirtualMachineScaleSetIPConfiguration{
  1071  				Name: &name,
  1072  				VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{
  1073  					Subnet: &compute.APIEntityReference{
  1074  						ID: &subnetId,
  1075  					},
  1076  				},
  1077  			}
  1078  
  1079  			if v := ipconfig["load_balancer_backend_address_pool_ids"]; v != nil {
  1080  				pools := v.(*schema.Set).List()
  1081  				resources := make([]compute.SubResource, 0, len(pools))
  1082  				for _, p := range pools {
  1083  					id := p.(string)
  1084  					resources = append(resources, compute.SubResource{
  1085  						ID: &id,
  1086  					})
  1087  				}
  1088  				ipConfiguration.LoadBalancerBackendAddressPools = &resources
  1089  			}
  1090  
  1091  			if v := ipconfig["load_balancer_inbound_nat_rules_ids"]; v != nil {
  1092  				rules := v.(*schema.Set).List()
  1093  				rulesResources := make([]compute.SubResource, 0, len(rules))
  1094  				for _, m := range rules {
  1095  					id := m.(string)
  1096  					rulesResources = append(rulesResources, compute.SubResource{
  1097  						ID: &id,
  1098  					})
  1099  				}
  1100  				ipConfiguration.LoadBalancerInboundNatPools = &rulesResources
  1101  			}
  1102  
  1103  			ipConfigurations = append(ipConfigurations, ipConfiguration)
  1104  		}
  1105  
  1106  		nProfile := compute.VirtualMachineScaleSetNetworkConfiguration{
  1107  			Name: &name,
  1108  			VirtualMachineScaleSetNetworkConfigurationProperties: &compute.VirtualMachineScaleSetNetworkConfigurationProperties{
  1109  				Primary:          &primary,
  1110  				IPConfigurations: &ipConfigurations,
  1111  			},
  1112  		}
  1113  
  1114  		networkProfileConfig = append(networkProfileConfig, nProfile)
  1115  	}
  1116  
  1117  	return &compute.VirtualMachineScaleSetNetworkProfile{
  1118  		NetworkInterfaceConfigurations: &networkProfileConfig,
  1119  	}
  1120  }
  1121  
  1122  func expandAzureRMVirtualMachineScaleSetsOsProfile(d *schema.ResourceData) (*compute.VirtualMachineScaleSetOSProfile, error) {
  1123  	osProfileConfigs := d.Get("os_profile").(*schema.Set).List()
  1124  
  1125  	osProfileConfig := osProfileConfigs[0].(map[string]interface{})
  1126  	namePrefix := osProfileConfig["computer_name_prefix"].(string)
  1127  	username := osProfileConfig["admin_username"].(string)
  1128  	password := osProfileConfig["admin_password"].(string)
  1129  	customData := osProfileConfig["custom_data"].(string)
  1130  
  1131  	osProfile := &compute.VirtualMachineScaleSetOSProfile{
  1132  		ComputerNamePrefix: &namePrefix,
  1133  		AdminUsername:      &username,
  1134  	}
  1135  
  1136  	if password != "" {
  1137  		osProfile.AdminPassword = &password
  1138  	}
  1139  
  1140  	if customData != "" {
  1141  		customData = base64Encode(customData)
  1142  		osProfile.CustomData = &customData
  1143  	}
  1144  
  1145  	if _, ok := d.GetOk("os_profile_secrets"); ok {
  1146  		secrets := expandAzureRmVirtualMachineScaleSetOsProfileSecrets(d)
  1147  		if secrets != nil {
  1148  			osProfile.Secrets = secrets
  1149  		}
  1150  	}
  1151  
  1152  	if _, ok := d.GetOk("os_profile_linux_config"); ok {
  1153  		linuxConfig, err := expandAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(d)
  1154  		if err != nil {
  1155  			return nil, err
  1156  		}
  1157  		osProfile.LinuxConfiguration = linuxConfig
  1158  	}
  1159  
  1160  	if _, ok := d.GetOk("os_profile_windows_config"); ok {
  1161  		winConfig, err := expandAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(d)
  1162  		if err != nil {
  1163  			return nil, err
  1164  		}
  1165  		if winConfig != nil {
  1166  			osProfile.WindowsConfiguration = winConfig
  1167  		}
  1168  	}
  1169  
  1170  	return osProfile, nil
  1171  }
  1172  
  1173  func expandAzureRMVirtualMachineScaleSetsStorageProfileOsDisk(d *schema.ResourceData) (*compute.VirtualMachineScaleSetOSDisk, error) {
  1174  	osDiskConfigs := d.Get("storage_profile_os_disk").(*schema.Set).List()
  1175  
  1176  	osDiskConfig := osDiskConfigs[0].(map[string]interface{})
  1177  	name := osDiskConfig["name"].(string)
  1178  	image := osDiskConfig["image"].(string)
  1179  	vhd_containers := osDiskConfig["vhd_containers"].(*schema.Set).List()
  1180  	caching := osDiskConfig["caching"].(string)
  1181  	osType := osDiskConfig["os_type"].(string)
  1182  	createOption := osDiskConfig["create_option"].(string)
  1183  	managedDiskType := osDiskConfig["managed_disk_type"].(string)
  1184  
  1185  	osDisk := &compute.VirtualMachineScaleSetOSDisk{
  1186  		Name:         &name,
  1187  		Caching:      compute.CachingTypes(caching),
  1188  		OsType:       compute.OperatingSystemTypes(osType),
  1189  		CreateOption: compute.DiskCreateOptionTypes(createOption),
  1190  	}
  1191  
  1192  	if image != "" {
  1193  		osDisk.Image = &compute.VirtualHardDisk{
  1194  			URI: &image,
  1195  		}
  1196  	}
  1197  
  1198  	if len(vhd_containers) > 0 {
  1199  		var vhdContainers []string
  1200  		for _, v := range vhd_containers {
  1201  			str := v.(string)
  1202  			vhdContainers = append(vhdContainers, str)
  1203  		}
  1204  		osDisk.VhdContainers = &vhdContainers
  1205  	}
  1206  
  1207  	managedDisk := &compute.VirtualMachineScaleSetManagedDiskParameters{}
  1208  
  1209  	if managedDiskType != "" {
  1210  		if name == "" {
  1211  			osDisk.Name = nil
  1212  			managedDisk.StorageAccountType = compute.StorageAccountTypes(managedDiskType)
  1213  			osDisk.ManagedDisk = managedDisk
  1214  		} else {
  1215  			return nil, fmt.Errorf("[ERROR] Conflict between `name` and `managed_disk_type` on `storage_profile_os_disk` (please set name to blank)")
  1216  		}
  1217  	}
  1218  
  1219  	//BEGIN: code to be removed after GH-13016 is merged
  1220  	if image != "" && managedDiskType != "" {
  1221  		return nil, fmt.Errorf("[ERROR] Conflict between `image` and `managed_disk_type` on `storage_profile_os_disk` (only one or the other can be used)")
  1222  	}
  1223  
  1224  	if len(vhd_containers) > 0 && managedDiskType != "" {
  1225  		return nil, fmt.Errorf("[ERROR] Conflict between `vhd_containers` and `managed_disk_type` on `storage_profile_os_disk` (only one or the other can be used)")
  1226  	}
  1227  	//END: code to be removed after GH-13016 is merged
  1228  
  1229  	return osDisk, nil
  1230  }
  1231  
  1232  func expandAzureRMVirtualMachineScaleSetsStorageProfileDataDisk(d *schema.ResourceData) ([]compute.VirtualMachineScaleSetDataDisk, error) {
  1233  	disks := d.Get("storage_profile_data_disk").([]interface{})
  1234  	dataDisks := make([]compute.VirtualMachineScaleSetDataDisk, 0, len(disks))
  1235  	for _, diskConfig := range disks {
  1236  		config := diskConfig.(map[string]interface{})
  1237  
  1238  		createOption := config["create_option"].(string)
  1239  		managedDiskType := config["managed_disk_type"].(string)
  1240  		lun := int32(config["lun"].(int))
  1241  
  1242  		dataDisk := compute.VirtualMachineScaleSetDataDisk{
  1243  			Lun:          &lun,
  1244  			CreateOption: compute.DiskCreateOptionTypes(createOption),
  1245  		}
  1246  
  1247  		managedDiskVMSS := &compute.VirtualMachineScaleSetManagedDiskParameters{}
  1248  
  1249  		if managedDiskType != "" {
  1250  			managedDiskVMSS.StorageAccountType = compute.StorageAccountTypes(managedDiskType)
  1251  		} else {
  1252  			managedDiskVMSS.StorageAccountType = compute.StorageAccountTypes(compute.StandardLRS)
  1253  		}
  1254  
  1255  		//assume that data disks in VMSS can only be Managed Disks
  1256  		dataDisk.ManagedDisk = managedDiskVMSS
  1257  		if v := config["caching"].(string); v != "" {
  1258  			dataDisk.Caching = compute.CachingTypes(v)
  1259  		}
  1260  
  1261  		if v := config["disk_size_gb"]; v != nil {
  1262  			diskSize := int32(config["disk_size_gb"].(int))
  1263  			dataDisk.DiskSizeGB = &diskSize
  1264  		}
  1265  
  1266  		dataDisks = append(dataDisks, dataDisk)
  1267  	}
  1268  
  1269  	return dataDisks, nil
  1270  }
  1271  
  1272  func expandAzureRmVirtualMachineScaleSetStorageProfileImageReference(d *schema.ResourceData) (*compute.ImageReference, error) {
  1273  	storageImageRefs := d.Get("storage_profile_image_reference").(*schema.Set).List()
  1274  
  1275  	storageImageRef := storageImageRefs[0].(map[string]interface{})
  1276  
  1277  	publisher := storageImageRef["publisher"].(string)
  1278  	offer := storageImageRef["offer"].(string)
  1279  	sku := storageImageRef["sku"].(string)
  1280  	version := storageImageRef["version"].(string)
  1281  
  1282  	return &compute.ImageReference{
  1283  		Publisher: &publisher,
  1284  		Offer:     &offer,
  1285  		Sku:       &sku,
  1286  		Version:   &version,
  1287  	}, nil
  1288  }
  1289  
  1290  func expandAzureRmVirtualMachineScaleSetOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) {
  1291  	osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List()
  1292  
  1293  	linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{})
  1294  	disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool)
  1295  
  1296  	linuxKeys := linuxConfig["ssh_keys"].([]interface{})
  1297  	sshPublicKeys := make([]compute.SSHPublicKey, 0, len(linuxKeys))
  1298  	for _, key := range linuxKeys {
  1299  		if key == nil {
  1300  			continue
  1301  		}
  1302  		sshKey := key.(map[string]interface{})
  1303  		path := sshKey["path"].(string)
  1304  		keyData := sshKey["key_data"].(string)
  1305  
  1306  		sshPublicKey := compute.SSHPublicKey{
  1307  			Path:    &path,
  1308  			KeyData: &keyData,
  1309  		}
  1310  
  1311  		sshPublicKeys = append(sshPublicKeys, sshPublicKey)
  1312  	}
  1313  
  1314  	config := &compute.LinuxConfiguration{
  1315  		DisablePasswordAuthentication: &disablePasswordAuth,
  1316  		SSH: &compute.SSHConfiguration{
  1317  			PublicKeys: &sshPublicKeys,
  1318  		},
  1319  	}
  1320  
  1321  	return config, nil
  1322  }
  1323  
  1324  func expandAzureRmVirtualMachineScaleSetOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) {
  1325  	osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List()
  1326  
  1327  	osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{})
  1328  	config := &compute.WindowsConfiguration{}
  1329  
  1330  	if v := osProfileConfig["provision_vm_agent"]; v != nil {
  1331  		provision := v.(bool)
  1332  		config.ProvisionVMAgent = &provision
  1333  	}
  1334  
  1335  	if v := osProfileConfig["enable_automatic_upgrades"]; v != nil {
  1336  		update := v.(bool)
  1337  		config.EnableAutomaticUpdates = &update
  1338  	}
  1339  
  1340  	if v := osProfileConfig["winrm"]; v != nil {
  1341  		winRm := v.(*schema.Set).List()
  1342  		if len(winRm) > 0 {
  1343  			winRmListeners := make([]compute.WinRMListener, 0, len(winRm))
  1344  			for _, winRmConfig := range winRm {
  1345  				config := winRmConfig.(map[string]interface{})
  1346  
  1347  				protocol := config["protocol"].(string)
  1348  				winRmListener := compute.WinRMListener{
  1349  					Protocol: compute.ProtocolTypes(protocol),
  1350  				}
  1351  				if v := config["certificate_url"].(string); v != "" {
  1352  					winRmListener.CertificateURL = &v
  1353  				}
  1354  
  1355  				winRmListeners = append(winRmListeners, winRmListener)
  1356  			}
  1357  			config.WinRM = &compute.WinRMConfiguration{
  1358  				Listeners: &winRmListeners,
  1359  			}
  1360  		}
  1361  	}
  1362  	if v := osProfileConfig["additional_unattend_config"]; v != nil {
  1363  		additionalConfig := v.(*schema.Set).List()
  1364  		if len(additionalConfig) > 0 {
  1365  			additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig))
  1366  			for _, addConfig := range additionalConfig {
  1367  				config := addConfig.(map[string]interface{})
  1368  				pass := config["pass"].(string)
  1369  				component := config["component"].(string)
  1370  				settingName := config["setting_name"].(string)
  1371  				content := config["content"].(string)
  1372  
  1373  				addContent := compute.AdditionalUnattendContent{
  1374  					PassName:      compute.PassNames(pass),
  1375  					ComponentName: compute.ComponentNames(component),
  1376  					SettingName:   compute.SettingNames(settingName),
  1377  					Content:       &content,
  1378  				}
  1379  
  1380  				additionalConfigContent = append(additionalConfigContent, addContent)
  1381  			}
  1382  			config.AdditionalUnattendContent = &additionalConfigContent
  1383  		}
  1384  	}
  1385  	return config, nil
  1386  }
  1387  
  1388  func expandAzureRmVirtualMachineScaleSetOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup {
  1389  	secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List()
  1390  	secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig))
  1391  
  1392  	for _, secretConfig := range secretsConfig {
  1393  		config := secretConfig.(map[string]interface{})
  1394  		sourceVaultId := config["source_vault_id"].(string)
  1395  
  1396  		vaultSecretGroup := compute.VaultSecretGroup{
  1397  			SourceVault: &compute.SubResource{
  1398  				ID: &sourceVaultId,
  1399  			},
  1400  		}
  1401  
  1402  		if v := config["vault_certificates"]; v != nil {
  1403  			certsConfig := v.([]interface{})
  1404  			certs := make([]compute.VaultCertificate, 0, len(certsConfig))
  1405  			for _, certConfig := range certsConfig {
  1406  				config := certConfig.(map[string]interface{})
  1407  
  1408  				certUrl := config["certificate_url"].(string)
  1409  				cert := compute.VaultCertificate{
  1410  					CertificateURL: &certUrl,
  1411  				}
  1412  				if v := config["certificate_store"].(string); v != "" {
  1413  					cert.CertificateStore = &v
  1414  				}
  1415  
  1416  				certs = append(certs, cert)
  1417  			}
  1418  			vaultSecretGroup.VaultCertificates = &certs
  1419  		}
  1420  
  1421  		secrets = append(secrets, vaultSecretGroup)
  1422  	}
  1423  
  1424  	return &secrets
  1425  }
  1426  
  1427  func expandAzureRMVirtualMachineScaleSetExtensions(d *schema.ResourceData) (*compute.VirtualMachineScaleSetExtensionProfile, error) {
  1428  	extensions := d.Get("extension").(*schema.Set).List()
  1429  	resources := make([]compute.VirtualMachineScaleSetExtension, 0, len(extensions))
  1430  	for _, e := range extensions {
  1431  		config := e.(map[string]interface{})
  1432  		name := config["name"].(string)
  1433  		publisher := config["publisher"].(string)
  1434  		t := config["type"].(string)
  1435  		version := config["type_handler_version"].(string)
  1436  
  1437  		extension := compute.VirtualMachineScaleSetExtension{
  1438  			Name: &name,
  1439  			VirtualMachineScaleSetExtensionProperties: &compute.VirtualMachineScaleSetExtensionProperties{
  1440  				Publisher:          &publisher,
  1441  				Type:               &t,
  1442  				TypeHandlerVersion: &version,
  1443  			},
  1444  		}
  1445  
  1446  		if u := config["auto_upgrade_minor_version"]; u != nil {
  1447  			upgrade := u.(bool)
  1448  			extension.VirtualMachineScaleSetExtensionProperties.AutoUpgradeMinorVersion = &upgrade
  1449  		}
  1450  
  1451  		if s := config["settings"].(string); s != "" {
  1452  			settings, err := structure.ExpandJsonFromString(s)
  1453  			if err != nil {
  1454  				return nil, fmt.Errorf("unable to parse settings: %s", err)
  1455  			}
  1456  			extension.VirtualMachineScaleSetExtensionProperties.Settings = &settings
  1457  		}
  1458  
  1459  		if s := config["protected_settings"].(string); s != "" {
  1460  			protectedSettings, err := structure.ExpandJsonFromString(s)
  1461  			if err != nil {
  1462  				return nil, fmt.Errorf("unable to parse protected_settings: %s", err)
  1463  			}
  1464  			extension.VirtualMachineScaleSetExtensionProperties.ProtectedSettings = &protectedSettings
  1465  		}
  1466  
  1467  		resources = append(resources, extension)
  1468  	}
  1469  
  1470  	return &compute.VirtualMachineScaleSetExtensionProfile{
  1471  		Extensions: &resources,
  1472  	}, nil
  1473  }