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