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