github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go (about)

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