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