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