github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/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 489 if err != nil { 490 return fmt.Errorf("Error making Read request on Azure Virtual Machine %s: %s", name, err) 491 } 492 if resp.StatusCode == http.StatusNotFound { 493 d.SetId("") 494 return nil 495 } 496 497 if resp.Plan != nil { 498 if err := d.Set("plan", flattenAzureRmVirtualMachinePlan(resp.Plan)); err != nil { 499 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Plan error: %#v", err) 500 } 501 } 502 503 if resp.Properties.AvailabilitySet != nil { 504 d.Set("availability_set_id", strings.ToLower(*resp.Properties.AvailabilitySet.ID)) 505 } 506 507 d.Set("vm_size", resp.Properties.HardwareProfile.VMSize) 508 509 if resp.Properties.StorageProfile.ImageReference != nil { 510 if err := d.Set("storage_image_reference", schema.NewSet(resourceArmVirtualMachineStorageImageReferenceHash, flattenAzureRmVirtualMachineImageReference(resp.Properties.StorageProfile.ImageReference))); err != nil { 511 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Image Reference error: %#v", err) 512 } 513 } 514 515 if err := d.Set("storage_os_disk", schema.NewSet(resourceArmVirtualMachineStorageOsDiskHash, flattenAzureRmVirtualMachineOsDisk(resp.Properties.StorageProfile.OsDisk))); err != nil { 516 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Disk error: %#v", err) 517 } 518 519 if resp.Properties.StorageProfile.DataDisks != nil { 520 if err := d.Set("storage_data_disk", flattenAzureRmVirtualMachineDataDisk(resp.Properties.StorageProfile.DataDisks)); err != nil { 521 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Data Disks error: %#v", err) 522 } 523 } 524 525 if err := d.Set("os_profile", schema.NewSet(resourceArmVirtualMachineStorageOsProfileHash, flattenAzureRmVirtualMachineOsProfile(resp.Properties.OsProfile))); err != nil { 526 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile: %#v", err) 527 } 528 529 if resp.Properties.OsProfile.WindowsConfiguration != nil { 530 if err := d.Set("os_profile_windows_config", flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(resp.Properties.OsProfile.WindowsConfiguration)); err != nil { 531 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Windows Configuration: %#v", err) 532 } 533 } 534 535 if resp.Properties.OsProfile.LinuxConfiguration != nil { 536 if err := d.Set("os_profile_linux_config", flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(resp.Properties.OsProfile.LinuxConfiguration)); err != nil { 537 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Linux Configuration: %#v", err) 538 } 539 } 540 541 if resp.Properties.OsProfile.Secrets != nil { 542 if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineOsProfileSecrets(resp.Properties.OsProfile.Secrets)); err != nil { 543 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Secrets: %#v", err) 544 } 545 } 546 547 if resp.Properties.NetworkProfile != nil { 548 if err := d.Set("network_interface_ids", flattenAzureRmVirtualMachineNetworkInterfaces(resp.Properties.NetworkProfile)); err != nil { 549 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Network Interfaces: %#v", err) 550 } 551 } 552 553 flattenAndSetTags(d, resp.Tags) 554 555 return nil 556 } 557 558 func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error { 559 vmClient := meta.(*ArmClient).vmClient 560 561 id, err := parseAzureResourceID(d.Id()) 562 if err != nil { 563 return err 564 } 565 resGroup := id.ResourceGroup 566 name := id.Path["virtualMachines"] 567 568 if _, err = vmClient.Delete(resGroup, name, make(chan struct{})); err != nil { 569 return err 570 } 571 572 // delete OS Disk if opted in 573 if deleteOsDisk := d.Get("delete_os_disk_on_termination").(bool); deleteOsDisk { 574 log.Printf("[INFO] delete_os_disk_on_termination is enabled, deleting") 575 576 osDisk, err := expandAzureRmVirtualMachineOsDisk(d) 577 if err != nil { 578 return fmt.Errorf("Error expanding OS Disk: %s", err) 579 } 580 581 if err = resourceArmVirtualMachineDeleteVhd(*osDisk.Vhd.URI, resGroup, meta); err != nil { 582 return fmt.Errorf("Error deleting OS Disk VHD: %s", err) 583 } 584 } 585 586 // delete Data disks if opted in 587 if deleteDataDisks := d.Get("delete_data_disks_on_termination").(bool); deleteDataDisks { 588 log.Printf("[INFO] delete_data_disks_on_termination is enabled, deleting each data disk") 589 590 disks, err := expandAzureRmVirtualMachineDataDisk(d) 591 if err != nil { 592 return fmt.Errorf("Error expanding Data Disks: %s", err) 593 } 594 595 for _, disk := range disks { 596 if err = resourceArmVirtualMachineDeleteVhd(*disk.Vhd.URI, resGroup, meta); err != nil { 597 return fmt.Errorf("Error deleting Data Disk VHD: %s", err) 598 } 599 } 600 } 601 602 return nil 603 } 604 605 func resourceArmVirtualMachineDeleteVhd(uri, resGroup string, meta interface{}) error { 606 vhdURL, err := url.Parse(uri) 607 if err != nil { 608 return fmt.Errorf("Cannot parse Disk VHD URI: %s", err) 609 } 610 611 // VHD URI is in the form: https://storageAccountName.blob.core.windows.net/containerName/blobName 612 storageAccountName := strings.Split(vhdURL.Host, ".")[0] 613 path := strings.Split(strings.TrimPrefix(vhdURL.Path, "/"), "/") 614 containerName := path[0] 615 blobName := path[1] 616 617 blobClient, saExists, err := meta.(*ArmClient).getBlobStorageClientForStorageAccount(resGroup, storageAccountName) 618 if err != nil { 619 return fmt.Errorf("Error creating blob store client for VHD deletion: %s", err) 620 } 621 622 if !saExists { 623 log.Printf("[INFO] Storage Account %q doesn't exist so the VHD blob won't exist", storageAccountName) 624 return nil 625 } 626 627 log.Printf("[INFO] Deleting VHD blob %s", blobName) 628 _, err = blobClient.DeleteBlobIfExists(containerName, blobName, nil) 629 if err != nil { 630 return fmt.Errorf("Error deleting VHD blob: %s", err) 631 } 632 633 return nil 634 } 635 636 func resourceArmVirtualMachinePlanHash(v interface{}) int { 637 var buf bytes.Buffer 638 m := v.(map[string]interface{}) 639 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 640 buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string))) 641 buf.WriteString(fmt.Sprintf("%s-", m["product"].(string))) 642 643 return hashcode.String(buf.String()) 644 } 645 646 func resourceArmVirtualMachineStorageImageReferenceHash(v interface{}) int { 647 var buf bytes.Buffer 648 m := v.(map[string]interface{}) 649 buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string))) 650 buf.WriteString(fmt.Sprintf("%s-", m["offer"].(string))) 651 buf.WriteString(fmt.Sprintf("%s-", m["sku"].(string))) 652 653 return hashcode.String(buf.String()) 654 } 655 656 func resourceArmVirtualMachineStorageOsProfileHash(v interface{}) int { 657 var buf bytes.Buffer 658 m := v.(map[string]interface{}) 659 buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string))) 660 buf.WriteString(fmt.Sprintf("%s-", m["computer_name"].(string))) 661 return hashcode.String(buf.String()) 662 } 663 664 func resourceArmVirtualMachineStorageOsDiskHash(v interface{}) int { 665 var buf bytes.Buffer 666 m := v.(map[string]interface{}) 667 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 668 buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string))) 669 670 return hashcode.String(buf.String()) 671 } 672 673 func resourceArmVirtualMachineStorageOsProfileLinuxConfigHash(v interface{}) int { 674 var buf bytes.Buffer 675 m := v.(map[string]interface{}) 676 buf.WriteString(fmt.Sprintf("%t-", m["disable_password_authentication"].(bool))) 677 678 return hashcode.String(buf.String()) 679 } 680 681 func resourceArmVirtualMachineStorageOsProfileWindowsConfigHash(v interface{}) int { 682 var buf bytes.Buffer 683 m := v.(map[string]interface{}) 684 if m["provision_vm_agent"] != nil { 685 buf.WriteString(fmt.Sprintf("%t-", m["provision_vm_agent"].(bool))) 686 } 687 if m["enable_automatic_upgrades"] != nil { 688 buf.WriteString(fmt.Sprintf("%t-", m["enable_automatic_upgrades"].(bool))) 689 } 690 return hashcode.String(buf.String()) 691 } 692 693 func flattenAzureRmVirtualMachinePlan(plan *compute.Plan) map[string]interface{} { 694 result := make(map[string]interface{}) 695 result["name"] = *plan.Name 696 result["publisher"] = *plan.Publisher 697 result["product"] = *plan.Product 698 699 return result 700 } 701 702 func flattenAzureRmVirtualMachineImageReference(image *compute.ImageReference) []interface{} { 703 result := make(map[string]interface{}) 704 result["offer"] = *image.Offer 705 result["publisher"] = *image.Publisher 706 result["sku"] = *image.Sku 707 708 if image.Version != nil { 709 result["version"] = *image.Version 710 } 711 712 return []interface{}{result} 713 } 714 715 func flattenAzureRmVirtualMachineNetworkInterfaces(profile *compute.NetworkProfile) []string { 716 result := make([]string, 0, len(*profile.NetworkInterfaces)) 717 for _, nic := range *profile.NetworkInterfaces { 718 result = append(result, *nic.ID) 719 } 720 return result 721 } 722 723 func flattenAzureRmVirtualMachineOsProfileSecrets(secrets *[]compute.VaultSecretGroup) []map[string]interface{} { 724 result := make([]map[string]interface{}, 0, len(*secrets)) 725 for _, secret := range *secrets { 726 s := map[string]interface{}{ 727 "source_vault_id": *secret.SourceVault.ID, 728 } 729 730 if secret.VaultCertificates != nil { 731 certs := make([]map[string]interface{}, 0, len(*secret.VaultCertificates)) 732 for _, cert := range *secret.VaultCertificates { 733 vaultCert := make(map[string]interface{}) 734 vaultCert["certificate_url"] = *cert.CertificateURL 735 736 if cert.CertificateStore != nil { 737 vaultCert["certificate_store"] = *cert.CertificateStore 738 } 739 740 certs = append(certs, vaultCert) 741 } 742 743 s["vault_certificates"] = certs 744 } 745 746 result = append(result, s) 747 } 748 return result 749 } 750 751 func flattenAzureRmVirtualMachineDataDisk(disks *[]compute.DataDisk) interface{} { 752 result := make([]interface{}, len(*disks)) 753 for i, disk := range *disks { 754 l := make(map[string]interface{}) 755 l["name"] = *disk.Name 756 l["vhd_uri"] = *disk.Vhd.URI 757 l["create_option"] = disk.CreateOption 758 l["disk_size_gb"] = *disk.DiskSizeGB 759 l["lun"] = *disk.Lun 760 761 result[i] = l 762 } 763 return result 764 } 765 766 func flattenAzureRmVirtualMachineOsProfile(osProfile *compute.OSProfile) []interface{} { 767 result := make(map[string]interface{}) 768 result["computer_name"] = *osProfile.ComputerName 769 result["admin_username"] = *osProfile.AdminUsername 770 if osProfile.CustomData != nil { 771 result["custom_data"] = *osProfile.CustomData 772 } 773 774 return []interface{}{result} 775 } 776 777 func flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(config *compute.WindowsConfiguration) []interface{} { 778 result := make(map[string]interface{}) 779 780 if config.ProvisionVMAgent != nil { 781 result["provision_vm_agent"] = *config.ProvisionVMAgent 782 } 783 784 if config.EnableAutomaticUpdates != nil { 785 result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates 786 } 787 788 if config.WinRM != nil { 789 listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners)) 790 for _, i := range *config.WinRM.Listeners { 791 listener := make(map[string]interface{}) 792 listener["protocol"] = i.Protocol 793 794 if i.CertificateURL != nil { 795 listener["certificate_url"] = *i.CertificateURL 796 } 797 798 listeners = append(listeners, listener) 799 } 800 801 result["winrm"] = listeners 802 } 803 804 if config.AdditionalUnattendContent != nil { 805 content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent)) 806 for _, i := range *config.AdditionalUnattendContent { 807 c := make(map[string]interface{}) 808 c["pass"] = i.PassName 809 c["component"] = i.ComponentName 810 c["setting_name"] = i.SettingName 811 812 if i.Content != nil { 813 c["content"] = *i.Content 814 } 815 816 content = append(content, c) 817 } 818 819 result["additional_unattend_config"] = content 820 } 821 822 return []interface{}{result} 823 } 824 825 func flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(config *compute.LinuxConfiguration) []interface{} { 826 827 result := make(map[string]interface{}) 828 result["disable_password_authentication"] = *config.DisablePasswordAuthentication 829 830 if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 { 831 ssh_keys := make([]map[string]interface{}, len(*config.SSH.PublicKeys)) 832 for _, i := range *config.SSH.PublicKeys { 833 key := make(map[string]interface{}) 834 key["path"] = *i.Path 835 836 if i.KeyData != nil { 837 key["key_data"] = *i.KeyData 838 } 839 840 ssh_keys = append(ssh_keys, key) 841 } 842 843 result["ssh_keys"] = ssh_keys 844 } 845 846 return []interface{}{result} 847 } 848 849 func flattenAzureRmVirtualMachineOsDisk(disk *compute.OSDisk) []interface{} { 850 result := make(map[string]interface{}) 851 result["name"] = *disk.Name 852 result["vhd_uri"] = *disk.Vhd.URI 853 result["create_option"] = disk.CreateOption 854 result["caching"] = disk.Caching 855 856 return []interface{}{result} 857 } 858 859 func expandAzureRmVirtualMachinePlan(d *schema.ResourceData) (*compute.Plan, error) { 860 planConfigs := d.Get("plan").(*schema.Set).List() 861 862 planConfig := planConfigs[0].(map[string]interface{}) 863 864 publisher := planConfig["publisher"].(string) 865 name := planConfig["name"].(string) 866 product := planConfig["product"].(string) 867 868 return &compute.Plan{ 869 Publisher: &publisher, 870 Name: &name, 871 Product: &product, 872 }, nil 873 } 874 875 func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSProfile, error) { 876 osProfiles := d.Get("os_profile").(*schema.Set).List() 877 878 osProfile := osProfiles[0].(map[string]interface{}) 879 880 adminUsername := osProfile["admin_username"].(string) 881 adminPassword := osProfile["admin_password"].(string) 882 computerName := osProfile["computer_name"].(string) 883 884 profile := &compute.OSProfile{ 885 AdminUsername: &adminUsername, 886 ComputerName: &computerName, 887 } 888 889 if adminPassword != "" { 890 profile.AdminPassword = &adminPassword 891 } 892 893 if _, ok := d.GetOk("os_profile_windows_config"); ok { 894 winConfig, err := expandAzureRmVirtualMachineOsProfileWindowsConfig(d) 895 if err != nil { 896 return nil, err 897 } 898 if winConfig != nil { 899 profile.WindowsConfiguration = winConfig 900 } 901 } 902 903 if _, ok := d.GetOk("os_profile_linux_config"); ok { 904 linuxConfig, err := expandAzureRmVirtualMachineOsProfileLinuxConfig(d) 905 if err != nil { 906 return nil, err 907 } 908 if linuxConfig != nil { 909 profile.LinuxConfiguration = linuxConfig 910 } 911 } 912 913 if _, ok := d.GetOk("os_profile_secrets"); ok { 914 secrets := expandAzureRmVirtualMachineOsProfileSecrets(d) 915 if secrets != nil { 916 profile.Secrets = secrets 917 } 918 } 919 920 if v := osProfile["custom_data"].(string); v != "" { 921 profile.CustomData = &v 922 } 923 924 return profile, nil 925 } 926 927 func expandAzureRmVirtualMachineOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup { 928 secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List() 929 secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig)) 930 931 for _, secretConfig := range secretsConfig { 932 config := secretConfig.(map[string]interface{}) 933 sourceVaultId := config["source_vault_id"].(string) 934 935 vaultSecretGroup := compute.VaultSecretGroup{ 936 SourceVault: &compute.SubResource{ 937 ID: &sourceVaultId, 938 }, 939 } 940 941 if v := config["vault_certificates"]; v != nil { 942 certsConfig := v.([]interface{}) 943 certs := make([]compute.VaultCertificate, 0, len(certsConfig)) 944 for _, certConfig := range certsConfig { 945 config := certConfig.(map[string]interface{}) 946 947 certUrl := config["certificate_url"].(string) 948 cert := compute.VaultCertificate{ 949 CertificateURL: &certUrl, 950 } 951 if v := config["certificate_store"].(string); v != "" { 952 cert.CertificateStore = &v 953 } 954 955 certs = append(certs, cert) 956 } 957 vaultSecretGroup.VaultCertificates = &certs 958 } 959 960 secrets = append(secrets, vaultSecretGroup) 961 } 962 963 return &secrets 964 } 965 966 func expandAzureRmVirtualMachineOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) { 967 osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List() 968 969 linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{}) 970 disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool) 971 972 config := &compute.LinuxConfiguration{ 973 DisablePasswordAuthentication: &disablePasswordAuth, 974 } 975 976 linuxKeys := linuxConfig["ssh_keys"].([]interface{}) 977 sshPublicKeys := []compute.SSHPublicKey{} 978 for _, key := range linuxKeys { 979 980 sshKey, ok := key.(map[string]interface{}) 981 if !ok { 982 continue 983 } 984 path := sshKey["path"].(string) 985 keyData := sshKey["key_data"].(string) 986 987 sshPublicKey := compute.SSHPublicKey{ 988 Path: &path, 989 KeyData: &keyData, 990 } 991 992 sshPublicKeys = append(sshPublicKeys, sshPublicKey) 993 } 994 995 config.SSH = &compute.SSHConfiguration{ 996 PublicKeys: &sshPublicKeys, 997 } 998 999 return config, nil 1000 } 1001 1002 func expandAzureRmVirtualMachineOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) { 1003 osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List() 1004 1005 osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{}) 1006 config := &compute.WindowsConfiguration{} 1007 1008 if v := osProfileConfig["provision_vm_agent"]; v != nil { 1009 provision := v.(bool) 1010 config.ProvisionVMAgent = &provision 1011 } 1012 1013 if v := osProfileConfig["enable_automatic_upgrades"]; v != nil { 1014 update := v.(bool) 1015 config.EnableAutomaticUpdates = &update 1016 } 1017 1018 if v := osProfileConfig["winrm"]; v != nil { 1019 winRm := v.([]interface{}) 1020 if len(winRm) > 0 { 1021 winRmListners := make([]compute.WinRMListener, 0, len(winRm)) 1022 for _, winRmConfig := range winRm { 1023 config := winRmConfig.(map[string]interface{}) 1024 1025 protocol := config["protocol"].(string) 1026 winRmListner := compute.WinRMListener{ 1027 Protocol: compute.ProtocolTypes(protocol), 1028 } 1029 if v := config["certificate_url"].(string); v != "" { 1030 winRmListner.CertificateURL = &v 1031 } 1032 1033 winRmListners = append(winRmListners, winRmListner) 1034 } 1035 config.WinRM = &compute.WinRMConfiguration{ 1036 Listeners: &winRmListners, 1037 } 1038 } 1039 } 1040 if v := osProfileConfig["additional_unattend_config"]; v != nil { 1041 additionalConfig := v.([]interface{}) 1042 if len(additionalConfig) > 0 { 1043 additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig)) 1044 for _, addConfig := range additionalConfig { 1045 config := addConfig.(map[string]interface{}) 1046 pass := config["pass"].(string) 1047 component := config["component"].(string) 1048 settingName := config["setting_name"].(string) 1049 content := config["content"].(string) 1050 1051 addContent := compute.AdditionalUnattendContent{ 1052 PassName: compute.PassNames(pass), 1053 ComponentName: compute.ComponentNames(component), 1054 SettingName: compute.SettingNames(settingName), 1055 Content: &content, 1056 } 1057 1058 additionalConfigContent = append(additionalConfigContent, addContent) 1059 } 1060 config.AdditionalUnattendContent = &additionalConfigContent 1061 } 1062 } 1063 return config, nil 1064 } 1065 1066 func expandAzureRmVirtualMachineDataDisk(d *schema.ResourceData) ([]compute.DataDisk, error) { 1067 disks := d.Get("storage_data_disk").([]interface{}) 1068 data_disks := make([]compute.DataDisk, 0, len(disks)) 1069 for _, disk_config := range disks { 1070 config := disk_config.(map[string]interface{}) 1071 1072 name := config["name"].(string) 1073 vhd := config["vhd_uri"].(string) 1074 createOption := config["create_option"].(string) 1075 lun := int32(config["lun"].(int)) 1076 disk_size := int32(config["disk_size_gb"].(int)) 1077 1078 data_disk := compute.DataDisk{ 1079 Name: &name, 1080 Vhd: &compute.VirtualHardDisk{ 1081 URI: &vhd, 1082 }, 1083 Lun: &lun, 1084 DiskSizeGB: &disk_size, 1085 CreateOption: compute.DiskCreateOptionTypes(createOption), 1086 } 1087 1088 data_disks = append(data_disks, data_disk) 1089 } 1090 1091 return data_disks, nil 1092 } 1093 1094 func expandAzureRmVirtualMachineImageReference(d *schema.ResourceData) (*compute.ImageReference, error) { 1095 storageImageRefs := d.Get("storage_image_reference").(*schema.Set).List() 1096 1097 storageImageRef := storageImageRefs[0].(map[string]interface{}) 1098 1099 publisher := storageImageRef["publisher"].(string) 1100 offer := storageImageRef["offer"].(string) 1101 sku := storageImageRef["sku"].(string) 1102 version := storageImageRef["version"].(string) 1103 1104 return &compute.ImageReference{ 1105 Publisher: &publisher, 1106 Offer: &offer, 1107 Sku: &sku, 1108 Version: &version, 1109 }, nil 1110 } 1111 1112 func expandAzureRmVirtualMachineNetworkProfile(d *schema.ResourceData) compute.NetworkProfile { 1113 nicIds := d.Get("network_interface_ids").(*schema.Set).List() 1114 network_interfaces := make([]compute.NetworkInterfaceReference, 0, len(nicIds)) 1115 1116 network_profile := compute.NetworkProfile{} 1117 1118 for _, nic := range nicIds { 1119 id := nic.(string) 1120 network_interface := compute.NetworkInterfaceReference{ 1121 ID: &id, 1122 } 1123 network_interfaces = append(network_interfaces, network_interface) 1124 } 1125 1126 network_profile.NetworkInterfaces = &network_interfaces 1127 1128 return network_profile 1129 } 1130 1131 func expandAzureRmVirtualMachineOsDisk(d *schema.ResourceData) (*compute.OSDisk, error) { 1132 disks := d.Get("storage_os_disk").(*schema.Set).List() 1133 1134 disk := disks[0].(map[string]interface{}) 1135 1136 name := disk["name"].(string) 1137 vhdURI := disk["vhd_uri"].(string) 1138 imageURI := disk["image_uri"].(string) 1139 createOption := disk["create_option"].(string) 1140 1141 osDisk := &compute.OSDisk{ 1142 Name: &name, 1143 Vhd: &compute.VirtualHardDisk{ 1144 URI: &vhdURI, 1145 }, 1146 CreateOption: compute.DiskCreateOptionTypes(createOption), 1147 } 1148 1149 if v := disk["image_uri"].(string); v != "" { 1150 osDisk.Image = &compute.VirtualHardDisk{ 1151 URI: &imageURI, 1152 } 1153 } 1154 1155 if v := disk["os_type"].(string); v != "" { 1156 if v == "linux" { 1157 osDisk.OsType = compute.Linux 1158 } else if v == "windows" { 1159 osDisk.OsType = compute.Windows 1160 } else { 1161 return nil, fmt.Errorf("[ERROR] os_type must be 'linux' or 'windows'") 1162 } 1163 } 1164 1165 if v := disk["caching"].(string); v != "" { 1166 osDisk.Caching = compute.CachingTypes(v) 1167 } 1168 1169 return osDisk, nil 1170 }