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