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