diff --git a/azurerm/resource_arm_virtual_machine.go b/azurerm/resource_arm_virtual_machine.go index 1eb3a49999da..5dee7b87b5fa 100644 --- a/azurerm/resource_arm_virtual_machine.go +++ b/azurerm/resource_arm_virtual_machine.go @@ -412,6 +412,11 @@ func resourceArmVirtualMachine() *schema.Resource { "protocol": { Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "HTTP", + "HTTPS", + }, true), + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, "certificate_url": { Type: schema.TypeString, @@ -425,17 +430,28 @@ func resourceArmVirtualMachine() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + // TODO: should we make `pass` and `component` Optional + Defaulted? "pass": { Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "oobeSystem", + }, false), }, "component": { Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Microsoft-Windows-Shell-Setup", + }, false), }, "setting_name": { Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "AutoLogon", + "FirstLogonCommands", + }, false), }, "content": { Type: schema.TypeString, @@ -472,7 +488,7 @@ func resourceArmVirtualMachine() *schema.Resource { }, "key_data": { Type: schema.TypeString, - Optional: true, + Required: true, }, }, }, diff --git a/examples/virtual-machines/managed-disks/attaching-external-disks/1-dependencies.tf b/examples/virtual-machines/managed-disks/attaching-external-disks/1-dependencies.tf new file mode 100644 index 000000000000..7d9d5da5ef5c --- /dev/null +++ b/examples/virtual-machines/managed-disks/attaching-external-disks/1-dependencies.tf @@ -0,0 +1,33 @@ +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = "${var.location}" + tags = "${var.tags}" +} + +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.internal.id}" + private_ip_address_allocation = "dynamic" + } +} diff --git a/examples/virtual-machines/managed-disks/attaching-external-disks/2-virtual-machine.tf b/examples/virtual-machines/managed-disks/attaching-external-disks/2-virtual-machine.tf new file mode 100644 index 000000000000..460d041c2a0d --- /dev/null +++ b/examples/virtual-machines/managed-disks/attaching-external-disks/2-virtual-machine.tf @@ -0,0 +1,41 @@ +resource "azurerm_virtual_machine" "main" { + name = "${var.prefix}-vm" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] + vm_size = "Standard_F2" + + # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_os_disk_on_termination = true + + # This means the Data Disk Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_data_disks_on_termination = true + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "hostname" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } + + tags = "${var.tags}" +} diff --git a/examples/virtual-machines/managed-disks/attaching-external-disks/3-external-disks.tf b/examples/virtual-machines/managed-disks/attaching-external-disks/3-external-disks.tf new file mode 100644 index 000000000000..1c89d2c37f69 --- /dev/null +++ b/examples/virtual-machines/managed-disks/attaching-external-disks/3-external-disks.tf @@ -0,0 +1,17 @@ +resource "azurerm_managed_disk" "external" { + count = "${var.number_of_disks}" + name = "${var.prefix}-disk${count.index+1}" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + storage_account_type = "Standard_LRS" + create_option = "Empty" + disk_size_gb = "10" +} + +resource "azurerm_virtual_machine_data_disk_attachment" "external" { + count = "${var.number_of_disks}" + managed_disk_id = "${azurerm_managed_disk.external.*.id[count.index]}" + virtual_machine_id = "${azurerm_virtual_machine.main.id}" + lun = "${10+count.index}" + caching = "ReadWrite" +} diff --git a/examples/virtual-machines/managed-disks/attaching-external-disks/README.md b/examples/virtual-machines/managed-disks/attaching-external-disks/README.md new file mode 100644 index 000000000000..120cdc02a798 --- /dev/null +++ b/examples/virtual-machines/managed-disks/attaching-external-disks/README.md @@ -0,0 +1,14 @@ +## Example: Virtual Machine with Data Disks + +This example provisions a Virtual Machine with 2 Data Disks and an OS Disk all of which are Managed Disks. + +Notes: + +- The files involved in this example are split out to make it easier to read, however all of the resources could be combined into a single file if needed. + +### Variables + +* `prefix` - (Required) The Prefix used for all resources in this example. +* `location` - (Required) The Azure Region in which the resources in this example should exist. +* `tags` - (Optional) Any tags which should be assigned to the resources in this example. +* `number_of_disks` - (Optional) The number of Data Disks which should be attached, defaults to `2`. diff --git a/examples/virtual-machines/managed-disks/attaching-external-disks/variables.tf b/examples/virtual-machines/managed-disks/attaching-external-disks/variables.tf new file mode 100644 index 000000000000..98d5a62c3f03 --- /dev/null +++ b/examples/virtual-machines/managed-disks/attaching-external-disks/variables.tf @@ -0,0 +1,18 @@ +variable "prefix" { + description = "The Prefix used for all resources in this example" +} + +variable "location" { + description = "The Azure Region in which the resources in this example should exist" +} + +variable "tags" { + type = "map" + default = {} + description = "Any tags which should be assigned to the resources in this example" +} + +variable "number_of_disks" { + description = "The number of Data Disks which should be attached" + default = 2 +} diff --git a/examples/virtual-machines/managed-disks/basic-osdisk/1-dependencies.tf b/examples/virtual-machines/managed-disks/basic-osdisk/1-dependencies.tf new file mode 100644 index 000000000000..7d9d5da5ef5c --- /dev/null +++ b/examples/virtual-machines/managed-disks/basic-osdisk/1-dependencies.tf @@ -0,0 +1,33 @@ +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = "${var.location}" + tags = "${var.tags}" +} + +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.internal.id}" + private_ip_address_allocation = "dynamic" + } +} diff --git a/examples/virtual-machines/managed-disks/basic-osdisk/2-virtual-machine.tf b/examples/virtual-machines/managed-disks/basic-osdisk/2-virtual-machine.tf new file mode 100644 index 000000000000..62932ed9a14f --- /dev/null +++ b/examples/virtual-machines/managed-disks/basic-osdisk/2-virtual-machine.tf @@ -0,0 +1,41 @@ +resource "azurerm_virtual_machine" "test" { + name = "${var.prefix}-vm" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] + vm_size = "Standard_F2" + + # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_os_disk_on_termination = true + + # This means the Data Disk Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_data_disks_on_termination = true + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "hostname" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } + + tags = "${var.tags}" +} diff --git a/examples/virtual-machines/managed-disks/basic-osdisk/README.md b/examples/virtual-machines/managed-disks/basic-osdisk/README.md new file mode 100644 index 000000000000..8ae13ecd1c56 --- /dev/null +++ b/examples/virtual-machines/managed-disks/basic-osdisk/README.md @@ -0,0 +1,13 @@ +## Example: Basic Virtual Machine using a Managed Disk + +This example provisions a Virtual Machine with no Data Disks with a Managed Disk as the main OS Disk. + +Notes: + +- The files involved in this example are split out to make it easier to read, however all of the resources could be combined into a single file if needed. + +### Variables + +* `prefix` - (Required) The Prefix used for all resources in this example. +* `location` - (Required) The Azure Region in which the resources in this example should exist. +* `tags` - (Optional) Any tags which should be assigned to the resources in this example. diff --git a/examples/virtual-machines/managed-disks/basic-osdisk/variables.tf b/examples/virtual-machines/managed-disks/basic-osdisk/variables.tf new file mode 100644 index 000000000000..1bd6bc2dbce3 --- /dev/null +++ b/examples/virtual-machines/managed-disks/basic-osdisk/variables.tf @@ -0,0 +1,13 @@ +variable "prefix" { + description = "The Prefix used for all resources in this example" +} + +variable "location" { + description = "The Azure Region in which the resources in this example should exist" +} + +variable "tags" { + type = "map" + default = {} + description = "Any tags which should be assigned to the resources in this example" +} diff --git a/examples/virtual-machines/managed-disks/from-custom-image/1-dependencies.tf b/examples/virtual-machines/managed-disks/from-custom-image/1-dependencies.tf new file mode 100644 index 000000000000..7d9d5da5ef5c --- /dev/null +++ b/examples/virtual-machines/managed-disks/from-custom-image/1-dependencies.tf @@ -0,0 +1,33 @@ +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = "${var.location}" + tags = "${var.tags}" +} + +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.internal.id}" + private_ip_address_allocation = "dynamic" + } +} diff --git a/examples/virtual-machines/managed-disks/from-custom-image/2-virtual-machine.tf b/examples/virtual-machines/managed-disks/from-custom-image/2-virtual-machine.tf new file mode 100644 index 000000000000..953ec859ca8e --- /dev/null +++ b/examples/virtual-machines/managed-disks/from-custom-image/2-virtual-machine.tf @@ -0,0 +1,44 @@ +# we assume that this Custom Image already exists +data "azurerm_image" "custom" { + name = "${var.custom_image_name}" + resource_group_name = "${var.custom_image_resource_group_name}" +} + +resource "azurerm_virtual_machine" "test" { + name = "${var.prefix}-vm" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] + vm_size = "Standard_F2" + + # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_os_disk_on_termination = true + + # This means the Data Disk Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_data_disks_on_termination = true + + storage_image_reference { + id = "${data.azurerm_image.custom.id}" + } + + storage_os_disk { + name = "osdisk" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "hostname" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } + + tags = "${var.tags}" +} diff --git a/examples/virtual-machines/managed-disks/from-custom-image/README.md b/examples/virtual-machines/managed-disks/from-custom-image/README.md new file mode 100644 index 000000000000..8a85af6abdae --- /dev/null +++ b/examples/virtual-machines/managed-disks/from-custom-image/README.md @@ -0,0 +1,17 @@ +## Example: Virtual Machine with Managed Disks from a Custom Image + +This example provisions a Virtual Machine with Managed Disks from a Custom Image that already exists. + +Notes: + +- The files involved in this example are split out to make it easier to read, however all of the resources could be combined into a single file if needed. +- This example assumes the Custom Image specified exists - if it doesn't this example will fail. + +### Variables + +* `prefix` - (Required) The Prefix used for all resources in this example. +* `location` - (Required) The Azure Region in which the resources in this example should exist. +* `tags` - (Optional) Any tags which should be assigned to the resources in this example. + +* `custom_image_resource_group_name` - (Required) The name of the Resource Group in which the Custom Image exists. +* `custom_image_name` - (Required) The name of the Custom Image to provision this Virtual Machine from. diff --git a/examples/virtual-machines/managed-disks/from-custom-image/variables.tf b/examples/virtual-machines/managed-disks/from-custom-image/variables.tf new file mode 100644 index 000000000000..b4ade98af701 --- /dev/null +++ b/examples/virtual-machines/managed-disks/from-custom-image/variables.tf @@ -0,0 +1,21 @@ +variable "prefix" { + description = "The Prefix used for all resources in this example" +} + +variable "location" { + description = "The Azure Region in which the resources in this example should exist" +} + +variable "tags" { + type = "map" + default = {} + description = "Any tags which should be assigned to the resources in this example" +} + +variable "custom_image_resource_group_name" { + description = "The name of the Resource Group in which the Custom Image exists." +} + +variable "custom_image_name" { + description = "The name of the Custom Image to provision this Virtual Machine from." +} diff --git a/examples/virtual-machines/provisioners/linux/1-dependencies.tf b/examples/virtual-machines/provisioners/linux/1-dependencies.tf new file mode 100644 index 000000000000..9e50341b7747 --- /dev/null +++ b/examples/virtual-machines/provisioners/linux/1-dependencies.tf @@ -0,0 +1,47 @@ +locals { + virtual_machine_name = "${var.prefix}-vm" + admin_username = "testadmin" + admin_password = "Password1234!" +} + +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = "${var.location}" + tags = "${var.tags}" +} + +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_public_ip" "main" { + name = "${var.prefix}-publicip" + resource_group_name = "${azurerm_resource_group.main.name}" + location = "${azurerm_resource_group.main.location}" + public_ip_address_allocation = "static" + tags = "${var.tags}" +} + +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + + ip_configuration { + name = "configuration" + subnet_id = "${azurerm_subnet.internal.id}" + private_ip_address_allocation = "dynamic" + public_ip_address_id = "${azurerm_public_ip.main.id}" + } +} diff --git a/examples/virtual-machines/provisioners/linux/2-virtual-machine.tf b/examples/virtual-machines/provisioners/linux/2-virtual-machine.tf new file mode 100644 index 000000000000..3507de92b4c7 --- /dev/null +++ b/examples/virtual-machines/provisioners/linux/2-virtual-machine.tf @@ -0,0 +1,52 @@ +resource "azurerm_virtual_machine" "example" { + name = "${local.virtual_machine_name}" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] + vm_size = "Standard_F2" + + # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_os_disk_on_termination = true + + # This means the Data Disk Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_data_disks_on_termination = true + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "${var.prefix}-osdisk" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "${local.virtual_machine_name}" + admin_username = "${local.admin_username}" + admin_password = "${local.admin_password}" + } + + os_profile_linux_config { + disable_password_authentication = false + } + + provisioner "remote-exec" { + connection { + user = "${local.admin_username}" + password = "${local.admin_password}" + } + + inline = [ + "ls -la", + ] + } + + tags = "${var.tags}" +} diff --git a/examples/virtual-machines/provisioners/linux/README.md b/examples/virtual-machines/provisioners/linux/README.md new file mode 100644 index 000000000000..9d9b03d3073c --- /dev/null +++ b/examples/virtual-machines/provisioners/linux/README.md @@ -0,0 +1,11 @@ +## Example: using Provisioner over SSH to a Linux Virtual Machine + +This example provisions a Virtual Machine running Ubuntu 16.04-LTS with a Public IP Address and [runs a `remote-exec` provisioner](https://www.terraform.io/docs/provisioners/remote-exec.html) over SSH. + +The files involved in this example are split out to make it easier to read, however all of the resources could be combined into a single file if needed. + +### Variables + +* `prefix` - (Required) The Prefix used for all resources in this example. +* `location` - (Required) The Azure Region in which the resources in this example should exist. +* `tags` - (Optional) Any tags which should be assigned to the resources in this example. diff --git a/examples/virtual-machines/provisioners/linux/variables.tf b/examples/virtual-machines/provisioners/linux/variables.tf new file mode 100644 index 000000000000..1bd6bc2dbce3 --- /dev/null +++ b/examples/virtual-machines/provisioners/linux/variables.tf @@ -0,0 +1,13 @@ +variable "prefix" { + description = "The Prefix used for all resources in this example" +} + +variable "location" { + description = "The Azure Region in which the resources in this example should exist" +} + +variable "tags" { + type = "map" + default = {} + description = "Any tags which should be assigned to the resources in this example" +} diff --git a/examples/virtual-machines/provisioners/windows/1-dependencies.tf b/examples/virtual-machines/provisioners/windows/1-dependencies.tf new file mode 100644 index 000000000000..9e50341b7747 --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/1-dependencies.tf @@ -0,0 +1,47 @@ +locals { + virtual_machine_name = "${var.prefix}-vm" + admin_username = "testadmin" + admin_password = "Password1234!" +} + +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = "${var.location}" + tags = "${var.tags}" +} + +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_public_ip" "main" { + name = "${var.prefix}-publicip" + resource_group_name = "${azurerm_resource_group.main.name}" + location = "${azurerm_resource_group.main.location}" + public_ip_address_allocation = "static" + tags = "${var.tags}" +} + +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + + ip_configuration { + name = "configuration" + subnet_id = "${azurerm_subnet.internal.id}" + private_ip_address_allocation = "dynamic" + public_ip_address_id = "${azurerm_public_ip.main.id}" + } +} diff --git a/examples/virtual-machines/provisioners/windows/2-certificates.tf b/examples/virtual-machines/provisioners/windows/2-certificates.tf new file mode 100644 index 000000000000..29a09d75cad8 --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/2-certificates.tf @@ -0,0 +1,78 @@ +data "azurerm_client_config" "current" {} + +resource "azurerm_key_vault" "main" { + name = "${var.prefix}keyvault" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + + enabled_for_deployment = true + enabled_for_template_deployment = true + + sku { + name = "standard" + } + + access_policy { + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + object_id = "${data.azurerm_client_config.current.service_principal_object_id}" + + certificate_permissions = [ + "create", + "delete", + "get", + "update", + ] + + key_permissions = [] + secret_permissions = [] + } + + tags = "${var.tags}" +} + +resource "azurerm_key_vault_certificate" "main" { + name = "${local.virtual_machine_name}-cert" + vault_uri = "${azurerm_key_vault.main.vault_uri}" + + certificate_policy { + issuer_parameters { + name = "Self" + } + + key_properties { + exportable = true + key_size = 2048 + key_type = "RSA" + reuse_key = true + } + + lifetime_action { + action { + action_type = "AutoRenew" + } + + trigger { + days_before_expiry = 30 + } + } + + secret_properties { + content_type = "application/x-pkcs12" + } + + x509_certificate_properties { + key_usage = [ + "cRLSign", + "dataEncipherment", + "digitalSignature", + "keyAgreement", + "keyCertSign", + "keyEncipherment", + ] + + subject = "CN=${local.virtual_machine_name}" + validity_in_months = 12 + } + } +} diff --git a/examples/virtual-machines/provisioners/windows/3-virtual-machine.tf b/examples/virtual-machines/provisioners/windows/3-virtual-machine.tf new file mode 100644 index 000000000000..8bb6691078f3 --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/3-virtual-machine.tf @@ -0,0 +1,91 @@ +locals { + custom_data_params = "Param($ComputerName = \"${local.virtual_machine_name}\")" + custom_data_content = "${local.custom_data_params} ${file("./files/winrm.ps1")}" +} + +resource "azurerm_virtual_machine" "example" { + name = "${local.virtual_machine_name}" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] + vm_size = "Standard_F2" + + # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_os_disk_on_termination = true + + # This means the Data Disk Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_data_disks_on_termination = true + + storage_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + + storage_os_disk { + name = "${var.prefix}-osdisk" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "${local.virtual_machine_name}" + admin_username = "${local.admin_username}" + admin_password = "${local.admin_password}" + custom_data = "${local.custom_data_content}" + } + + os_profile_secrets { + source_vault_id = "${azurerm_key_vault.main.id}" + + vault_certificates { + certificate_url = "${azurerm_key_vault_certificate.main.secret_id}" + certificate_store = "My" + } + } + + os_profile_windows_config { + provision_vm_agent = true + enable_automatic_upgrades = true + + # Auto-Login's required to configure WinRM + additional_unattend_config { + pass = "oobeSystem" + component = "Microsoft-Windows-Shell-Setup" + setting_name = "AutoLogon" + content = "${local.admin_password}true1${local.admin_username}" + } + + # Unattend config is to enable basic auth in WinRM, required for the provisioner stage. + additional_unattend_config { + pass = "oobeSystem" + component = "Microsoft-Windows-Shell-Setup" + setting_name = "FirstLogonCommands" + content = "${file("./files/FirstLogonCommands.xml")}" + } + } + + provisioner "remote-exec" { + connection { + user = "${local.admin_username}" + password = "${local.admin_password}" + port = 5986 + https = true + timeout = "10m" + + # NOTE: if you're using a real certificate, rather than a self-signed one, you'll want this set to `false`/to remove this. + insecure = true + } + + inline = [ + "cd C:\\Windows", + "dir", + ] + } + + tags = "${var.tags}" +} diff --git a/examples/virtual-machines/provisioners/windows/README.md b/examples/virtual-machines/provisioners/windows/README.md new file mode 100644 index 000000000000..3041a495a92d --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/README.md @@ -0,0 +1,14 @@ +## Example: Running commands via WinRM on a Windows Virtual Machine + +This example provisions a Virtual Machine running Windows Server 2016 with a Public IP Address and [runs a `remote-exec` provisioner](https://www.terraform.io/docs/provisioners/remote-exec.html) via WinRM. + +Notes: + +- The files involved in this example are split out to make it easier to read, however all of the resources could be combined into a single file if needed. +- The certificate used for WinRM is generated by Azure KeyVault and then installed on the VM; as such the certificate in this example is self-signed, which may not be desirable in a real-world environment. + +### Variables + +* `prefix` - (Required) The Prefix used for all resources in this example. +* `location` - (Required) The Azure Region in which the resources in this example should exist. +* `tags` - (Optional) Any tags which should be assigned to the resources in this example. diff --git a/examples/virtual-machines/provisioners/windows/files/FirstLogonCommands.xml b/examples/virtual-machines/provisioners/windows/files/FirstLogonCommands.xml new file mode 100644 index 000000000000..fead3000350c --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/files/FirstLogonCommands.xml @@ -0,0 +1,17 @@ + + + cmd /c "mkdir C:\terraform" + Create the Terraform working directory + 11 + + + cmd /c "copy C:\AzureData\CustomData.bin C:\terraform\winrm.ps1" + Move the CustomData file to the working directory + 12 + + + powershell.exe -sta -ExecutionPolicy Unrestricted -file C:\terraform\winrm.ps1 + Execute the WinRM enabling script + 13 + + diff --git a/examples/virtual-machines/provisioners/windows/files/winrm.ps1 b/examples/virtual-machines/provisioners/windows/files/winrm.ps1 new file mode 100644 index 000000000000..f1e189cdbf99 --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/files/winrm.ps1 @@ -0,0 +1,11 @@ +Write-Host "Obtaining the Thumbprint of the Certificate from KeyVault" +$Thumbprint = (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match "$ComputerName"}).Thumbprint + +Write-Host "Enable HTTPS in WinRM.." +winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=`"$ComputerName`"; CertificateThumbprint=`"$Thumbprint`"}" + +Write-Host "Enabling Basic Authentication.." +winrm set winrm/config/service/Auth "@{Basic=`"true`"}" + +Write-Host "Open Firewall Ports" +netsh advfirewall firewall add rule name="Windows Remote Management (HTTPS-In)" dir=in action=allow protocol=TCP localport=5986 diff --git a/examples/virtual-machines/provisioners/windows/variables.tf b/examples/virtual-machines/provisioners/windows/variables.tf new file mode 100644 index 000000000000..1bd6bc2dbce3 --- /dev/null +++ b/examples/virtual-machines/provisioners/windows/variables.tf @@ -0,0 +1,13 @@ +variable "prefix" { + description = "The Prefix used for all resources in this example" +} + +variable "location" { + description = "The Azure Region in which the resources in this example should exist" +} + +variable "tags" { + type = "map" + default = {} + description = "Any tags which should be assigned to the resources in this example" +} diff --git a/examples/virtual-machines/unmanaged-disks/1-dependencies.tf b/examples/virtual-machines/unmanaged-disks/1-dependencies.tf new file mode 100644 index 000000000000..28813415ea5e --- /dev/null +++ b/examples/virtual-machines/unmanaged-disks/1-dependencies.tf @@ -0,0 +1,5 @@ +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = "${var.location}" + tags = "${var.tags}" +} diff --git a/examples/virtual-machines/unmanaged-disks/2-network.tf b/examples/virtual-machines/unmanaged-disks/2-network.tf new file mode 100644 index 000000000000..2876cf658987 --- /dev/null +++ b/examples/virtual-machines/unmanaged-disks/2-network.tf @@ -0,0 +1,27 @@ +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + tags = "${var.tags}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.internal.id}" + private_ip_address_allocation = "dynamic" + } +} diff --git a/examples/virtual-machines/unmanaged-disks/3-storage-account.tf b/examples/virtual-machines/unmanaged-disks/3-storage-account.tf new file mode 100644 index 000000000000..d87baef1ba1c --- /dev/null +++ b/examples/virtual-machines/unmanaged-disks/3-storage-account.tf @@ -0,0 +1,15 @@ +resource "azurerm_storage_account" "main" { + name = "${var.prefix}stor" + resource_group_name = "${azurerm_resource_group.main.name}" + location = "${azurerm_resource_group.main.location}" + account_tier = "Standard" + account_replication_type = "LRS" + tags = "${var.tags}" +} + +resource "azurerm_storage_container" "disks" { + name = "vhds" + resource_group_name = "${azurerm_resource_group.main.name}" + storage_account_name = "${azurerm_storage_account.main.name}" + container_access_type = "private" +} diff --git a/examples/virtual-machines/unmanaged-disks/3-virtual-machine.tf b/examples/virtual-machines/unmanaged-disks/3-virtual-machine.tf new file mode 100644 index 000000000000..3ca475aaff53 --- /dev/null +++ b/examples/virtual-machines/unmanaged-disks/3-virtual-machine.tf @@ -0,0 +1,53 @@ +locals { + storage_account_base_uri = "${azurerm_storage_account.main.primary_blob_endpoint}${azurerm_storage_container.disks.name}" +} + +resource "azurerm_virtual_machine" "example" { + name = "${var.prefix}-vm" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] + vm_size = "Standard_F2" + tags = "${var.tags}" + + # This means the OS Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_os_disk_on_termination = true + + # This means the Data Disk Disk will be deleted when Terraform destroys the Virtual Machine + # NOTE: This may not be optimal in all cases. + delete_data_disks_on_termination = true + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "osdisk" + vhd_uri = "${local.storage_account_base_uri}/osdisk.vhd" + caching = "ReadWrite" + create_option = "FromImage" + } + + # Optional data disks + storage_data_disk { + name = "datadisk1" + vhd_uri = "${local.storage_account_base_uri}/datadisk1.vhd" + disk_size_gb = "1023" + create_option = "Empty" + lun = 0 + } + + os_profile { + computer_name = "hostname" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } +} diff --git a/examples/virtual-machines/unmanaged-disks/README.md b/examples/virtual-machines/unmanaged-disks/README.md new file mode 100644 index 000000000000..755b23f64925 --- /dev/null +++ b/examples/virtual-machines/unmanaged-disks/README.md @@ -0,0 +1,13 @@ +## Example: Virtual Machine with Unmanaged Disks + +This example provisions a Virtual Machine with Unmanaged Disks, with one OS Disk and one Data Disk. + +Notes: + +- The files involved in this example are split out to make it easier to read, however all of the resources could be combined into a single file if needed. + +### Variables + +* `prefix` - (Required) The Prefix used for all resources in this example. +* `location` - (Required) The Azure Region in which the resources in this example should exist. +* `tags` - (Optional) Any tags which should be assigned to the resources in this example. diff --git a/examples/virtual-machines/unmanaged-disks/variables.tf b/examples/virtual-machines/unmanaged-disks/variables.tf new file mode 100644 index 000000000000..1bd6bc2dbce3 --- /dev/null +++ b/examples/virtual-machines/unmanaged-disks/variables.tf @@ -0,0 +1,13 @@ +variable "prefix" { + description = "The Prefix used for all resources in this example" +} + +variable "location" { + description = "The Azure Region in which the resources in this example should exist" +} + +variable "tags" { + type = "map" + default = {} + description = "Any tags which should be assigned to the resources in this example" +} diff --git a/website/docs/r/virtual_machine.html.markdown b/website/docs/r/virtual_machine.html.markdown index 8614fc85adc7..838843edf1b3 100644 --- a/website/docs/r/virtual_machine.html.markdown +++ b/website/docs/r/virtual_machine.html.markdown @@ -3,63 +3,60 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_virtual_machine" sidebar_current: "docs-azurerm-resource-compute-virtual-machine-x" description: |- - Create a Virtual Machine. + Manages a Virtual Machine. --- # azurerm_virtual_machine -Create a virtual machine. +Manages a Virtual Machine. ~> **NOTE:** Data Disks can be attached either directly on the `azurerm_virtual_machine` resource, or using the `azurerm_virtual_machine_data_disk_attachment` resource - but the two cannot be used together. If both are used against the same Virtual Machine, spurious changes will occur. -## Example Usage with Managed Disks and Azure Platform Images (Recommended) +## Example Usage (from an Azure Platform Image) + +This example provisions a Virtual Machine with Managed Disks. Other examples of the `azurerm_virtual_machine` resource can be found in [the `./examples/virtual-machines` directory within the Github Repository](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/virtual-machines) ```hcl -resource "azurerm_resource_group" "test" { - name = "acctestRG" +variable "prefix" { + default = "tfvmex" +} + +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" location = "West US 2" } -resource "azurerm_virtual_network" "test" { - name = "acctvn" +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" } -resource "azurerm_subnet" "test" { - name = "acctsub" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = "${azurerm_resource_group.main.name}" + virtual_network_name = "${azurerm_virtual_network.main.name}" address_prefix = "10.0.2.0/24" } -resource "azurerm_network_interface" "test" { - name = "acctni" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +resource "azurerm_network_interface" "main" { + name = "${var.prefix}-nic" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" ip_configuration { name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + subnet_id = "${azurerm_subnet.internal.id}" private_ip_address_allocation = "dynamic" } } -resource "azurerm_managed_disk" "test" { - name = "datadisk_existing" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "1023" -} - -resource "azurerm_virtual_machine" "test" { - name = "acctvm" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_interface_ids = ["${azurerm_network_interface.test.id}"] +resource "azurerm_virtual_machine" "main" { + name = "${var.prefix}-vm" + location = "${azurerm_resource_group.main.location}" + resource_group_name = "${azurerm_resource_group.main.name}" + network_interface_ids = ["${azurerm_network_interface.main.id}"] vm_size = "Standard_DS1_v2" # Uncomment this line to delete the OS disk automatically when deleting the VM @@ -82,23 +79,6 @@ resource "azurerm_virtual_machine" "test" { managed_disk_type = "Standard_LRS" } - # Optional data disks - storage_data_disk { - name = "datadisk_new" - managed_disk_type = "Standard_LRS" - create_option = "Empty" - lun = 0 - disk_size_gb = "1023" - } - - storage_data_disk { - name = "${azurerm_managed_disk.test.name}" - managed_disk_id = "${azurerm_managed_disk.test.id}" - create_option = "Attach" - lun = 1 - disk_size_gb = "${azurerm_managed_disk.test.disk_size_gb}" - } - os_profile { computer_name = "hostname" admin_username = "testadmin" @@ -115,409 +95,254 @@ resource "azurerm_virtual_machine" "test" { } ``` -## Example Usage with Managed Disks and Custom Images (Recommended) +## Argument Reference -```hcl -#Assume that custom image has been already created in the 'customimage' resource group -data "azurerm_resource_group" "image" { - name = "customimage" -} +The following arguments are supported: -data "azurerm_image" "image" { - name = "myCustomImage" - resource_group_name = "${data.azurerm_resource_group.image.name}" -} +* `name` - (Required) Specifies the name of the Virtual Machine. Changing this forces a new resource to be created. -resource "azurerm_resource_group" "test" { - name = "acctestRG" - location = "West US 2" -} +* `resource_group_name` - (Required) Specifies the name of the Resource Group in which the Virtual Machine should exist. Changing this forces a new resource to be created. -resource "azurerm_virtual_network" "test" { - name = "acctvn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +* `location` - (Required) Specifies the Azure Region where the Virtual Machine exists. Changing this forces a new resource to be created. -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" -} +* `network_interface_ids` - (Required) A list of Network Interface ID's which should be associated with the Virtual Machine. -resource "azurerm_network_interface" "test" { - name = "acctni" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +* `os_profile_linux_config` - (Required, when a Linux machine) A `os_profile_linux_config` block. - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "dynamic" - } -} +* `os_profile_windows_config` - (Required, when a Windows machine) A `os_profile_windows_config` block. -resource "azurerm_managed_disk" "test" { - name = "datadisk_existing" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "1023" -} +* `vm_size` - (Required) Specifies the [size of the Virtual Machine](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-size-specs/). -resource "azurerm_virtual_machine" "test" { - name = "acctvm" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - vm_size = "Standard_DS1_v2" +--- - # Uncomment this line to delete the OS disk automatically when deleting the VM - # delete_os_disk_on_termination = true +* `availability_set_id` - (Optional) The ID of the Availability Set in which the Virtual Machine should exist. Changing this forces a new resource to be created. - # Uncomment this line to delete the data disks automatically when deleting the VM - # delete_data_disks_on_termination = true +* `boot_diagnostics` - (Optional) A `boot_diagnostics` block. - storage_image_reference { - id="${data.azurerm_image.image.id}" - } +* `delete_os_disk_on_termination` - (Optional) Should the OS Disk (either the Managed Disk / VHD Blob) be deleted when the Virtual Machine is destroyed? Defaults to `false`. - storage_os_disk { - name = "myosdisk1" - caching = "ReadWrite" - create_option = "FromImage" - managed_disk_type = "Standard_LRS" - } +* `delete_data_disks_on_termination` - (Optional) Should the Data Disks (either the Managed Disks / VHD Blobs) be deleted when the Virtual Machine is destroyed? Defaults to `false`. - # Optional data disks - storage_data_disk { - name = "datadisk_new" - managed_disk_type = "Standard_LRS" - create_option = "Empty" - lun = 0 - disk_size_gb = "1023" - } +* `identity` - (Optional) A `identity` block. - storage_data_disk { - name = "${azurerm_managed_disk.test.name}" - managed_disk_id = "${azurerm_managed_disk.test.id}" - create_option = "Attach" - lun = 1 - disk_size_gb = "${azurerm_managed_disk.test.disk_size_gb}" - } +* `license_type` - (Optional) Specifies the BYOL Type for this Virtual Machine. This is only applicable to Windows Virtual Machines. Possible values are `Windows_Client` and `Windows_Server`. - os_profile { - computer_name = "hostname" - admin_username = "testadmin" - admin_password = "Password1234!" - } +* `os_profile` - (Optional) An `os_profile` block. Required when `create_option` in the `storage_os_disk` block is set to `FromImage`. - os_profile_linux_config { - disable_password_authentication = false - } +* `os_profile_secrets` - (Optional) One or more `os_profile_secrets` blocks. - tags { - environment = "staging" - } -} -``` +* `plan` - (Optional) A `plan` block. -## Example Usage with Unmanaged Disks +* `primary_network_interface_id` - (Optional) The ID of the Network Interface (which must be attached to the Virtual Machine) which should be the Primary Network Interface for this Virtual Machine. -```hcl -resource "azurerm_resource_group" "test" { - name = "acctestRG" - location = "West US" -} +* `storage_data_disk` - (Optional) One or more `storage_data_disk` blocks. -resource "azurerm_virtual_network" "test" { - name = "acctvn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +~> **Please Note:** Data Disks can also be attached either using this block or [the `azurerm_virtual_machine_data_disk_attachment` resource](virtual_machine_data_disk_attachment.html) - but not both. -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" -} +* `storage_image_reference` - (Optional) A `storage_image_reference` block. -resource "azurerm_network_interface" "test" { - name = "acctni" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +* `storage_os_disk` - (Required) A `storage_os_disk` block. - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "dynamic" - } -} +* `tags` - (Optional) A mapping of tags to assign to the Virtual Machine. -resource "azurerm_storage_account" "test" { - name = "accsa" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" +* `zones` - (Optional) A list of a single item of the Availability Zone which the Virtual Machine should be allocated in. - tags { - environment = "staging" - } -} +-> **Please Note**: Availability Zones are [in Preview and only supported in several regions at this time](https://docs.microsoft.com/en-us/azure/availability-zones/az-overview) - as such you must be opted into the Preview to use this functionality. You can [opt into the Availability Zones Preview in the Azure Portal](http://aka.ms/azenroll). -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" -} +For more information on the different example configurations, please check out the [Azure documentation](https://docs.microsoft.com/en-gb/rest/api/compute/virtualmachines/createorupdate#examples) -resource "azurerm_virtual_machine" "test" { - name = "acctvm" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - vm_size = "Standard_F2" +--- - # Uncomment this line to delete the OS disk automatically when deleting the VM - # delete_os_disk_on_termination = true +A `additional_unattend_config` block supports the following: - # Uncomment this line to delete the data disks automatically when deleting the VM - # delete_data_disks_on_termination = true +* `pass` - (Required) Specifies the name of the pass that the content applies to. The only allowable value is `oobeSystem`. - storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } +* `component` - (Required) Specifies the name of the component to configure with the added content. The only allowable value is `Microsoft-Windows-Shell-Setup`. - 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" - } +* `setting_name` - (Required) Specifies the name of the setting to which the content applies. Possible values are: `FirstLogonCommands` and `AutoLogon`. - # Optional data disks - storage_data_disk { - name = "datadisk0" - vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/datadisk0.vhd" - disk_size_gb = "1023" - create_option = "Empty" - lun = 0 - } +* `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 { - computer_name = "hostname" - admin_username = "testadmin" - admin_password = "Password1234!" - } +--- - os_profile_linux_config { - disable_password_authentication = false - } +A `boot_diagnostics` block supports the following: - tags { - environment = "staging" - } -} -``` +* `enabled` - (Required) Should Boot Diagnostics be enabled for this Virtual Machine? -## Argument Reference +* `storage_uri` - (Required) The Storage Account's Blob Endpoint which should hold the virtual machine's diagnostic files. -The following arguments are supported: +~> **NOTE:** This needs to be the root of a Storage Account and not a Storage Container. -* `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 Availability Set in which to create the virtual machine -* `boot_diagnostics` - (Optional) A boot diagnostics profile block as referenced below. -* `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. -* `delete_os_disk_on_termination` - (Optional) Flag to enable deletion of the OS disk VHD blob or managed disk when the VM is deleted, defaults to `false` -* `storage_data_disk` - (Optional) A list of Storage Data disk blocks as referenced below. +--- -~> **Please Note:** Data Disks can also be attached either using this block or [the `azurerm_virtual_machine_data_disk_attachment` resource](virtual_machine_data_disk_attachment.html) - but not both. +A `identity` block supports the following: -* `delete_data_disks_on_termination` - (Optional) Flag to enable deletion of storage data disk VHD blobs or managed disks when the VM is deleted, defaults to `false` -* `os_profile` - (Optional) An OS Profile block as documented below. Required when `create_option` in the `storage_os_disk` block is set to `FromImage`. -* `identity` - (Optional) An identity block as documented below. +* `type` - (Required) The Managed Service Identity Type of this Virtual Machine. Possible values are `SystemAssigned` (where Azure will generate a Service Principal for you) and `UserAssigned` (where you can specify the Service Principal ID's) to be used by this Virtual Machine using the `identity_ids` field. -* `license_type` - (Optional, when a Windows machine) Specifies the Windows OS license type. If supplied, the only allowed values are `Windows_Client` and `Windows_Server`. -* `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. -* `primary_network_interface_id` - (Optional) Specifies the resource ID for the primary network interface associated with the virtual machine. -* `tags` - (Optional) A mapping of tags to assign to the resource. -* `zones` - (Optional) A collection containing the availability zone to allocate the Virtual Machine in. +-> **NOTE:** Managed Service Identity previously required the installation of a VM Extension, but this information [is now available via the Azure Instance Metadata Service](https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/overview#how-does-it-work). --> **Please Note**: Availability Zones are [in Preview and only supported in several regions at this time](https://docs.microsoft.com/en-us/azure/availability-zones/az-overview) - as such you must be opted into the Preview to use this functionality. You can [opt into the Availability Zones Preview in the Azure Portal](http://aka.ms/azenroll). +~> **NOTE:** When `type` is set to `SystemAssigned`, identity the Principal ID can be retrieved after the virtual machine has been created. See [documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/overview) for more information. + +* `identity_ids` - (Optional) Specifies a list of user managed identity ids to be assigned to the VM. Required if `type` is `UserAssigned`. + +--- + +A `os_profile` block supports the following: + +* `computer_name` - (Required) Specifies the name of the Virtual Machine. + +* `admin_username` - (Required) Specifies the name of the local administrator account. -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) +* `admin_password` - (Required for Windows, Optional for Linux) The password associated with the local administrator account. -`Plan` supports the following: +-> **NOTE:** If using Linux, it may be preferable to use SSH Key authentication (available in the `os_profile_linux_config` block) instead of password authentication. + +~> **NOTE:** `admin_password` must be between 6-72 characters long and must satisfy at least 3 of password complexity requirements from the following: +1. Contains an uppercase character +2. Contains a lowercase character +3. Contains a numeric digit +4. Contains a special character + +* `custom_data` - (Optional) Specifies custom data to supply to the machine. On Linux-based systems, this can be used as a cloud-init script. On other systems, this will be copied as a file on disk. Internally, Terraform will base64 encode this value before sending it to the API. The maximum length of the binary array is 65535 bytes. + +--- + +A `os_profile_linux_config` block supports the following: + +* `disable_password_authentication` - (Required) Specifies whether password authentication should be disabled. If set to `false`, an `admin_password` must be specified. + +* `ssh_keys` - (Optional) One or more `ssh_keys` blocks. This field is required if `disable_password_authentication` is set to `true`. + +--- + +A `os_profile_secrets` block supports the following: + +* `source_vault_id` - (Required) Specifies the ID of the Key Vault to use. + +* `vault_certificates` - (Required) One or more `vault_certificates` blocks. + +--- + +A `os_profile_windows_config` block supports the following: + +* `provision_vm_agent` - (Optional) Should the Azure Virtual Machine Guest Agent be installed on this Virtual Machine? Defaults to `false`. + +-> **NOTE:** This is different from the Default value used for this field within Azure. + +* `enable_automatic_upgrades` - (Optional) Are automatic updates enabled on this Virtual Machine? Defaults to `false.` + +* `timezone` - (Optional) Specifies the time zone of the virtual machine, [the possible values are defined here](http://jackstromberg.com/2017/01/list-of-time-zones-consumed-by-azure/). + +* `winrm` - (Optional) One or more `winrm` block. + +* `additional_unattend_config` - (Optional) A `additional_unattend_config` block. + +--- + +A `plan` block supports the following: * `name` - (Required) Specifies the name of the image from the marketplace. + * `publisher` - (Required) Specifies the publisher of the image. + * `product` - (Required) Specifies the product of the image from the marketplace. -`boot_diagnostics` supports the following: +--- -* `enabled`: (Required) Whether to enable boot diagnostics for the virtual machine. -* `storage_uri`: (Required) Blob endpoint for the storage account to hold the virtual machine's diagnostic files. This must be the root of a storage account, and not a storage container. +A `ssh_keys` block supports the following: -`storage_image_reference` supports the following: +* `key_data` - (Required) The Public SSH Key which should be written to the `path` defined above. -* `id` - (Optional) Specifies the ID of the (custom) image to use to create the virtual -machine, for example: +-> **NOTE:** Rather than defining this in-line you can source this from a local file using [the `file` interpolation function](https://www.terraform.io/docs/configuration/interpolation.html#file_path_) - for example `key_data = "${file("~/.ssh/id_rsa.pub")}"`. -```hcl +* `path` - (Required) The path of the destination file on the virtual machine + +-> **NOTE:** Due to a limitation in the Azure VM Agent the only allowed `path` is `/home/{username}/.ssh/authorized_keys`. -resource "azurerm_image" "test" { - name = "test" - ... -} -resource "azurerm_virtual_machine" "test" { - name = "test" - ... +--- - storage_image_reference { - id = "${azurerm_image.test.id}" - } +A `storage_image_reference` block supports the following: -... -``` +This block provisions the Virtual Machine from one of two sources: an Azure Platform Image (e.g. Ubuntu/Windows Server) or a Custom Image. + +To provision from an Azure Platform Image, the following fields are applicable: + +* `publisher` - (Required) Specifies the publisher of the image used to create the virtual machine. Changing this forces a new resource to be created. + +* `offer` - (Required) Specifies the offer of the image used to create the virtual machine. Changing this forces a new resource to be created. + +* `sku` - (Required) Specifies the SKU of the image used to create the virtual machine. Changing this forces a new resource to be created. -* `publisher` - (Required, when not using image resource) Specifies the publisher of the image used to create the virtual machine. Changing this forces a new resource to be created. -* `offer` - (Required, when not using image resource) Specifies the offer of the image used to create the virtual machine. Changing this forces a new resource to be created. -* `sku` - (Required, when not using image resource) Specifies the SKU of the image used to create the virtual machine. Changing this forces a new resource to be created. * `version` - (Optional) Specifies the version of the image used to create the virtual machine. Changing this forces a new resource to be created. -`storage_os_disk` supports the following: - -* `name` - (Required) Specifies the disk name. -* `vhd_uri` - (Optional) Specifies the vhd uri. Changing this forces a new resource to be created. Cannot be used with managed disks. -* `managed_disk_type` - (Optional) Specifies the type of managed disk to create. Value you must be either `Standard_LRS` or `Premium_LRS`. Cannot be used when `vhd_uri` is specified. -* `managed_disk_id` - (Optional) Specifies an existing managed disk to use by id. Can only be used when `create_option` is `Attach`. Cannot be used when `vhd_uri` is specified. -* `create_option` - (Required) Specifies how the virtual machine should be created. Possible values are `Attach` (managed disks only) and `FromImage`. -* `caching` - (Optional) Specifies the caching requirements. -* `image_uri` - (Optional) Specifies the image_uri in the form publisherName:offer:skus:version. `image_uri` can also specify the [VHD uri](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-cli-deploy-templates/#create-a-custom-vm-image) of a custom VM image to clone. When cloning a custom disk image the `os_type` documented below becomes required. -* `os_type` - (Optional) Specifies the operating system Type, valid values are windows, linux. -* `disk_size_gb` - (Optional) Specifies the size of the os disk in gigabytes. -* `write_accelerator_enabled` - (Optional) Specifies if Write Accelerator is enabled on the disk. This can only be enabled on `Premium_LRS` managed disks with no caching and [M-Series VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/how-to-enable-write-accelerator). Defaults to `false`. +To provision a Custom Image, the following fields are applicable: + +* `id` - (Required) Specifies the ID of the Custom Image which the Virtual Machine should be created from. Changing this forces a new resource to be created. + +-> **NOTE:** An example of how to use this is available within [the `./examples/virtual-machines/managed-disks/from-custom-image` directory within the Github Repository](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/virtual-machines/managed-disks/from-custom-image) + +--- -`storage_data_disk` supports the following: +A `storage_data_disk` block supports the following: + +~> **NOTE:** Data Disks can also be attached either using this block or [the `azurerm_virtual_machine_data_disk_attachment` resource](virtual_machine_data_disk_attachment.html) - but not both. + +* `name` - (Required) The name of the Data Disk. + +* `caching` - (Optional) Specifies the caching requirements for the Data Disk. Possible values include `None`, `ReadOnly` and `ReadWrite`. -* `name` - (Required) Specifies the name of the data disk. -* `vhd_uri` - (Optional) Specifies the uri of the location in storage where the vhd for the virtual machine should be placed. Cannot be used with managed disks. -* `managed_disk_type` - (Optional) Specifies the type of managed disk to create. Value you must be either `Standard_LRS` or `Premium_LRS`. Cannot be used when `vhd_uri` is specified. -* `managed_disk_id` - (Optional) Specifies an existing managed disk to use by id. Can only be used when `create_option` is `Attach`. Cannot be used when `vhd_uri` is specified. * `create_option` - (Required) Specifies how the data disk should be created. Possible values are `Attach`, `FromImage` and `Empty`. + * `disk_size_gb` - (Required) Specifies the size of the data disk in gigabytes. -* `caching` - (Optional) Specifies the caching requirements. -* `lun` - (Required) Specifies the logical unit number of the data disk. + +* `lun` - (Required) Specifies the logical unit number of the data disk. This needs to be unique within all the Data Disks on the Virtual Machine. + * `write_accelerator_enabled` - (Optional) Specifies if Write Accelerator is enabled on the disk. This can only be enabled on `Premium_LRS` managed disks with no caching and [M-Series VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/how-to-enable-write-accelerator). Defaults to `false`. -`os_profile` supports the following: +The following properties apply when using Managed Disks: -* `computer_name` - (Required) Specifies the name of the virtual machine. -* `admin_username` - (Required) Specifies the name of the administrator account. -* `admin_password` - (Required for Windows, Optional for Linux) Specifies the password of the administrator account. -* `custom_data` - (Optional) Specifies custom data to supply to the machine. On linux-based systems, this can be used as a cloud-init script. On other systems, this will be copied as a file on disk. Internally, Terraform will base64 encode this value before sending it to the API. The maximum length of the binary array is 65535 bytes. +* `managed_disk_type` - (Optional) Specifies the type of managed disk to create. Possible values are either `Standard_LRS` or `Premium_LRS`. -~> **NOTE:** `admin_password` must be between 6-72 characters long and must satisfy at least 3 of password complexity requirements from the following: -1. Contains an uppercase character -2. Contains a lowercase character -3. Contains a numeric digit -4. Contains a special character +* `managed_disk_id` - (Optional) Specifies the ID of an Existing Managed Disk which should be attached to this Virtual Machine. When this field is set `create_option` must be set to `Attach`. -`identity` supports the following: +The following properties apply when using Unmanaged Disks: -* `type` - (Required) Specifies the identity type of the virtual machine. Allowable values are `SystemAssigned` and `UserAssigned`. To enable Managed Service Identity the virtual machine extension "ManagedIdentityExtensionForWindows" or "ManagedIdentityExtensionForLinux" must also be added to the virtual machine. For the `SystemAssigned` identity the Principal ID can be retrieved after the virtual machine has been created. See [documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/overview) for more information. +* `vhd_uri` - (Optional) Specifies the URI of the VHD file backing this Unmanaged Data Disk. Changing this forces a new resource to be created. -* `identity_ids` - (Optional) Specifies a list of user managed identity ids to be assigned to the VM. Required if `type` is `UserAssigned`. +--- -```hcl -resource "azurerm_virtual_machine" "test" { - name = "test" +A `storage_os_disk` block supports the following: - identity = { - type = "SystemAssigned" - } -} -resource "azurerm_virtual_machine_extension" "test" { - name = "test" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - virtual_machine_name = "${azurerm_virtual_machine.test.name}" - publisher = "Microsoft.ManagedIdentity" - type = "ManagedIdentityExtensionForWindows" - type_handler_version = "1.0" - - settings = <` needs to be replaced with the actual username): -```hcl - ssh_keys { - key_data = "${file("/home//.ssh/authorized_keys")}" - path = "/home//.ssh/authorized_keys" - } -``` -~> **Note:** Please note that the only allowed `path` is `/home//.ssh/authorized_keys` due to a limitation of Azure. +* `managed_disk_id` - (Optional) Specifies the ID of an existing Managed Disk which should be attached as the OS Disk of this Virtual Machine. If this is set then the `create_option` must be set to `Attach`. + +* `managed_disk_type` - (Optional) Specifies the type of Managed Disk which should be created. Possible values are `Standard_LRS` or `Premium_LRS`. -`os_profile_secrets` supports the following: +The following properties apply when using Unmanaged Disks: -* `source_vault_id` - (Required) Specifies the key vault to use. -* `vault_certificates` - (Required) A collection of Vault Certificates as documented below +* `vhd_uri` - (Optional) Specifies the URI of the VHD file backing this Unmanaged OS Disk. Changing this forces a new resource to be created. -`vault_certificates` support the following: +--- + +A `vault_certificates` block supports the following: -* `certificate_url` - (Required) Specifies the URI of the key vault secrets in the format of `https:///secrets//`. Stored secret is the Base64 encoding of a JSON Object that which is encoded in UTF-8 of which the contents need to be +* `certificate_url` - (Required) The ID of the Key Vault Secret. Stored secret is the Base64 encoding of a JSON Object that which is encoded in UTF-8 of which the contents need to be: ```json { @@ -527,13 +352,25 @@ output "principal_id" { } ``` -* `certificate_store` - (Required, on windows machines) Specifies the certificate store on the Virtual Machine where the certificate should be added to. +-> **NOTE:** If your certificate is stored in Azure Key Vault - this can be sourced from the `secret_id` property on the `azurerm_key_vault_certificate` resource. + +* `certificate_store` - (Required, on windows machines) Specifies the certificate store on the Virtual Machine where the certificate should be added to, such as `My`. + +--- + +A `winrm` block supports the following: + +* `protocol` - (Required) Specifies the protocol of listener. Possible values are `HTTP` or `HTTPS`. + +* `certificate_url` - (Optional) The ID of the Key Vault Secret which contains the encrypted Certificate which should be installed on the Virtual Machine. This certificate must also be specified in the `vault_certificates` block within the `os_profile_secrets` block. + +-> **NOTE:** This can be sourced from the `secret_id` field on the `azurerm_key_vault_certificate` resource. ## Attributes Reference The following attributes are exported: -* `id` - The virtual machine ID. +* `id` - The ID of the Virtual Machine. ## Import