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