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