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