github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/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/Azure/azure-sdk-for-go/storage" 13 "github.com/hashicorp/terraform/helper/hashcode" 14 "github.com/hashicorp/terraform/helper/schema" 15 "github.com/hashicorp/terraform/helper/validation" 16 riviera "github.com/jen20/riviera/azure" 17 ) 18 19 func resourceArmVirtualMachine() *schema.Resource { 20 return &schema.Resource{ 21 Create: resourceArmVirtualMachineCreate, 22 Read: resourceArmVirtualMachineRead, 23 Update: resourceArmVirtualMachineCreate, 24 Delete: resourceArmVirtualMachineDelete, 25 Importer: &schema.ResourceImporter{ 26 State: schema.ImportStatePassthrough, 27 }, 28 29 Schema: map[string]*schema.Schema{ 30 "name": { 31 Type: schema.TypeString, 32 Required: true, 33 ForceNew: true, 34 }, 35 36 "location": locationSchema(), 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 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 ValidateFunc: validateLicenseType, 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 ForceNew: true, 96 MaxItems: 1, 97 Elem: &schema.Resource{ 98 Schema: map[string]*schema.Schema{ 99 "publisher": { 100 Type: schema.TypeString, 101 Required: true, 102 ForceNew: true, 103 }, 104 105 "offer": { 106 Type: schema.TypeString, 107 Required: true, 108 ForceNew: true, 109 }, 110 111 "sku": { 112 Type: schema.TypeString, 113 Required: true, 114 ForceNew: true, 115 }, 116 117 "version": { 118 Type: schema.TypeString, 119 Optional: true, 120 Computed: true, 121 ForceNew: true, 122 }, 123 }, 124 }, 125 Set: resourceArmVirtualMachineStorageImageReferenceHash, 126 }, 127 128 "storage_os_disk": { 129 Type: schema.TypeSet, 130 Required: true, 131 MaxItems: 1, 132 Elem: &schema.Resource{ 133 Schema: map[string]*schema.Schema{ 134 "os_type": { 135 Type: schema.TypeString, 136 Optional: true, 137 }, 138 139 "name": { 140 Type: schema.TypeString, 141 Required: true, 142 }, 143 144 "vhd_uri": { 145 Type: schema.TypeString, 146 Optional: true, 147 ForceNew: true, 148 }, 149 150 "managed_disk_id": { 151 Type: schema.TypeString, 152 Optional: true, 153 ForceNew: true, 154 Computed: true, 155 ConflictsWith: []string{"storage_os_disk.vhd_uri"}, 156 }, 157 158 "managed_disk_type": { 159 Type: schema.TypeString, 160 Optional: true, 161 Computed: true, 162 ConflictsWith: []string{"storage_os_disk.vhd_uri"}, 163 ValidateFunc: validation.StringInSlice([]string{ 164 string(compute.PremiumLRS), 165 string(compute.StandardLRS), 166 }, true), 167 }, 168 169 "image_uri": { 170 Type: schema.TypeString, 171 Optional: true, 172 }, 173 174 "caching": { 175 Type: schema.TypeString, 176 Optional: true, 177 Computed: true, 178 }, 179 180 "create_option": { 181 Type: schema.TypeString, 182 Required: true, 183 DiffSuppressFunc: ignoreCaseDiffSuppressFunc, 184 }, 185 186 "disk_size_gb": { 187 Type: schema.TypeInt, 188 Optional: true, 189 ValidateFunc: validateDiskSizeGB, 190 }, 191 }, 192 }, 193 Set: resourceArmVirtualMachineStorageOsDiskHash, 194 }, 195 196 "delete_os_disk_on_termination": { 197 Type: schema.TypeBool, 198 Optional: true, 199 Default: false, 200 }, 201 202 "storage_data_disk": { 203 Type: schema.TypeList, 204 Optional: true, 205 Elem: &schema.Resource{ 206 Schema: map[string]*schema.Schema{ 207 "name": { 208 Type: schema.TypeString, 209 Required: true, 210 }, 211 212 "vhd_uri": { 213 Type: schema.TypeString, 214 Optional: true, 215 }, 216 217 "managed_disk_id": { 218 Type: schema.TypeString, 219 Optional: true, 220 ForceNew: true, 221 Computed: true, 222 ConflictsWith: []string{"storage_data_disk.vhd_uri"}, 223 }, 224 225 "managed_disk_type": { 226 Type: schema.TypeString, 227 Optional: true, 228 Computed: true, 229 ConflictsWith: []string{"storage_data_disk.vhd_uri"}, 230 ValidateFunc: validation.StringInSlice([]string{ 231 string(compute.PremiumLRS), 232 string(compute.StandardLRS), 233 }, true), 234 }, 235 236 "create_option": { 237 Type: schema.TypeString, 238 Required: true, 239 DiffSuppressFunc: ignoreCaseDiffSuppressFunc, 240 }, 241 242 "caching": { 243 Type: schema.TypeString, 244 Optional: true, 245 Computed: true, 246 }, 247 248 "disk_size_gb": { 249 Type: schema.TypeInt, 250 Optional: true, 251 Computed: true, 252 ValidateFunc: validateDiskSizeGB, 253 }, 254 255 "lun": { 256 Type: schema.TypeInt, 257 Required: true, 258 }, 259 }, 260 }, 261 }, 262 263 "delete_data_disks_on_termination": { 264 Type: schema.TypeBool, 265 Optional: true, 266 Default: false, 267 }, 268 269 "diagnostics_profile": { 270 Type: schema.TypeSet, 271 Optional: true, 272 MaxItems: 1, 273 ConflictsWith: []string{"boot_diagnostics"}, 274 Deprecated: "Use field boot_diagnostics instead", 275 Elem: &schema.Resource{ 276 Schema: map[string]*schema.Schema{ 277 "boot_diagnostics": { 278 Type: schema.TypeSet, 279 Required: true, 280 MaxItems: 1, 281 Elem: &schema.Resource{ 282 Schema: map[string]*schema.Schema{ 283 "enabled": { 284 Type: schema.TypeBool, 285 Required: true, 286 }, 287 288 "storage_uri": { 289 Type: schema.TypeString, 290 Required: true, 291 }, 292 }, 293 }, 294 }, 295 }, 296 }, 297 }, 298 299 "boot_diagnostics": { 300 Type: schema.TypeList, 301 Optional: true, 302 MaxItems: 1, 303 Elem: &schema.Resource{ 304 Schema: map[string]*schema.Schema{ 305 "enabled": { 306 Type: schema.TypeBool, 307 Required: true, 308 }, 309 310 "storage_uri": { 311 Type: schema.TypeString, 312 Required: true, 313 }, 314 }, 315 }, 316 }, 317 318 "os_profile": { 319 Type: schema.TypeSet, 320 Optional: true, 321 MaxItems: 1, 322 Elem: &schema.Resource{ 323 Schema: map[string]*schema.Schema{ 324 "computer_name": { 325 Type: schema.TypeString, 326 ForceNew: true, 327 Required: true, 328 }, 329 330 "admin_username": { 331 Type: schema.TypeString, 332 Required: true, 333 }, 334 335 "admin_password": { 336 Type: schema.TypeString, 337 Required: true, 338 }, 339 340 "custom_data": { 341 Type: schema.TypeString, 342 Optional: true, 343 Computed: true, 344 StateFunc: userDataStateFunc, 345 }, 346 }, 347 }, 348 Set: resourceArmVirtualMachineStorageOsProfileHash, 349 }, 350 351 "os_profile_windows_config": { 352 Type: schema.TypeSet, 353 Optional: true, 354 MaxItems: 1, 355 Elem: &schema.Resource{ 356 Schema: map[string]*schema.Schema{ 357 "provision_vm_agent": { 358 Type: schema.TypeBool, 359 Optional: true, 360 }, 361 "enable_automatic_upgrades": { 362 Type: schema.TypeBool, 363 Optional: true, 364 }, 365 "winrm": { 366 Type: schema.TypeList, 367 Optional: true, 368 Elem: &schema.Resource{ 369 Schema: map[string]*schema.Schema{ 370 "protocol": { 371 Type: schema.TypeString, 372 Required: true, 373 }, 374 "certificate_url": { 375 Type: schema.TypeString, 376 Optional: true, 377 }, 378 }, 379 }, 380 }, 381 "additional_unattend_config": { 382 Type: schema.TypeList, 383 Optional: true, 384 Elem: &schema.Resource{ 385 Schema: map[string]*schema.Schema{ 386 "pass": { 387 Type: schema.TypeString, 388 Required: true, 389 }, 390 "component": { 391 Type: schema.TypeString, 392 Required: true, 393 }, 394 "setting_name": { 395 Type: schema.TypeString, 396 Required: true, 397 }, 398 "content": { 399 Type: schema.TypeString, 400 Required: true, 401 }, 402 }, 403 }, 404 }, 405 }, 406 }, 407 Set: resourceArmVirtualMachineStorageOsProfileWindowsConfigHash, 408 }, 409 410 "os_profile_linux_config": { 411 Type: schema.TypeSet, 412 Optional: true, 413 MaxItems: 1, 414 Elem: &schema.Resource{ 415 Schema: map[string]*schema.Schema{ 416 "disable_password_authentication": { 417 Type: schema.TypeBool, 418 Required: true, 419 }, 420 "ssh_keys": { 421 Type: schema.TypeList, 422 Optional: true, 423 Elem: &schema.Resource{ 424 Schema: map[string]*schema.Schema{ 425 "path": { 426 Type: schema.TypeString, 427 Required: true, 428 }, 429 "key_data": { 430 Type: schema.TypeString, 431 Optional: true, 432 }, 433 }, 434 }, 435 }, 436 }, 437 }, 438 Set: resourceArmVirtualMachineStorageOsProfileLinuxConfigHash, 439 }, 440 441 "os_profile_secrets": { 442 Type: schema.TypeSet, 443 Optional: true, 444 Elem: &schema.Resource{ 445 Schema: map[string]*schema.Schema{ 446 "source_vault_id": { 447 Type: schema.TypeString, 448 Required: true, 449 }, 450 451 "vault_certificates": { 452 Type: schema.TypeList, 453 Optional: true, 454 Elem: &schema.Resource{ 455 Schema: map[string]*schema.Schema{ 456 "certificate_url": { 457 Type: schema.TypeString, 458 Required: true, 459 }, 460 "certificate_store": { 461 Type: schema.TypeString, 462 Optional: true, 463 }, 464 }, 465 }, 466 }, 467 }, 468 }, 469 }, 470 471 "network_interface_ids": { 472 Type: schema.TypeSet, 473 Required: true, 474 Elem: &schema.Schema{ 475 Type: schema.TypeString, 476 }, 477 Set: schema.HashString, 478 }, 479 480 "primary_network_interface_id": { 481 Type: schema.TypeString, 482 Optional: true, 483 }, 484 485 "tags": tagsSchema(), 486 }, 487 } 488 } 489 490 func validateLicenseType(v interface{}, k string) (ws []string, errors []error) { 491 value := v.(string) 492 if value != "" && value != "Windows_Server" { 493 errors = append(errors, fmt.Errorf( 494 "[ERROR] license_type must be 'Windows_Server' or empty")) 495 } 496 return 497 } 498 499 func resourceArmVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error { 500 client := meta.(*ArmClient) 501 vmClient := client.vmClient 502 503 log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine creation.") 504 505 name := d.Get("name").(string) 506 location := d.Get("location").(string) 507 resGroup := d.Get("resource_group_name").(string) 508 tags := d.Get("tags").(map[string]interface{}) 509 expandedTags := expandTags(tags) 510 511 osDisk, err := expandAzureRmVirtualMachineOsDisk(d) 512 if err != nil { 513 return err 514 } 515 storageProfile := compute.StorageProfile{ 516 OsDisk: osDisk, 517 } 518 519 if _, ok := d.GetOk("storage_image_reference"); ok { 520 imageRef, err := expandAzureRmVirtualMachineImageReference(d) 521 if err != nil { 522 return err 523 } 524 storageProfile.ImageReference = imageRef 525 } 526 527 if _, ok := d.GetOk("storage_data_disk"); ok { 528 dataDisks, err := expandAzureRmVirtualMachineDataDisk(d) 529 if err != nil { 530 return err 531 } 532 storageProfile.DataDisks = &dataDisks 533 } 534 535 networkProfile := expandAzureRmVirtualMachineNetworkProfile(d) 536 vmSize := d.Get("vm_size").(string) 537 properties := compute.VirtualMachineProperties{ 538 NetworkProfile: &networkProfile, 539 HardwareProfile: &compute.HardwareProfile{ 540 VMSize: compute.VirtualMachineSizeTypes(vmSize), 541 }, 542 StorageProfile: &storageProfile, 543 } 544 545 if v, ok := d.GetOk("license_type"); ok { 546 license := v.(string) 547 properties.LicenseType = &license 548 } 549 550 if _, ok := d.GetOk("boot_diagnostics"); ok { 551 diagnosticsProfile := expandAzureRmVirtualMachineDiagnosticsProfile(d) 552 if diagnosticsProfile != nil { 553 properties.DiagnosticsProfile = diagnosticsProfile 554 } 555 } 556 557 if _, ok := d.GetOk("os_profile"); ok { 558 osProfile, err := expandAzureRmVirtualMachineOsProfile(d) 559 if err != nil { 560 return err 561 } 562 properties.OsProfile = osProfile 563 } 564 565 if v, ok := d.GetOk("availability_set_id"); ok { 566 availabilitySet := v.(string) 567 availSet := compute.SubResource{ 568 ID: &availabilitySet, 569 } 570 571 properties.AvailabilitySet = &availSet 572 } 573 574 vm := compute.VirtualMachine{ 575 Name: &name, 576 Location: &location, 577 VirtualMachineProperties: &properties, 578 Tags: expandedTags, 579 } 580 581 if _, ok := d.GetOk("plan"); ok { 582 plan, err := expandAzureRmVirtualMachinePlan(d) 583 if err != nil { 584 return err 585 } 586 587 vm.Plan = plan 588 } 589 590 _, vmError := vmClient.CreateOrUpdate(resGroup, name, vm, make(chan struct{})) 591 vmErr := <-vmError 592 if vmErr != nil { 593 return vmErr 594 } 595 596 read, err := vmClient.Get(resGroup, name, "") 597 if err != nil { 598 return err 599 } 600 if read.ID == nil { 601 return fmt.Errorf("Cannot read Virtual Machine %s (resource group %s) ID", name, resGroup) 602 } 603 604 d.SetId(*read.ID) 605 606 return resourceArmVirtualMachineRead(d, meta) 607 } 608 609 func resourceArmVirtualMachineRead(d *schema.ResourceData, meta interface{}) error { 610 vmClient := meta.(*ArmClient).vmClient 611 612 id, err := parseAzureResourceID(d.Id()) 613 if err != nil { 614 return err 615 } 616 resGroup := id.ResourceGroup 617 name := id.Path["virtualMachines"] 618 619 resp, err := vmClient.Get(resGroup, name, "") 620 621 if err != nil { 622 if resp.StatusCode == http.StatusNotFound { 623 d.SetId("") 624 return nil 625 } 626 return fmt.Errorf("Error making Read request on Azure Virtual Machine %s: %s", name, err) 627 } 628 629 d.Set("name", resp.Name) 630 d.Set("resource_group_name", resGroup) 631 d.Set("location", resp.Location) 632 633 if resp.Plan != nil { 634 if err := d.Set("plan", schema.NewSet(resourceArmVirtualMachinePlanHash, flattenAzureRmVirtualMachinePlan(resp.Plan))); err != nil { 635 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Plan error: %#v", err) 636 } 637 } 638 639 if resp.VirtualMachineProperties.AvailabilitySet != nil { 640 d.Set("availability_set_id", strings.ToLower(*resp.VirtualMachineProperties.AvailabilitySet.ID)) 641 } 642 643 d.Set("vm_size", resp.VirtualMachineProperties.HardwareProfile.VMSize) 644 645 if resp.VirtualMachineProperties.StorageProfile.ImageReference != nil { 646 if err := d.Set("storage_image_reference", schema.NewSet(resourceArmVirtualMachineStorageImageReferenceHash, flattenAzureRmVirtualMachineImageReference(resp.VirtualMachineProperties.StorageProfile.ImageReference))); err != nil { 647 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Image Reference error: %#v", err) 648 } 649 } 650 651 if err := d.Set("storage_os_disk", schema.NewSet(resourceArmVirtualMachineStorageOsDiskHash, flattenAzureRmVirtualMachineOsDisk(resp.VirtualMachineProperties.StorageProfile.OsDisk))); err != nil { 652 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Disk error: %#v", err) 653 } 654 655 if resp.VirtualMachineProperties.StorageProfile.DataDisks != nil { 656 if err := d.Set("storage_data_disk", flattenAzureRmVirtualMachineDataDisk(resp.VirtualMachineProperties.StorageProfile.DataDisks)); err != nil { 657 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Data Disks error: %#v", err) 658 } 659 } 660 661 if resp.VirtualMachineProperties.OsProfile != nil { 662 if err := d.Set("os_profile", schema.NewSet(resourceArmVirtualMachineStorageOsProfileHash, flattenAzureRmVirtualMachineOsProfile(resp.VirtualMachineProperties.OsProfile))); err != nil { 663 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile: %#v", err) 664 } 665 666 if resp.VirtualMachineProperties.OsProfile.WindowsConfiguration != nil { 667 if err := d.Set("os_profile_windows_config", flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(resp.VirtualMachineProperties.OsProfile.WindowsConfiguration)); err != nil { 668 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Windows Configuration: %#v", err) 669 } 670 } 671 672 if resp.VirtualMachineProperties.OsProfile.LinuxConfiguration != nil { 673 if err := d.Set("os_profile_linux_config", flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(resp.VirtualMachineProperties.OsProfile.LinuxConfiguration)); err != nil { 674 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Linux Configuration: %#v", err) 675 } 676 } 677 678 if resp.VirtualMachineProperties.OsProfile.Secrets != nil { 679 if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineOsProfileSecrets(resp.VirtualMachineProperties.OsProfile.Secrets)); err != nil { 680 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Secrets: %#v", err) 681 } 682 } 683 } 684 685 if resp.VirtualMachineProperties.DiagnosticsProfile != nil && resp.VirtualMachineProperties.DiagnosticsProfile.BootDiagnostics != nil { 686 if err := d.Set("boot_diagnostics", flattenAzureRmVirtualMachineDiagnosticsProfile(resp.VirtualMachineProperties.DiagnosticsProfile.BootDiagnostics)); err != nil { 687 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Diagnostics Profile: %#v", err) 688 } 689 } 690 691 if resp.VirtualMachineProperties.NetworkProfile != nil { 692 if err := d.Set("network_interface_ids", flattenAzureRmVirtualMachineNetworkInterfaces(resp.VirtualMachineProperties.NetworkProfile)); err != nil { 693 return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Network Interfaces: %#v", err) 694 } 695 696 if resp.VirtualMachineProperties.NetworkProfile.NetworkInterfaces != nil { 697 for _, nic := range *resp.VirtualMachineProperties.NetworkProfile.NetworkInterfaces { 698 if nic.NetworkInterfaceReferenceProperties != nil && *nic.NetworkInterfaceReferenceProperties.Primary { 699 d.Set("primary_network_interface_id", nic.ID) 700 break 701 } 702 } 703 } 704 } 705 706 flattenAndSetTags(d, resp.Tags) 707 708 return nil 709 } 710 711 func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error { 712 vmClient := meta.(*ArmClient).vmClient 713 714 id, err := parseAzureResourceID(d.Id()) 715 if err != nil { 716 return err 717 } 718 resGroup := id.ResourceGroup 719 name := id.Path["virtualMachines"] 720 721 _, error := vmClient.Delete(resGroup, name, make(chan struct{})) 722 err = <-error 723 724 if err != nil { 725 return err 726 } 727 728 // delete OS Disk if opted in 729 if deleteOsDisk := d.Get("delete_os_disk_on_termination").(bool); deleteOsDisk { 730 log.Printf("[INFO] delete_os_disk_on_termination is enabled, deleting disk from %s", name) 731 732 osDisk, err := expandAzureRmVirtualMachineOsDisk(d) 733 if err != nil { 734 return fmt.Errorf("Error expanding OS Disk: %s", err) 735 } 736 737 if osDisk.Vhd != nil { 738 if err = resourceArmVirtualMachineDeleteVhd(*osDisk.Vhd.URI, meta); err != nil { 739 return fmt.Errorf("Error deleting OS Disk VHD: %s", err) 740 } 741 } else if osDisk.ManagedDisk != nil { 742 if err = resourceArmVirtualMachineDeleteManagedDisk(*osDisk.ManagedDisk.ID, meta); err != nil { 743 return fmt.Errorf("Error deleting OS Managed Disk: %s", err) 744 } 745 } else { 746 return fmt.Errorf("Unable to locate OS managed disk properties from %s", name) 747 } 748 } 749 750 // delete Data disks if opted in 751 if deleteDataDisks := d.Get("delete_data_disks_on_termination").(bool); deleteDataDisks { 752 log.Printf("[INFO] delete_data_disks_on_termination is enabled, deleting each data disk from %s", name) 753 754 disks, err := expandAzureRmVirtualMachineDataDisk(d) 755 if err != nil { 756 return fmt.Errorf("Error expanding Data Disks: %s", err) 757 } 758 759 for _, disk := range disks { 760 if disk.Vhd != nil { 761 if err = resourceArmVirtualMachineDeleteVhd(*disk.Vhd.URI, meta); err != nil { 762 return fmt.Errorf("Error deleting Data Disk VHD: %s", err) 763 } 764 } else if disk.ManagedDisk != nil { 765 if err = resourceArmVirtualMachineDeleteManagedDisk(*disk.ManagedDisk.ID, meta); err != nil { 766 return fmt.Errorf("Error deleting Data Managed Disk: %s", err) 767 } 768 } else { 769 return fmt.Errorf("Unable to locate data managed disk properties from %s", name) 770 } 771 } 772 } 773 774 return nil 775 } 776 777 func resourceArmVirtualMachineDeleteVhd(uri string, meta interface{}) error { 778 vhdURL, err := url.Parse(uri) 779 if err != nil { 780 return fmt.Errorf("Cannot parse Disk VHD URI: %s", err) 781 } 782 783 // VHD URI is in the form: https://storageAccountName.blob.core.windows.net/containerName/blobName 784 storageAccountName := strings.Split(vhdURL.Host, ".")[0] 785 path := strings.Split(strings.TrimPrefix(vhdURL.Path, "/"), "/") 786 containerName := path[0] 787 blobName := path[1] 788 789 storageAccountResourceGroupName, err := findStorageAccountResourceGroup(meta, storageAccountName) 790 if err != nil { 791 return fmt.Errorf("Error finding resource group for storage account %s: %s", storageAccountName, err) 792 } 793 794 blobClient, saExists, err := meta.(*ArmClient).getBlobStorageClientForStorageAccount(storageAccountResourceGroupName, storageAccountName) 795 if err != nil { 796 return fmt.Errorf("Error creating blob store client for VHD deletion: %s", err) 797 } 798 799 if !saExists { 800 log.Printf("[INFO] Storage Account %q in resource group %q doesn't exist so the VHD blob won't exist", storageAccountName, storageAccountResourceGroupName) 801 return nil 802 } 803 804 log.Printf("[INFO] Deleting VHD blob %s", blobName) 805 container := blobClient.GetContainerReference(containerName) 806 blob := container.GetBlobReference(blobName) 807 options := &storage.DeleteBlobOptions{} 808 err = blob.Delete(options) 809 if err != nil { 810 return fmt.Errorf("Error deleting VHD blob: %s", err) 811 } 812 813 return nil 814 } 815 816 func resourceArmVirtualMachineDeleteManagedDisk(managedDiskID string, meta interface{}) error { 817 diskClient := meta.(*ArmClient).diskClient 818 819 id, err := parseAzureResourceID(managedDiskID) 820 if err != nil { 821 return err 822 } 823 resGroup := id.ResourceGroup 824 name := id.Path["disks"] 825 826 _, error := diskClient.Delete(resGroup, name, make(chan struct{})) 827 err = <-error 828 if err != nil { 829 return fmt.Errorf("Error deleting Managed Disk (%s %s) %s", name, resGroup, err) 830 } 831 832 return nil 833 } 834 835 func resourceArmVirtualMachinePlanHash(v interface{}) int { 836 var buf bytes.Buffer 837 m := v.(map[string]interface{}) 838 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 839 buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string))) 840 buf.WriteString(fmt.Sprintf("%s-", m["product"].(string))) 841 842 return hashcode.String(buf.String()) 843 } 844 845 func resourceArmVirtualMachineStorageImageReferenceHash(v interface{}) int { 846 var buf bytes.Buffer 847 m := v.(map[string]interface{}) 848 buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string))) 849 buf.WriteString(fmt.Sprintf("%s-", m["offer"].(string))) 850 buf.WriteString(fmt.Sprintf("%s-", m["sku"].(string))) 851 852 return hashcode.String(buf.String()) 853 } 854 855 func resourceArmVirtualMachineStorageOsProfileHash(v interface{}) int { 856 var buf bytes.Buffer 857 m := v.(map[string]interface{}) 858 buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string))) 859 buf.WriteString(fmt.Sprintf("%s-", m["computer_name"].(string))) 860 return hashcode.String(buf.String()) 861 } 862 863 func resourceArmVirtualMachineStorageOsDiskHash(v interface{}) int { 864 var buf bytes.Buffer 865 m := v.(map[string]interface{}) 866 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 867 if m["vhd_uri"] != nil { 868 buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string))) 869 } 870 return hashcode.String(buf.String()) 871 } 872 873 func resourceArmVirtualMachineStorageOsProfileLinuxConfigHash(v interface{}) int { 874 var buf bytes.Buffer 875 m := v.(map[string]interface{}) 876 buf.WriteString(fmt.Sprintf("%t-", m["disable_password_authentication"].(bool))) 877 878 return hashcode.String(buf.String()) 879 } 880 881 func resourceArmVirtualMachineStorageOsProfileWindowsConfigHash(v interface{}) int { 882 var buf bytes.Buffer 883 m := v.(map[string]interface{}) 884 if m["provision_vm_agent"] != nil { 885 buf.WriteString(fmt.Sprintf("%t-", m["provision_vm_agent"].(bool))) 886 } 887 if m["enable_automatic_upgrades"] != nil { 888 buf.WriteString(fmt.Sprintf("%t-", m["enable_automatic_upgrades"].(bool))) 889 } 890 return hashcode.String(buf.String()) 891 } 892 893 func flattenAzureRmVirtualMachinePlan(plan *compute.Plan) []interface{} { 894 result := make(map[string]interface{}) 895 result["name"] = *plan.Name 896 result["publisher"] = *plan.Publisher 897 result["product"] = *plan.Product 898 899 return []interface{}{result} 900 } 901 902 func flattenAzureRmVirtualMachineImageReference(image *compute.ImageReference) []interface{} { 903 result := make(map[string]interface{}) 904 result["offer"] = *image.Offer 905 result["publisher"] = *image.Publisher 906 result["sku"] = *image.Sku 907 908 if image.Version != nil { 909 result["version"] = *image.Version 910 } 911 912 return []interface{}{result} 913 } 914 915 func flattenAzureRmVirtualMachineDiagnosticsProfile(profile *compute.BootDiagnostics) []interface{} { 916 result := make(map[string]interface{}) 917 918 result["enabled"] = *profile.Enabled 919 if profile.StorageURI != nil { 920 result["storage_uri"] = *profile.StorageURI 921 } 922 923 return []interface{}{result} 924 } 925 926 func flattenAzureRmVirtualMachineNetworkInterfaces(profile *compute.NetworkProfile) []string { 927 result := make([]string, 0, len(*profile.NetworkInterfaces)) 928 for _, nic := range *profile.NetworkInterfaces { 929 result = append(result, *nic.ID) 930 } 931 return result 932 } 933 934 func flattenAzureRmVirtualMachineOsProfileSecrets(secrets *[]compute.VaultSecretGroup) []map[string]interface{} { 935 result := make([]map[string]interface{}, 0, len(*secrets)) 936 for _, secret := range *secrets { 937 s := map[string]interface{}{ 938 "source_vault_id": *secret.SourceVault.ID, 939 } 940 941 if secret.VaultCertificates != nil { 942 certs := make([]map[string]interface{}, 0, len(*secret.VaultCertificates)) 943 for _, cert := range *secret.VaultCertificates { 944 vaultCert := make(map[string]interface{}) 945 vaultCert["certificate_url"] = *cert.CertificateURL 946 947 if cert.CertificateStore != nil { 948 vaultCert["certificate_store"] = *cert.CertificateStore 949 } 950 951 certs = append(certs, vaultCert) 952 } 953 954 s["vault_certificates"] = certs 955 } 956 957 result = append(result, s) 958 } 959 return result 960 } 961 962 func flattenAzureRmVirtualMachineDataDisk(disks *[]compute.DataDisk) interface{} { 963 result := make([]interface{}, len(*disks)) 964 for i, disk := range *disks { 965 l := make(map[string]interface{}) 966 l["name"] = *disk.Name 967 if disk.Vhd != nil { 968 l["vhd_uri"] = *disk.Vhd.URI 969 } 970 if disk.ManagedDisk != nil { 971 l["managed_disk_type"] = string(disk.ManagedDisk.StorageAccountType) 972 l["managed_disk_id"] = *disk.ManagedDisk.ID 973 } 974 l["create_option"] = disk.CreateOption 975 l["caching"] = string(disk.Caching) 976 if disk.DiskSizeGB != nil { 977 l["disk_size_gb"] = *disk.DiskSizeGB 978 } 979 l["lun"] = *disk.Lun 980 981 result[i] = l 982 } 983 return result 984 } 985 986 func flattenAzureRmVirtualMachineOsProfile(osProfile *compute.OSProfile) []interface{} { 987 result := make(map[string]interface{}) 988 result["computer_name"] = *osProfile.ComputerName 989 result["admin_username"] = *osProfile.AdminUsername 990 if osProfile.CustomData != nil { 991 result["custom_data"] = *osProfile.CustomData 992 } 993 994 return []interface{}{result} 995 } 996 997 func flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(config *compute.WindowsConfiguration) []interface{} { 998 result := make(map[string]interface{}) 999 1000 if config.ProvisionVMAgent != nil { 1001 result["provision_vm_agent"] = *config.ProvisionVMAgent 1002 } 1003 1004 if config.EnableAutomaticUpdates != nil { 1005 result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates 1006 } 1007 1008 if config.WinRM != nil { 1009 listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners)) 1010 for _, i := range *config.WinRM.Listeners { 1011 listener := make(map[string]interface{}) 1012 listener["protocol"] = i.Protocol 1013 1014 if i.CertificateURL != nil { 1015 listener["certificate_url"] = *i.CertificateURL 1016 } 1017 1018 listeners = append(listeners, listener) 1019 } 1020 1021 result["winrm"] = listeners 1022 } 1023 1024 if config.AdditionalUnattendContent != nil { 1025 content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent)) 1026 for _, i := range *config.AdditionalUnattendContent { 1027 c := make(map[string]interface{}) 1028 c["pass"] = i.PassName 1029 c["component"] = i.ComponentName 1030 c["setting_name"] = i.SettingName 1031 1032 if i.Content != nil { 1033 c["content"] = *i.Content 1034 } 1035 1036 content = append(content, c) 1037 } 1038 1039 result["additional_unattend_config"] = content 1040 } 1041 1042 return []interface{}{result} 1043 } 1044 1045 func flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(config *compute.LinuxConfiguration) []interface{} { 1046 1047 result := make(map[string]interface{}) 1048 result["disable_password_authentication"] = *config.DisablePasswordAuthentication 1049 1050 if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 { 1051 ssh_keys := make([]map[string]interface{}, 0, len(*config.SSH.PublicKeys)) 1052 for _, i := range *config.SSH.PublicKeys { 1053 key := make(map[string]interface{}) 1054 key["path"] = *i.Path 1055 1056 if i.KeyData != nil { 1057 key["key_data"] = *i.KeyData 1058 } 1059 1060 ssh_keys = append(ssh_keys, key) 1061 } 1062 1063 result["ssh_keys"] = ssh_keys 1064 } 1065 1066 return []interface{}{result} 1067 } 1068 1069 func flattenAzureRmVirtualMachineOsDisk(disk *compute.OSDisk) []interface{} { 1070 result := make(map[string]interface{}) 1071 result["name"] = *disk.Name 1072 if disk.Vhd != nil { 1073 result["vhd_uri"] = *disk.Vhd.URI 1074 } 1075 if disk.ManagedDisk != nil { 1076 result["managed_disk_type"] = string(disk.ManagedDisk.StorageAccountType) 1077 result["managed_disk_id"] = *disk.ManagedDisk.ID 1078 } 1079 result["create_option"] = disk.CreateOption 1080 result["caching"] = disk.Caching 1081 if disk.DiskSizeGB != nil { 1082 result["disk_size_gb"] = *disk.DiskSizeGB 1083 } 1084 1085 return []interface{}{result} 1086 } 1087 1088 func expandAzureRmVirtualMachinePlan(d *schema.ResourceData) (*compute.Plan, error) { 1089 planConfigs := d.Get("plan").(*schema.Set).List() 1090 1091 planConfig := planConfigs[0].(map[string]interface{}) 1092 1093 publisher := planConfig["publisher"].(string) 1094 name := planConfig["name"].(string) 1095 product := planConfig["product"].(string) 1096 1097 return &compute.Plan{ 1098 Publisher: &publisher, 1099 Name: &name, 1100 Product: &product, 1101 }, nil 1102 } 1103 1104 func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSProfile, error) { 1105 osProfiles := d.Get("os_profile").(*schema.Set).List() 1106 1107 osProfile := osProfiles[0].(map[string]interface{}) 1108 1109 adminUsername := osProfile["admin_username"].(string) 1110 adminPassword := osProfile["admin_password"].(string) 1111 computerName := osProfile["computer_name"].(string) 1112 1113 profile := &compute.OSProfile{ 1114 AdminUsername: &adminUsername, 1115 ComputerName: &computerName, 1116 } 1117 1118 if adminPassword != "" { 1119 profile.AdminPassword = &adminPassword 1120 } 1121 1122 if _, ok := d.GetOk("os_profile_windows_config"); ok { 1123 winConfig, err := expandAzureRmVirtualMachineOsProfileWindowsConfig(d) 1124 if err != nil { 1125 return nil, err 1126 } 1127 if winConfig != nil { 1128 profile.WindowsConfiguration = winConfig 1129 } 1130 } 1131 1132 if _, ok := d.GetOk("os_profile_linux_config"); ok { 1133 linuxConfig, err := expandAzureRmVirtualMachineOsProfileLinuxConfig(d) 1134 if err != nil { 1135 return nil, err 1136 } 1137 if linuxConfig != nil { 1138 profile.LinuxConfiguration = linuxConfig 1139 } 1140 } 1141 1142 if _, ok := d.GetOk("os_profile_secrets"); ok { 1143 secrets := expandAzureRmVirtualMachineOsProfileSecrets(d) 1144 if secrets != nil { 1145 profile.Secrets = secrets 1146 } 1147 } 1148 1149 if v := osProfile["custom_data"].(string); v != "" { 1150 v = base64Encode(v) 1151 profile.CustomData = &v 1152 } 1153 1154 return profile, nil 1155 } 1156 1157 func expandAzureRmVirtualMachineOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup { 1158 secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List() 1159 secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig)) 1160 1161 for _, secretConfig := range secretsConfig { 1162 config := secretConfig.(map[string]interface{}) 1163 sourceVaultId := config["source_vault_id"].(string) 1164 1165 vaultSecretGroup := compute.VaultSecretGroup{ 1166 SourceVault: &compute.SubResource{ 1167 ID: &sourceVaultId, 1168 }, 1169 } 1170 1171 if v := config["vault_certificates"]; v != nil { 1172 certsConfig := v.([]interface{}) 1173 certs := make([]compute.VaultCertificate, 0, len(certsConfig)) 1174 for _, certConfig := range certsConfig { 1175 config := certConfig.(map[string]interface{}) 1176 1177 certUrl := config["certificate_url"].(string) 1178 cert := compute.VaultCertificate{ 1179 CertificateURL: &certUrl, 1180 } 1181 if v := config["certificate_store"].(string); v != "" { 1182 cert.CertificateStore = &v 1183 } 1184 1185 certs = append(certs, cert) 1186 } 1187 vaultSecretGroup.VaultCertificates = &certs 1188 } 1189 1190 secrets = append(secrets, vaultSecretGroup) 1191 } 1192 1193 return &secrets 1194 } 1195 1196 func expandAzureRmVirtualMachineOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) { 1197 osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List() 1198 1199 linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{}) 1200 disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool) 1201 1202 config := &compute.LinuxConfiguration{ 1203 DisablePasswordAuthentication: &disablePasswordAuth, 1204 } 1205 1206 linuxKeys := linuxConfig["ssh_keys"].([]interface{}) 1207 sshPublicKeys := []compute.SSHPublicKey{} 1208 for _, key := range linuxKeys { 1209 1210 sshKey, ok := key.(map[string]interface{}) 1211 if !ok { 1212 continue 1213 } 1214 path := sshKey["path"].(string) 1215 keyData := sshKey["key_data"].(string) 1216 1217 sshPublicKey := compute.SSHPublicKey{ 1218 Path: &path, 1219 KeyData: &keyData, 1220 } 1221 1222 sshPublicKeys = append(sshPublicKeys, sshPublicKey) 1223 } 1224 1225 if len(sshPublicKeys) > 0 { 1226 config.SSH = &compute.SSHConfiguration{ 1227 PublicKeys: &sshPublicKeys, 1228 } 1229 } 1230 1231 return config, nil 1232 } 1233 1234 func expandAzureRmVirtualMachineOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) { 1235 osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List() 1236 1237 osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{}) 1238 config := &compute.WindowsConfiguration{} 1239 1240 if v := osProfileConfig["provision_vm_agent"]; v != nil { 1241 provision := v.(bool) 1242 config.ProvisionVMAgent = &provision 1243 } 1244 1245 if v := osProfileConfig["enable_automatic_upgrades"]; v != nil { 1246 update := v.(bool) 1247 config.EnableAutomaticUpdates = &update 1248 } 1249 1250 if v := osProfileConfig["winrm"]; v != nil { 1251 winRm := v.([]interface{}) 1252 if len(winRm) > 0 { 1253 winRmListeners := make([]compute.WinRMListener, 0, len(winRm)) 1254 for _, winRmConfig := range winRm { 1255 config := winRmConfig.(map[string]interface{}) 1256 1257 protocol := config["protocol"].(string) 1258 winRmListener := compute.WinRMListener{ 1259 Protocol: compute.ProtocolTypes(protocol), 1260 } 1261 if v := config["certificate_url"].(string); v != "" { 1262 winRmListener.CertificateURL = &v 1263 } 1264 1265 winRmListeners = append(winRmListeners, winRmListener) 1266 } 1267 config.WinRM = &compute.WinRMConfiguration{ 1268 Listeners: &winRmListeners, 1269 } 1270 } 1271 } 1272 if v := osProfileConfig["additional_unattend_config"]; v != nil { 1273 additionalConfig := v.([]interface{}) 1274 if len(additionalConfig) > 0 { 1275 additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig)) 1276 for _, addConfig := range additionalConfig { 1277 config := addConfig.(map[string]interface{}) 1278 pass := config["pass"].(string) 1279 component := config["component"].(string) 1280 settingName := config["setting_name"].(string) 1281 content := config["content"].(string) 1282 1283 addContent := compute.AdditionalUnattendContent{ 1284 PassName: compute.PassNames(pass), 1285 ComponentName: compute.ComponentNames(component), 1286 SettingName: compute.SettingNames(settingName), 1287 Content: &content, 1288 } 1289 1290 additionalConfigContent = append(additionalConfigContent, addContent) 1291 } 1292 config.AdditionalUnattendContent = &additionalConfigContent 1293 } 1294 } 1295 return config, nil 1296 } 1297 1298 func expandAzureRmVirtualMachineDataDisk(d *schema.ResourceData) ([]compute.DataDisk, error) { 1299 disks := d.Get("storage_data_disk").([]interface{}) 1300 data_disks := make([]compute.DataDisk, 0, len(disks)) 1301 for _, disk_config := range disks { 1302 config := disk_config.(map[string]interface{}) 1303 1304 name := config["name"].(string) 1305 createOption := config["create_option"].(string) 1306 vhdURI := config["vhd_uri"].(string) 1307 managedDiskType := config["managed_disk_type"].(string) 1308 managedDiskID := config["managed_disk_id"].(string) 1309 lun := int32(config["lun"].(int)) 1310 1311 data_disk := compute.DataDisk{ 1312 Name: &name, 1313 Lun: &lun, 1314 CreateOption: compute.DiskCreateOptionTypes(createOption), 1315 } 1316 1317 if vhdURI != "" { 1318 data_disk.Vhd = &compute.VirtualHardDisk{ 1319 URI: &vhdURI, 1320 } 1321 } 1322 1323 managedDisk := &compute.ManagedDiskParameters{} 1324 1325 if managedDiskType != "" { 1326 managedDisk.StorageAccountType = compute.StorageAccountTypes(managedDiskType) 1327 data_disk.ManagedDisk = managedDisk 1328 } 1329 1330 if managedDiskID != "" { 1331 managedDisk.ID = &managedDiskID 1332 data_disk.ManagedDisk = managedDisk 1333 } 1334 1335 //BEGIN: code to be removed after GH-13016 is merged 1336 if vhdURI != "" && managedDiskID != "" { 1337 return nil, fmt.Errorf("[ERROR] Conflict between `vhd_uri` and `managed_disk_id` (only one or the other can be used)") 1338 } 1339 if vhdURI != "" && managedDiskType != "" { 1340 return nil, fmt.Errorf("[ERROR] Conflict between `vhd_uri` and `managed_disk_type` (only one or the other can be used)") 1341 } 1342 //END: code to be removed after GH-13016 is merged 1343 if managedDiskID == "" && strings.EqualFold(string(data_disk.CreateOption), string(compute.Attach)) { 1344 return nil, fmt.Errorf("[ERROR] Must specify which disk to attach") 1345 } 1346 1347 if v := config["caching"].(string); v != "" { 1348 data_disk.Caching = compute.CachingTypes(v) 1349 } 1350 1351 if v := config["disk_size_gb"]; v != nil { 1352 diskSize := int32(config["disk_size_gb"].(int)) 1353 data_disk.DiskSizeGB = &diskSize 1354 } 1355 1356 data_disks = append(data_disks, data_disk) 1357 } 1358 1359 return data_disks, nil 1360 } 1361 1362 func expandAzureRmVirtualMachineDiagnosticsProfile(d *schema.ResourceData) *compute.DiagnosticsProfile { 1363 bootDiagnostics := d.Get("boot_diagnostics").([]interface{}) 1364 1365 diagnosticsProfile := &compute.DiagnosticsProfile{} 1366 if len(bootDiagnostics) > 0 { 1367 bootDiagnostic := bootDiagnostics[0].(map[string]interface{}) 1368 1369 diagnostic := &compute.BootDiagnostics{ 1370 Enabled: riviera.Bool(bootDiagnostic["enabled"].(bool)), 1371 StorageURI: riviera.String(bootDiagnostic["storage_uri"].(string)), 1372 } 1373 1374 diagnosticsProfile.BootDiagnostics = diagnostic 1375 1376 return diagnosticsProfile 1377 } 1378 1379 return nil 1380 } 1381 1382 func expandAzureRmVirtualMachineImageReference(d *schema.ResourceData) (*compute.ImageReference, error) { 1383 storageImageRefs := d.Get("storage_image_reference").(*schema.Set).List() 1384 1385 storageImageRef := storageImageRefs[0].(map[string]interface{}) 1386 1387 publisher := storageImageRef["publisher"].(string) 1388 offer := storageImageRef["offer"].(string) 1389 sku := storageImageRef["sku"].(string) 1390 version := storageImageRef["version"].(string) 1391 1392 return &compute.ImageReference{ 1393 Publisher: &publisher, 1394 Offer: &offer, 1395 Sku: &sku, 1396 Version: &version, 1397 }, nil 1398 } 1399 1400 func expandAzureRmVirtualMachineNetworkProfile(d *schema.ResourceData) compute.NetworkProfile { 1401 nicIds := d.Get("network_interface_ids").(*schema.Set).List() 1402 primaryNicId := d.Get("primary_network_interface_id").(string) 1403 network_interfaces := make([]compute.NetworkInterfaceReference, 0, len(nicIds)) 1404 1405 network_profile := compute.NetworkProfile{} 1406 1407 for _, nic := range nicIds { 1408 id := nic.(string) 1409 primary := id == primaryNicId 1410 1411 network_interface := compute.NetworkInterfaceReference{ 1412 ID: &id, 1413 NetworkInterfaceReferenceProperties: &compute.NetworkInterfaceReferenceProperties{ 1414 Primary: &primary, 1415 }, 1416 } 1417 network_interfaces = append(network_interfaces, network_interface) 1418 } 1419 1420 network_profile.NetworkInterfaces = &network_interfaces 1421 1422 return network_profile 1423 } 1424 1425 func expandAzureRmVirtualMachineOsDisk(d *schema.ResourceData) (*compute.OSDisk, error) { 1426 disks := d.Get("storage_os_disk").(*schema.Set).List() 1427 1428 config := disks[0].(map[string]interface{}) 1429 1430 name := config["name"].(string) 1431 imageURI := config["image_uri"].(string) 1432 createOption := config["create_option"].(string) 1433 vhdURI := config["vhd_uri"].(string) 1434 managedDiskType := config["managed_disk_type"].(string) 1435 managedDiskID := config["managed_disk_id"].(string) 1436 1437 osDisk := &compute.OSDisk{ 1438 Name: &name, 1439 CreateOption: compute.DiskCreateOptionTypes(createOption), 1440 } 1441 1442 if vhdURI != "" { 1443 osDisk.Vhd = &compute.VirtualHardDisk{ 1444 URI: &vhdURI, 1445 } 1446 } 1447 1448 managedDisk := &compute.ManagedDiskParameters{} 1449 1450 if managedDiskType != "" { 1451 managedDisk.StorageAccountType = compute.StorageAccountTypes(managedDiskType) 1452 osDisk.ManagedDisk = managedDisk 1453 } 1454 1455 if managedDiskID != "" { 1456 managedDisk.ID = &managedDiskID 1457 osDisk.ManagedDisk = managedDisk 1458 } 1459 1460 //BEGIN: code to be removed after GH-13016 is merged 1461 if vhdURI != "" && managedDiskID != "" { 1462 return nil, fmt.Errorf("[ERROR] Conflict between `vhd_uri` and `managed_disk_id` (only one or the other can be used)") 1463 } 1464 if vhdURI != "" && managedDiskType != "" { 1465 return nil, fmt.Errorf("[ERROR] Conflict between `vhd_uri` and `managed_disk_type` (only one or the other can be used)") 1466 } 1467 //END: code to be removed after GH-13016 is merged 1468 if managedDiskID == "" && vhdURI == "" && strings.EqualFold(string(osDisk.CreateOption), string(compute.Attach)) { 1469 return nil, fmt.Errorf("[ERROR] Must specify `vhd_uri` or `managed_disk_id` to attach") 1470 } 1471 1472 if v := config["image_uri"].(string); v != "" { 1473 osDisk.Image = &compute.VirtualHardDisk{ 1474 URI: &imageURI, 1475 } 1476 } 1477 1478 if v := config["os_type"].(string); v != "" { 1479 if v == "linux" { 1480 osDisk.OsType = compute.Linux 1481 } else if v == "windows" { 1482 osDisk.OsType = compute.Windows 1483 } else { 1484 return nil, fmt.Errorf("[ERROR] os_type must be 'linux' or 'windows'") 1485 } 1486 } 1487 1488 if v := config["caching"].(string); v != "" { 1489 osDisk.Caching = compute.CachingTypes(v) 1490 } 1491 1492 if v := config["disk_size_gb"].(int); v != 0 { 1493 diskSize := int32(v) 1494 osDisk.DiskSizeGB = &diskSize 1495 } 1496 1497 return osDisk, nil 1498 } 1499 1500 func findStorageAccountResourceGroup(meta interface{}, storageAccountName string) (string, error) { 1501 client := meta.(*ArmClient).resourceFindClient 1502 filter := fmt.Sprintf("name eq '%s' and resourceType eq 'Microsoft.Storage/storageAccounts'", storageAccountName) 1503 expand := "" 1504 var pager *int32 1505 1506 rf, err := client.List(filter, expand, pager) 1507 if err != nil { 1508 return "", fmt.Errorf("Error making resource request for query %s: %s", filter, err) 1509 } 1510 1511 results := *rf.Value 1512 if len(results) != 1 { 1513 return "", fmt.Errorf("Wrong number of results making resource request for query %s: %d", filter, len(results)) 1514 } 1515 1516 id, err := parseAzureResourceID(*results[0].ID) 1517 if err != nil { 1518 return "", err 1519 } 1520 1521 return id.ResourceGroup, nil 1522 }