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