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