diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index 9b3c5dcfa9aa..6ce290be0782 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -46,35 +46,36 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "azurerm_resource_group": resourceArmResourceGroup(), - "azurerm_virtual_network": resourceArmVirtualNetwork(), - "azurerm_local_network_gateway": resourceArmLocalNetworkGateway(), "azurerm_availability_set": resourceArmAvailabilitySet(), - "azurerm_network_security_group": resourceArmNetworkSecurityGroup(), - "azurerm_network_security_rule": resourceArmNetworkSecurityRule(), - "azurerm_public_ip": resourceArmPublicIp(), - "azurerm_subnet": resourceArmSubnet(), - "azurerm_network_interface": resourceArmNetworkInterface(), - "azurerm_route_table": resourceArmRouteTable(), - "azurerm_route": resourceArmRoute(), - "azurerm_cdn_profile": resourceArmCdnProfile(), "azurerm_cdn_endpoint": resourceArmCdnEndpoint(), - "azurerm_storage_account": resourceArmStorageAccount(), - "azurerm_storage_container": resourceArmStorageContainer(), - "azurerm_storage_blob": resourceArmStorageBlob(), - "azurerm_storage_queue": resourceArmStorageQueue(), - "azurerm_dns_zone": resourceArmDnsZone(), + "azurerm_cdn_profile": resourceArmCdnProfile(), "azurerm_dns_a_record": resourceArmDnsARecord(), "azurerm_dns_aaaa_record": resourceArmDnsAAAARecord(), "azurerm_dns_cname_record": resourceArmDnsCNameRecord(), - "azurerm_dns_txt_record": resourceArmDnsTxtRecord(), - "azurerm_dns_ns_record": resourceArmDnsNsRecord(), "azurerm_dns_mx_record": resourceArmDnsMxRecord(), + "azurerm_dns_ns_record": resourceArmDnsNsRecord(), "azurerm_dns_srv_record": resourceArmDnsSrvRecord(), - "azurerm_sql_server": resourceArmSqlServer(), + "azurerm_dns_txt_record": resourceArmDnsTxtRecord(), + "azurerm_dns_zone": resourceArmDnsZone(), + "azurerm_local_network_gateway": resourceArmLocalNetworkGateway(), + "azurerm_network_interface": resourceArmNetworkInterface(), + "azurerm_network_security_group": resourceArmNetworkSecurityGroup(), + "azurerm_network_security_rule": resourceArmNetworkSecurityRule(), + "azurerm_public_ip": resourceArmPublicIp(), + "azurerm_resource_group": resourceArmResourceGroup(), + "azurerm_route": resourceArmRoute(), + "azurerm_route_table": resourceArmRouteTable(), + "azurerm_search_service": resourceArmSearchService(), "azurerm_sql_database": resourceArmSqlDatabase(), "azurerm_sql_firewall_rule": resourceArmSqlFirewallRule(), - "azurerm_search_service": resourceArmSearchService(), + "azurerm_sql_server": resourceArmSqlServer(), + "azurerm_storage_account": resourceArmStorageAccount(), + "azurerm_storage_blob": resourceArmStorageBlob(), + "azurerm_storage_container": resourceArmStorageContainer(), + "azurerm_storage_queue": resourceArmStorageQueue(), + "azurerm_subnet": resourceArmSubnet(), + "azurerm_virtual_machine": resourceArmVirtualMachine(), + "azurerm_virtual_network": resourceArmVirtualNetwork(), }, ConfigureFunc: providerConfigure, } diff --git a/builtin/providers/azurerm/resource_arm_virtual_machine.go b/builtin/providers/azurerm/resource_arm_virtual_machine.go new file mode 100644 index 000000000000..4c2c38c8b899 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_virtual_machine.go @@ -0,0 +1,1095 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + "net/http" + "time" + + "github.com/Azure/azure-sdk-for-go/arm/compute" + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceArmVirtualMachine() *schema.Resource { + return &schema.Resource{ + Create: resourceArmVirtualMachineCreate, + Read: resourceArmVirtualMachineRead, + Update: resourceArmVirtualMachineCreate, + Delete: resourceArmVirtualMachineDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: azureRMNormalizeLocation, + }, + + "resource_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "plan": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "publisher": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "product": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceArmVirtualMachinePlanHash, + }, + + "availability_set_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "license_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "vm_size": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "storage_image_reference": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "publisher": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "offer": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "sku": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "version": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + Set: resourceArmVirtualMachineStorageImageReferenceHash, + }, + + "storage_os_disk": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "vhd_uri": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "caching": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "create_option": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceArmVirtualMachineStorageOsDiskHash, + }, + + "storage_data_disk": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "vhd_uri": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "create_option": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "disk_size_gb": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "lun": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + }, + }, + Set: resourceArmVirtualMachineStorageDataDiskHash, + }, + + "os_profile": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "computer_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "admin_username": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "admin_password": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "custom_data": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + Set: resourceArmVirtualMachineStorageOsProfileHash, + }, + + "os_profile_windows_config": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "provision_vm_agent": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + }, + "enable_automatic_upgrades": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + }, + "winrm": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "protocol": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "certificate_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "additional_unattend_config": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pass": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "component": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "setting_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "content": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + }, + }, + Set: resourceArmVirtualMachineStorageOsProfileWindowsConfigHash, + }, + + "os_profile_linux_config": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disable_password_authentication": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + }, + "ssh_keys": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "path": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "key_data": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + }, + Set: resourceArmVirtualMachineStorageOsProfileLinuxConfigSshKeyHash, + }, + }, + }, + Set: resourceArmVirtualMachineStorageOsProfileLinuxConfigHash, + }, + + "os_profile_secrets": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "source_vault_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "vault_certificates": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "certificate_url": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "certificate_store": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + + "network_interface_ids": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + } +} + +func resourceArmVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + vmClient := client.vmClient + + log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine creation.") + + name := d.Get("name").(string) + location := d.Get("location").(string) + resGroup := d.Get("resource_group_name").(string) + + osDisk, err := expandAzureRmVirtualMachineOsDisk(d) + if err != nil { + return err + } + storageProfile := compute.StorageProfile{ + OsDisk: osDisk, + } + + if _, ok := d.GetOk("storage_image_reference"); ok { + imageRef, err := expandAzureRmVirtualMachineImageReference(d) + if err != nil { + return err + } + storageProfile.ImageReference = imageRef + } + + if _, ok := d.GetOk("storage_data_disk"); ok { + dataDisks, err := expandAzureRmVirtualMachineDataDisk(d) + if err != nil { + return err + } + storageProfile.DataDisks = &dataDisks + } + + networkProfile := expandAzureRmVirtualMachineNetworkProfile(d) + vmSize := d.Get("vm_size").(string) + properties := compute.VirtualMachineProperties{ + NetworkProfile: &networkProfile, + HardwareProfile: &compute.HardwareProfile{ + VMSize: compute.VirtualMachineSizeTypes(vmSize), + }, + StorageProfile: &storageProfile, + } + + osProfile, err := expandAzureRmVirtualMachineOsProfile(d) + if err != nil { + return err + } + properties.OsProfile = osProfile + + if v, ok := d.GetOk("availability_set_id"); ok { + availabilitySet := v.(string) + availSet := compute.SubResource{ + ID: &availabilitySet, + } + + properties.AvailabilitySet = &availSet + } + + vm := compute.VirtualMachine{ + Name: &name, + Location: &location, + Properties: &properties, + } + + if _, ok := d.GetOk("plan"); ok { + plan, err := expandAzureRmVirtualMachinePlan(d) + if err != nil { + return err + } + + vm.Plan = plan + } + + resp, vmErr := vmClient.CreateOrUpdate(resGroup, name, vm) + if vmErr != nil { + return vmErr + } + + d.SetId(*resp.ID) + + log.Printf("[DEBUG] Waiting for Virtual Machine (%s) to become available", name) + stateConf := &resource.StateChangeConf{ + Pending: []string{"Creating", "Updating"}, + Target: []string{"Succeeded"}, + Refresh: virtualMachineStateRefreshFunc(client, resGroup, name), + Timeout: 10 * time.Minute, + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("Error waiting for Virtual Machine (%s) to become available: %s", name, err) + } + + return resourceArmVirtualMachineRead(d, meta) +} + +func resourceArmVirtualMachineRead(d *schema.ResourceData, meta interface{}) error { + vmClient := meta.(*ArmClient).vmClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + name := id.Path["virtualMachines"] + + resp, err := vmClient.Get(resGroup, name, "") + if resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("Error making Read request on Azure Virtual Machine %s: %s", name, err) + } + + if resp.Plan != nil { + if err := d.Set("plan", flattenAzureRmVirtualMachinePlan(resp.Plan)); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Plan error: %#v", err) + } + } + + if resp.Properties.AvailabilitySet != nil { + d.Set("availability_set_id", resp.Properties.AvailabilitySet.ID) + } + + d.Set("vm_size", resp.Properties.HardwareProfile.VMSize) + + if resp.Properties.StorageProfile.ImageReference != nil { + if err := d.Set("storage_image_reference", schema.NewSet(resourceArmVirtualMachineStorageImageReferenceHash, flattenAzureRmVirtualMachineImageReference(resp.Properties.StorageProfile.ImageReference))); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Image Reference error: %#v", err) + } + } + + if err := d.Set("storage_os_disk", schema.NewSet(resourceArmVirtualMachineStorageOsDiskHash, flattenAzureRmVirtualMachineOsDisk(resp.Properties.StorageProfile.OsDisk))); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Disk error: %#v", err) + } + + if resp.Properties.StorageProfile.DataDisks != nil { + if err := d.Set("storage_data_disk", flattenAzureRmVirtualMachineDataDisk(resp.Properties.StorageProfile.DataDisks)); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Data Disks error: %#v", err) + } + } + + if err := d.Set("os_profile", schema.NewSet(resourceArmVirtualMachineStorageOsProfileHash, flattenAzureRmVirtualMachineOsProfile(resp.Properties.OsProfile))); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile: %#v", err) + } + + if resp.Properties.OsProfile.WindowsConfiguration != nil { + if err := d.Set("os_profile_windows_config", schema.NewSet(resourceArmVirtualMachineStorageOsProfileWindowsConfigHash, flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(resp.Properties.OsProfile.WindowsConfiguration))); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Windows Configuration: %#v", err) + } + } + + if resp.Properties.OsProfile.LinuxConfiguration != nil { + if err := d.Set("os_profile_linux_config", schema.NewSet(resourceArmVirtualMachineStorageOsProfileLinuxConfigHash, flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(resp.Properties.OsProfile.LinuxConfiguration))); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Linux Configuration: %#v", err) + } + } + + if resp.Properties.OsProfile.Secrets != nil { + if err := d.Set("os_profile_secrets", flattenAzureRmVirtualMachineOsProfileSecrets(resp.Properties.OsProfile.Secrets)); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage OS Profile Secrets: %#v", err) + } + } + + if resp.Properties.NetworkProfile != nil { + if err := d.Set("network_interface_ids", flattenAzureRmVirtualMachineNetworkInterfaces(resp.Properties.NetworkProfile)); err != nil { + return fmt.Errorf("[DEBUG] Error setting Virtual Machine Storage Network Interfaces: %#v", err) + } + } + + return nil +} + +func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error { + vmClient := meta.(*ArmClient).vmClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + name := id.Path["virtualMachines"] + + _, err = vmClient.Delete(resGroup, name) + + return err +} + +func virtualMachineStateRefreshFunc(client *ArmClient, resourceGroupName string, vmName string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + res, err := client.vmClient.Get(resourceGroupName, vmName, "") + if err != nil { + return nil, "", fmt.Errorf("Error issuing read request in virtualMachineStateRefreshFunc to Azure ARM for Virtual Machine '%s' (RG: '%s'): %s", vmName, resourceGroupName, err) + } + + return res, *res.Properties.ProvisioningState, nil + } +} + +func resourceArmVirtualMachinePlanHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["product"].(string))) + + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageImageReferenceHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["publisher"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["offer"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["sku"].(string))) + + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageOsProfileHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["admin_username"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["computer_name"].(string))) + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageDataDiskHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["create_option"].(string))) + buf.WriteString(fmt.Sprintf("%d-", m["disk_size_gb"].(int))) + buf.WriteString(fmt.Sprintf("%d-", m["lun"].(int))) + + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageOsDiskHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string))) + + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageOsProfileLinuxConfigSshKeyHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["path"].(string))) + if m["key_data"] != nil { + buf.WriteString(fmt.Sprintf("%s-", m["key_data"].(string))) + } + + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageOsProfileLinuxConfigHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%t-", m["disable_password_authentication"].(bool))) + + return hashcode.String(buf.String()) +} + +func resourceArmVirtualMachineStorageOsProfileWindowsConfigHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + if m["provision_vm_agent"] != nil { + buf.WriteString(fmt.Sprintf("%t-", m["provision_vm_agent"].(bool))) + } + if m["enable_automatic_upgrades"] != nil { + buf.WriteString(fmt.Sprintf("%t-", m["enable_automatic_upgrades"].(bool))) + } + return hashcode.String(buf.String()) +} + +func flattenAzureRmVirtualMachinePlan(plan *compute.Plan) map[string]interface{} { + result := make(map[string]interface{}) + result["name"] = *plan.Name + result["publisher"] = *plan.Publisher + result["product"] = *plan.Product + + return result +} + +func flattenAzureRmVirtualMachineImageReference(image *compute.ImageReference) []interface{} { + result := make(map[string]interface{}) + result["offer"] = *image.Offer + result["publisher"] = *image.Publisher + result["sku"] = *image.Sku + + if image.Version != nil { + result["version"] = *image.Version + } + + return []interface{}{result} +} + +func flattenAzureRmVirtualMachineNetworkInterfaces(profile *compute.NetworkProfile) []string { + result := make([]string, 0, len(*profile.NetworkInterfaces)) + for _, nic := range *profile.NetworkInterfaces { + result = append(result, *nic.ID) + } + return result +} + +func flattenAzureRmVirtualMachineOsProfileSecrets(secrets *[]compute.VaultSecretGroup) []map[string]interface{} { + result := make([]map[string]interface{}, 0, len(*secrets)) + for _, secret := range *secrets { + s := map[string]interface{}{ + "source_vault_id": *secret.SourceVault.ID, + } + + if secret.VaultCertificates != nil { + certs := make([]map[string]interface{}, 0, len(*secret.VaultCertificates)) + for _, cert := range *secret.VaultCertificates { + vaultCert := make(map[string]interface{}) + vaultCert["certificate_url"] = *cert.CertificateURL + + if cert.CertificateStore != nil { + vaultCert["certificate_store"] = *cert.CertificateStore + } + + certs = append(certs, vaultCert) + } + + s["vault_certificates"] = certs + } + + result = append(result, s) + } + return result +} + +func flattenAzureRmVirtualMachineDataDisk(disks *[]compute.DataDisk) []map[string]interface{} { + result := make([]map[string]interface{}, 0, len(*disks)) + for _, i := range *disks { + l := make(map[string]interface{}) + l["name"] = *i.Name + l["vhd_url"] = *i.Vhd.URI + l["create_option"] = i.CreateOption + l["disk_size_gb"] = *i.DiskSizeGB + l["lun"] = *i.Lun + + result = append(result, l) + } + return result +} + +func flattenAzureRmVirtualMachineOsProfile(osProfile *compute.OSProfile) []interface{} { + result := make(map[string]interface{}) + result["computer_name"] = *osProfile.ComputerName + result["admin_username"] = *osProfile.AdminUsername + if osProfile.CustomData != nil { + result["custom_data"] = *osProfile.CustomData + } + + return []interface{}{result} +} + +func flattenAzureRmVirtualMachineOsProfileWindowsConfiguration(config *compute.WindowsConfiguration) []interface{} { + result := make(map[string]interface{}) + + if config.ProvisionVMAgent != nil { + result["provision_vm_agent"] = *config.ProvisionVMAgent + } + + if config.EnableAutomaticUpdates != nil { + result["enable_automatic_upgrades"] = *config.EnableAutomaticUpdates + } + + if config.WinRM != nil { + listeners := make([]map[string]interface{}, 0, len(*config.WinRM.Listeners)) + for _, i := range *config.WinRM.Listeners { + listener := make(map[string]interface{}) + listener["protocol"] = i.Protocol + + if i.CertificateURL != nil { + listener["certificate_url"] = *i.CertificateURL + } + + listeners = append(listeners, listener) + } + + result["winrm"] = listeners + } + + if config.AdditionalUnattendContent != nil { + content := make([]map[string]interface{}, 0, len(*config.AdditionalUnattendContent)) + for _, i := range *config.AdditionalUnattendContent { + c := make(map[string]interface{}) + c["pass"] = i.PassName + c["component"] = i.ComponentName + c["setting_name"] = i.SettingName + c["content"] = *i.Content + + content = append(content, c) + } + + result["additional_unattend_config"] = content + } + + return []interface{}{result} +} + +func flattenAzureRmVirtualMachineOsProfileLinuxConfiguration(config *compute.LinuxConfiguration) []interface{} { + result := map[string]interface{}{ + "disable_password_authentication": *config.DisablePasswordAuthentication, + } + + if config.SSH != nil && len(*config.SSH.PublicKeys) > 0 { + ssh_keys := make([]map[string]interface{}, 0, len(*config.SSH.PublicKeys)) + for _, i := range *config.SSH.PublicKeys { + key := make(map[string]interface{}) + key["name"] = *i.Path + + if i.KeyData != nil { + key["key_data"] = *i.KeyData + } + + ssh_keys = append(ssh_keys, key) + } + + result["ssh_keys"] = ssh_keys + } + + return []interface{}{result} +} + +func flattenAzureRmVirtualMachineOsDisk(disk *compute.OSDisk) []interface{} { + result := make(map[string]interface{}) + result["name"] = *disk.Name + result["vhd_uri"] = *disk.Vhd.URI + result["create_option"] = disk.CreateOption + result["caching"] = disk.Caching + + return []interface{}{result} +} + +func expandAzureRmVirtualMachinePlan(d *schema.ResourceData) (*compute.Plan, error) { + planConfigs := d.Get("plan").(*schema.Set).List() + + if len(planConfigs) != 1 { + return nil, fmt.Errorf("Cannot specify more than one plan.") + } + + planConfig := planConfigs[0].(map[string]interface{}) + + publisher := planConfig["publisher"].(string) + name := planConfig["name"].(string) + product := planConfig["product"].(string) + + return &compute.Plan{ + Publisher: &publisher, + Name: &name, + Product: &product, + }, nil +} + +func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSProfile, error) { + osProfiles := d.Get("os_profile").(*schema.Set).List() + + if len(osProfiles) != 1 { + return nil, fmt.Errorf("[ERROR] Only 1 OS Profile Can be specified for an Azure RM Virtual Machine") + } + + osProfile := osProfiles[0].(map[string]interface{}) + + adminUsername := osProfile["admin_username"].(string) + adminPassword := osProfile["admin_password"].(string) + + profile := &compute.OSProfile{ + AdminUsername: &adminUsername, + AdminPassword: &adminPassword, + } + + if _, ok := d.GetOk("os_profile_windows_config"); ok { + winConfig, err := expandAzureRmVirtualMachineOsProfileWindowsConfig(d) + if err != nil { + return nil, err + } + if winConfig != nil { + profile.WindowsConfiguration = winConfig + } + } + + if _, ok := d.GetOk("os_profile_linux_config"); ok { + linuxConfig, err := expandAzureRmVirtualMachineOsProfileLinuxConfig(d) + if err != nil { + return nil, err + } + if linuxConfig != nil { + profile.LinuxConfiguration = linuxConfig + } + } + + if _, ok := d.GetOk("os_profile_secrets"); ok { + secrets := expandAzureRmVirtualMachineOsProfileSecrets(d) + if secrets != nil { + profile.Secrets = secrets + } + } + + if v := osProfile["computer_name"].(string); v != "" { + profile.ComputerName = &v + } + if v := osProfile["custom_data"].(string); v != "" { + profile.CustomData = &v + } + + return profile, nil +} + +func expandAzureRmVirtualMachineOsProfileSecrets(d *schema.ResourceData) *[]compute.VaultSecretGroup { + secretsConfig := d.Get("os_profile_secrets").(*schema.Set).List() + secrets := make([]compute.VaultSecretGroup, 0, len(secretsConfig)) + + for _, secretConfig := range secretsConfig { + config := secretConfig.(map[string]interface{}) + sourceVaultId := config["source_vault_id"].(string) + + vaultSecretGroup := compute.VaultSecretGroup{ + SourceVault: &compute.SubResource{ + ID: &sourceVaultId, + }, + } + + if v := config["vault_certificates"]; v != nil { + certsConfig := v.(*schema.Set).List() + certs := make([]compute.VaultCertificate, 0, len(certsConfig)) + for _, certConfig := range certsConfig { + config := certConfig.(map[string]interface{}) + + certUrl := config["certificate_url"].(string) + cert := compute.VaultCertificate{ + CertificateURL: &certUrl, + } + if v := config["certificate_store"].(string); v != "" { + cert.CertificateStore = &v + } + + certs = append(certs, cert) + } + vaultSecretGroup.VaultCertificates = &certs + } + + secrets = append(secrets, vaultSecretGroup) + } + + return &secrets +} + +func expandAzureRmVirtualMachineOsProfileLinuxConfig(d *schema.ResourceData) (*compute.LinuxConfiguration, error) { + osProfilesLinuxConfig := d.Get("os_profile_linux_config").(*schema.Set).List() + + if len(osProfilesLinuxConfig) != 1 { + return nil, fmt.Errorf("[ERROR] Only 1 OS Profile Linux Config Can be specified for an Azure RM Virtual Machine") + } + + linuxConfig := osProfilesLinuxConfig[0].(map[string]interface{}) + disablePasswordAuth := linuxConfig["disable_password_authentication"].(bool) + + config := &compute.LinuxConfiguration{ + DisablePasswordAuthentication: &disablePasswordAuth, + } + + linuxKeys := linuxConfig["ssh_keys"].(*schema.Set).List() + sshPublicKeys := make([]compute.SSHPublicKey, 0, len(linuxKeys)) + for _, key := range linuxKeys { + sshKey := key.(map[string]interface{}) + path := sshKey["path"].(string) + keyData := sshKey["key_data"].(string) + + sshPublicKey := compute.SSHPublicKey{ + Path: &path, + KeyData: &keyData, + } + + sshPublicKeys = append(sshPublicKeys, sshPublicKey) + } + + config.SSH = &compute.SSHConfiguration{ + PublicKeys: &sshPublicKeys, + } + + return config, nil +} + +func expandAzureRmVirtualMachineOsProfileWindowsConfig(d *schema.ResourceData) (*compute.WindowsConfiguration, error) { + osProfilesWindowsConfig := d.Get("os_profile_windows_config").(*schema.Set).List() + + if len(osProfilesWindowsConfig) != 1 { + return nil, fmt.Errorf("[ERROR] Only 1 OS Profile Windows Config Can be specified for an Azure RM Virtual Machine") + } + + osProfileConfig := osProfilesWindowsConfig[0].(map[string]interface{}) + config := &compute.WindowsConfiguration{} + + if v := osProfileConfig["provision_vm_agent"]; v != nil { + provision := v.(bool) + config.ProvisionVMAgent = &provision + } + + if v := osProfileConfig["enable_automatic_upgrades"]; v != nil { + update := v.(bool) + config.EnableAutomaticUpdates = &update + } + + if v := osProfileConfig["winrm"]; v != nil { + winRm := v.(*schema.Set).List() + if len(winRm) > 0 { + winRmListners := make([]compute.WinRMListener, 0, len(winRm)) + for _, winRmConfig := range winRm { + config := winRmConfig.(map[string]interface{}) + + protocol := config["protocol"].(string) + winRmListner := compute.WinRMListener{ + Protocol: compute.ProtocolTypes(protocol), + } + if v := config["certificate_url"].(string); v != "" { + winRmListner.CertificateURL = &v + } + + winRmListners = append(winRmListners, winRmListner) + } + config.WinRM = &compute.WinRMConfiguration{ + Listeners: &winRmListners, + } + } + } + if v := osProfileConfig["additional_unattend_config"]; v != nil { + additionalConfig := v.(*schema.Set).List() + if len(additionalConfig) > 0 { + additionalConfigContent := make([]compute.AdditionalUnattendContent, 0, len(additionalConfig)) + for _, addConfig := range additionalConfig { + config := addConfig.(map[string]interface{}) + pass := config["pass"].(string) + component := config["component"].(string) + settingName := config["setting_name"].(string) + content := config["content"].(string) + + addContent := compute.AdditionalUnattendContent{ + PassName: compute.PassNames(pass), + ComponentName: compute.ComponentNames(component), + SettingName: compute.SettingNames(settingName), + Content: &content, + } + + additionalConfigContent = append(additionalConfigContent, addContent) + } + config.AdditionalUnattendContent = &additionalConfigContent + } + } + return config, nil +} + +func expandAzureRmVirtualMachineDataDisk(d *schema.ResourceData) ([]compute.DataDisk, error) { + disks := d.Get("storage_data_disk").([]interface{}) + data_disks := make([]compute.DataDisk, 0, len(disks)) + for _, disk_config := range disks { + config := disk_config.(map[string]interface{}) + + name := config["name"].(string) + vhd := config["vhd_uri"].(string) + createOption := config["create_option"].(string) + lun := config["lun"].(int) + disk_size := config["disk_size_gb"].(int) + + data_disk := compute.DataDisk{ + Name: &name, + Vhd: &compute.VirtualHardDisk{ + URI: &vhd, + }, + Lun: &lun, + DiskSizeGB: &disk_size, + CreateOption: compute.DiskCreateOptionTypes(createOption), + } + + data_disks = append(data_disks, data_disk) + } + + return data_disks, nil +} + +func expandAzureRmVirtualMachineImageReference(d *schema.ResourceData) (*compute.ImageReference, error) { + storageImageRefs := d.Get("storage_image_reference").(*schema.Set).List() + + if len(storageImageRefs) != 1 { + return nil, fmt.Errorf("Cannot specify more than one storage_image_reference.") + } + + storageImageRef := storageImageRefs[0].(map[string]interface{}) + + publisher := storageImageRef["publisher"].(string) + offer := storageImageRef["offer"].(string) + sku := storageImageRef["sku"].(string) + version := storageImageRef["version"].(string) + + return &compute.ImageReference{ + Publisher: &publisher, + Offer: &offer, + Sku: &sku, + Version: &version, + }, nil +} + +func expandAzureRmVirtualMachineNetworkProfile(d *schema.ResourceData) compute.NetworkProfile { + nicIds := d.Get("network_interface_ids").(*schema.Set).List() + network_interfaces := make([]compute.NetworkInterfaceReference, 0, len(nicIds)) + + network_profile := compute.NetworkProfile{} + + for _, nic := range nicIds { + id := nic.(string) + network_interface := compute.NetworkInterfaceReference{ + ID: &id, + } + network_interfaces = append(network_interfaces, network_interface) + } + + network_profile.NetworkInterfaces = &network_interfaces + + return network_profile +} + +func expandAzureRmVirtualMachineOsDisk(d *schema.ResourceData) (*compute.OSDisk, error) { + disks := d.Get("storage_os_disk").(*schema.Set).List() + + if len(disks) != 1 { + return nil, fmt.Errorf("[ERROR] Only 1 OS Disk Can be specified for an Azure RM Virtual Machine") + } + + disk := disks[0].(map[string]interface{}) + + name := disk["name"].(string) + vhdURI := disk["vhd_uri"].(string) + createOption := disk["create_option"].(string) + + osDisk := &compute.OSDisk{ + Name: &name, + Vhd: &compute.VirtualHardDisk{ + URI: &vhdURI, + }, + CreateOption: compute.DiskCreateOptionTypes(createOption), + } + + if v := disk["caching"].(string); v != "" { + osDisk.Caching = compute.CachingTypes(v) + } + + return osDisk, nil +} diff --git a/builtin/providers/azurerm/resource_arm_virtual_machine_test.go b/builtin/providers/azurerm/resource_arm_virtual_machine_test.go new file mode 100644 index 000000000000..73c695b1abb9 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_virtual_machine_test.go @@ -0,0 +1,268 @@ +package azurerm + +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAzureRMVirtualMachine_basicLinuxMachine(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMVirtualMachine_basicLinuxMachine, ri, ri, ri, ri, ri, ri, ri) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualMachineDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualMachineExists("azurerm_virtual_machine.test"), + ), + }, + }, + }) +} + +func TestAccAzureRMVirtualMachine_basicWindowsMachine(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMVirtualMachine_basicWindowsMachine, ri, ri, ri, ri, ri, ri) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualMachineDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualMachineExists("azurerm_virtual_machine.test"), + ), + }, + }, + }) +} + +func testCheckAzureRMVirtualMachineExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + vmName := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for virtual machine: %s", vmName) + } + + conn := testAccProvider.Meta().(*ArmClient).vmClient + + resp, err := conn.Get(resourceGroup, vmName, "") + if err != nil { + return fmt.Errorf("Bad: Get on vmClient: %s", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: VirtualMachine %q (resource group: %q) does not exist", vmName, resourceGroup) + } + + return nil + } +} + +func testCheckAzureRMVirtualMachineDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).vmClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_virtual_machine" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(resourceGroup, name, "") + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Virtual Machine still exists:\n%#v", resp.Properties) + } + } + + return nil +} + +var testAccAzureRMVirtualMachine_basicLinuxMachine = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn-%d" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctsub-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "test" { + name = "acctni-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.test.id}" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_storage_account" "test" { + name = "accsa%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "westus" + account_type = "Standard_LRS" + + tags { + environment = "staging" + } +} + +resource "azurerm_storage_container" "test" { + name = "vhds" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" +} + +resource "azurerm_virtual_machine" "test" { + name = "acctvm-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + network_interface_ids = ["${azurerm_network_interface.test.id}"] + vm_size = "Standard_A0" + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "14.04.2-LTS" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd" + caching = "ReadWrite" + create_option = "FromImage" + } + + os_profile { + computer_name = "hostname%d" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } +} +` + +var testAccAzureRMVirtualMachine_basicWindowsMachine = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn-%d" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctsub-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "test" { + name = "acctni-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.test.id}" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_storage_account" "test" { + name = "accsa%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "westus" + account_type = "Standard_LRS" + + tags { + environment = "staging" + } +} + +resource "azurerm_storage_container" "test" { + name = "vhds" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" +} + +resource "azurerm_virtual_machine" "test" { + name = "acctvm-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + network_interface_ids = ["${azurerm_network_interface.test.id}"] + vm_size = "Standard_A0" + + storage_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2012-Datacenter" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd" + caching = "ReadWrite" + create_option = "FromImage" + } + + os_profile { + computer_name = "winhost01" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_windows_config { + enable_automatic_upgrades = false + provision_vm_agent = true + } +} +` diff --git a/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown b/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown new file mode 100644 index 000000000000..bd3725740ba7 --- /dev/null +++ b/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown @@ -0,0 +1,194 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_virtual_machine" +sidebar_current: "docs-azurerm-resource-virtualmachine" +description: |- + Create a Virtual Machine. +--- + +# azurerm\_virtual\_machine + +Create a virtual machine. + +## Example Usage + +``` +resource "azurerm_resource_group" "test" { + name = "acctestrg" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctsub" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "test" { + name = "acctni" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.test.id}" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_storage_account" "test" { + name = "accsa" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "westus" + account_type = "Standard_LRS" + + tags { + environment = "staging" + } +} + +resource "azurerm_storage_container" "test" { + name = "vhds" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" +} + +resource "azurerm_virtual_machine" "test" { + name = "acctvm" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + network_interface_ids = ["${azurerm_network_interface.test.id}"] + vm_size = "Standard_A0" + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "14.04.2-LTS" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd" + caching = "ReadWrite" + create_option = "FromImage" + } + + os_profile { + computer_name = "hostname%d" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the virtual machine resource. Changing this forces a + new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to + create the virtual machine. +* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. +* `plan` - (Optional) A plan block as documented below. +* `availability_set_id` - (Optional) The Id of the Availablity Set in which to create the virtual machine +* `vm_size` - (Required) Specifies the [size of the virtual machine](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-size-specs/). +* `storage_image_reference` - (Optional) A Storage Image Reference block as documented below. +* `storage_os_disk` - (Required) A Storage OS Disk block as referenced below. +* `storage_data_disk` - (Optional) A list of Storage Data disk blocks as referenced below. +* `os_profile` - (Required) An OS Profile block as documented below. +* `os_profile_windows_config` - (Required, when a windows machine) A Windows config block as documented below. +* `os_profile_linux_config` - (Required, when a linux machine) A Linux config block as documented below. +* `os_profile_secrets` - (Optional) A collection of Secret blocks as documented below. +* `network_interface_ids` - (Required) Specifies the list of resource IDs for the network interfaces associated with the virtual machine. + +For more information on the different example configurations, please check out the [azure documentation](https://msdn.microsoft.com/en-us/library/mt163591.aspx#Anchor_2) + +`Plan` supports the following: + +* `name` - (Required) Specifies the name of the image from the marketplace. +* `publisher` - (Optional) Specifies the publisher of the image. +* `product` - (Optional) Specifies the product of the image from the marketplace. + +`storage_image_reference` supports the following: + +* `publisher` - (Required) Specifies the publisher of the image used to create the virtual machine +* `offer` - (Required) Specifies the offer of the image used to create the virtual machine. +* `sku` - (Required) Specifies the SKU of the image used to create the virtual machine. +* `version` - (Optional) Specifies the version of the image used to create the virtual machine. + +`storage_os_disk` supports the following: + +* `name` - (Required) Specifies the disk name. +* `vhd_uri` - (Required) Specifies the vhd uri. +* `create_option` - (Required) Specifies how the virtual machine should be created. Possible values are `attach` and `FromImage`. +* `caching` - (Optional) Specifies the caching requirements. + +`storage_data_disk` supports the following: + +* `name` - (Required) Specifies the name of the data disk. +* `vhd_uri` - (Required) Specifies the uri of the location in storage where the vhd for the virtual machine should be placed. +* `create_option` - (Required) Specifies how the data disk should be created. +* `disk_size_gb` - (Required) Specifies the size of the data disk in gigabytes. +* `lun` - (Required) Specifies the logical unit number of the data disk. + +`os_profile` supports the following: + +* `computer_name` - (Optional) Specifies the name of the virtual machine. +* `admin_username` - (Required) Specifies the name of the administrator account. +* `admin_password` - (Required) Specifies the password of the administrator account. +* `custom_data` - (Optional) Specifies a base-64 encoded string of custom data. The base-64 encoded string is decoded to a binary array that is saved as a file on the Virtual Machine. The maximum length of the binary array is 65535 bytes. + +`os_profile_windows_config` supports the following: + +* `provision_vm_agent` - (Optional) +* `enable_automatic_upgrades` - (Optional) +* `winrm` - (Optional) A collection of WinRM configuration blocks as documented below. +* `additional_unattend_config` - (Optional) An Additional Unattended Config block as documented below. + +`winrm` supports the following: + +* `protocol` - (Required) Specifies the protocol of listener +* `certificate_url` - (Optional) Specifies URL of the certificate with which new Virtual Machines is provisioned. + +`additional_unattend_config` supports the following: + +* `pass` - (Required) Specifies the name of the pass that the content applies to. The only allowable value is `oobeSystem`. +* `component` - (Required) Specifies the name of the component to configure with the added content. The only allowable value is `Microsoft-Windows-Shell-Setup`. +* `setting_name` - (Required) Specifies the name of the setting to which the content applies. Possible values are: `FirstLogonCommands` and `AutoLogon`. +* `content` - (Optional) Specifies the base-64 encoded XML formatted content that is added to the unattend.xml file for the specified path and component. + +`os_profile_linux_config` supports the following: + +* `disable_password_authentication` - (Required) Specifies whether password authentication should be disabled. +* `ssh_keys` - (Optional) Specifies a collection of `key_path` and `key_data` to be placed on the virtual machine. + +`os_profile_secrets` supports the following: + +* `source_vault_id` - (Required) Specifies the key vault to use. +* `vault_certificates` - (Required, on windows machines) A collection of Vault Certificates as documented below + +`vault_certificates` support the following: + +* `certificate_url` - (Required) It is the Base64 encoding of a JSON Object that which is encoded in UTF-8 of which the contents need to be `data`, `dataType` and `password`. +* `certificate_store` - (Required, on windows machines) Specifies the certificate store on the Virtual Machine where the certificate should be added to. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The virtual machine ID. \ No newline at end of file diff --git a/website/source/layouts/azurerm.erb b/website/source/layouts/azurerm.erb index 1006418cefca..0e0e60052a22 100644 --- a/website/source/layouts/azurerm.erb +++ b/website/source/layouts/azurerm.erb @@ -171,6 +171,10 @@ azurerm_availability_set +