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