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