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