From 9f0d99091f030656a48bebcdfcb2565f9ae109cf Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Mon, 17 Apr 2017 19:07:53 -0500 Subject: [PATCH 01/68] initial commit - 101-vm-from-user-image --- examples/101-vm-from-user-image/.gitignore | 3 +++ examples/101-vm-from-user-image/README.md | 7 +++++++ examples/101-vm-from-user-image/main.tf | 0 examples/101-vm-from-user-image/variables.tf | 0 4 files changed, 10 insertions(+) create mode 100644 examples/101-vm-from-user-image/.gitignore create mode 100644 examples/101-vm-from-user-image/README.md create mode 100644 examples/101-vm-from-user-image/main.tf create mode 100644 examples/101-vm-from-user-image/variables.tf diff --git a/examples/101-vm-from-user-image/.gitignore b/examples/101-vm-from-user-image/.gitignore new file mode 100644 index 000000000000..352c8a2b9b6e --- /dev/null +++ b/examples/101-vm-from-user-image/.gitignore @@ -0,0 +1,3 @@ +terraform.tfstate* +terraform.tfvars* +creds.tf* diff --git a/examples/101-vm-from-user-image/README.md b/examples/101-vm-from-user-image/README.md new file mode 100644 index 000000000000..08f105832396 --- /dev/null +++ b/examples/101-vm-from-user-image/README.md @@ -0,0 +1,7 @@ +# Create a Virtual Machine from a User Image +**Prerequisite - The Storage Account with the User Image VHD should already exist** + +This template allows you to create a Virtual Machines from a User image. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. + +Azure requires that an application is added to Azure Active Directory to generate the client_id, client_secret, and tenant_id needed by Terraform (subscription_id can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this. + diff --git a/examples/101-vm-from-user-image/main.tf b/examples/101-vm-from-user-image/main.tf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/examples/101-vm-from-user-image/variables.tf b/examples/101-vm-from-user-image/variables.tf new file mode 100644 index 000000000000..e69de29bb2d1 From 6f577a8cad0be9293e47c2670391604db895fa10 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Wed, 19 Apr 2017 17:56:43 -0500 Subject: [PATCH 02/68] changed branch name --- examples/101-vm-from-user-image/.gitignore | 2 +- examples/101-vm-from-user-image/README.md | 2 + examples/101-vm-from-user-image/main.tf | 94 ++++++++++++++++++++ examples/101-vm-from-user-image/variables.tf | 90 +++++++++++++++++++ examples/101-vm-simple-linux/.gitignore | 2 +- 5 files changed, 188 insertions(+), 2 deletions(-) diff --git a/examples/101-vm-from-user-image/.gitignore b/examples/101-vm-from-user-image/.gitignore index 352c8a2b9b6e..a4f6eebd0a98 100644 --- a/examples/101-vm-from-user-image/.gitignore +++ b/examples/101-vm-from-user-image/.gitignore @@ -1,3 +1,3 @@ terraform.tfstate* terraform.tfvars* -creds.tf* +provider.tf* diff --git a/examples/101-vm-from-user-image/README.md b/examples/101-vm-from-user-image/README.md index 08f105832396..c1c5423e5103 100644 --- a/examples/101-vm-from-user-image/README.md +++ b/examples/101-vm-from-user-image/README.md @@ -5,3 +5,5 @@ This template allows you to create a Virtual Machines from a User image. This te Azure requires that an application is added to Azure Active Directory to generate the client_id, client_secret, and tenant_id needed by Terraform (subscription_id can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this. +`image_uri` - Specifies the `image_uri` in the form publisherName:offer:skus:version. `image_uri` can also specify the VHD uri of a custom VM image to clone. +`os_type` - When cloning a custom disk image the `os_type` documented below becomes required. Specifies the operating system Type, valid values are windows, linux. \ No newline at end of file diff --git a/examples/101-vm-from-user-image/main.tf b/examples/101-vm-from-user-image/main.tf index e69de29bb2d1..ce85956cb3e2 100644 --- a/examples/101-vm-from-user-image/main.tf +++ b/examples/101-vm-from-user-image/main.tf @@ -0,0 +1,94 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_virtual_network" "vnet" { + name = "${var.virtual_network_name}" + location = "${var.location}" + address_space = ["${var.address_space}"] + resource_group_name = "${azurerm_resource_group.rg.name}" +} + +resource "azurerm_subnet" "subnet" { + name = "${var.rg_prefix}subnet" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + address_prefix = "${var.subnet_prefix}" +} + +resource "azurerm_network_interface" "nic" { + name = "${var.rg_prefix}nic" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + + ip_configuration { + name = "${var.rg_prefix}ipconfig" + subnet_id = "${azurerm_subnet.subnet.id}" + private_ip_address_allocation = "Dynamic" + public_ip_address_id = "${azurerm_public_ip.pip.id}" + } +} + +resource "azurerm_public_ip" "pip" { + name = "${var.rg_prefix}-ip" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + public_ip_address_allocation = "dynamic" + domain_name_label = "${var.dns_name}" +} + +resource "azurerm_storage_account" "stor" { + name = "${var.hostname}stor" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + account_type = "${var.storage_account_type}" +} + +resource "azurerm_storage_container" "storc" { + name = "${var.hostname}-vhds" + resource_group_name = "${azurerm_resource_group.rg.name}" + storage_account_name = "${azurerm_storage_account.stor.name}" + container_access_type = "private" +} + +resource "azurerm_virtual_machine" "vm" { + name = "${var.rg_prefix}vm" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + vm_size = "${var.vm_size}" + network_interface_ids = ["${azurerm_network_interface.nic.id}"] + + storage_image_reference { + publisher = "${var.image_publisher}" + offer = "${var.image_offer}" + sku = "${var.image_sku}" + version = "${var.image_version}" + } + + storage_os_disk { + name = "${var.hostname}-osdisk1" + image_uri = "${var.image_uri}" + caching = "ReadWrite" + create_option = "FromImage" + } + + os_profile { + computer_name = "${var.hostname}" + admin_username = "${var.admin_username}" + admin_password = "${var.admin_password}" + } + + boot_diagnostics { + enabled = "true" + storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" + } +} + +output "hostname" { + value = "${var.hostname}" +} + +output "vm_fqdn" { + value = "${azurerm_public_ip.pip.fqdn}" +} \ No newline at end of file diff --git a/examples/101-vm-from-user-image/variables.tf b/examples/101-vm-from-user-image/variables.tf index e69de29bb2d1..f15b77ff0d89 100644 --- a/examples/101-vm-from-user-image/variables.tf +++ b/examples/101-vm-from-user-image/variables.tf @@ -0,0 +1,90 @@ +variable "resource_group" { + description = "The name of the resource group in which to create the virtual network." + default = "myresourcegroup" +} + +variable "image_uri" { + description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." + default = "" +} + +variable "os_type" { + description = "Specifies the operating system Type, valid values are windows, linux." + default = "linux" +} + +variable "rg_prefix" { + description = "The shortened abbreviation to represent your resource group that will go on the front of some resources." + default = "rg" +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "virtual_network_name" { + description = "The name for the virtual network." + default = "vnet" +} + +# UNCERTAIN OF THIS VARIABLE +variable "address_space" { + description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." + default = "10.0.0.0/16" +} + +# UNCERTAIN OF THIS VARIABLE +variable "subnet_prefix" { + description = "The address prefix to use for the subnet." + default = "10.1.0.0/24" +} + +variable "storage_account_type" { + description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." + default = "Premium_LRS" +} + +variable "vm_size" { + description = "Specifies the name of the virtual machine resource. Changing this forces a new resource to be created." + default = "Standard_DS1_v2" +} + +variable "image_publisher" { + description = "name of the publisher of the image (az vm image list)" + default = "Canonical" +} + +variable "image_offer" { + description = "the name of the offer (az vm image list)" + default = "UbuntuServer" +} + +variable "image_sku" { + description = "image sku to apply (az vm image list)" + default = "12.04.5-LTS" +} + +variable "image_version" { + description = "version of the image to apply (az vm image list)" + default = "latest" +} + +variable "hostname" { + description = "VM name referenced also in storage-related names." + default = "myvm" +} + +variable "dns_name" { + description = " Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." +} + +variable "admin_username" { + description = "administrator user name" + default = "vmadmin" +} + +variable "admin_password" { + description = "administrator password (recommended to disable password auth)" + default = "T3rr@f0rmP@ssword" +} diff --git a/examples/101-vm-simple-linux/.gitignore b/examples/101-vm-simple-linux/.gitignore index 352c8a2b9b6e..a4f6eebd0a98 100644 --- a/examples/101-vm-simple-linux/.gitignore +++ b/examples/101-vm-simple-linux/.gitignore @@ -1,3 +1,3 @@ terraform.tfstate* terraform.tfvars* -creds.tf* +provider.tf* From 611d70affe9f89df717c524fbd97d698e74a6cc7 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Fri, 21 Apr 2017 09:03:15 -0500 Subject: [PATCH 03/68] not deploying - storage problems --- examples/101-vm-from-user-image/variables.tf | 90 ------------------- .../.gitignore | 0 .../README.md | 5 +- examples/azure-vm-from-user-image/deploy.sh | 43 +++++++++ .../main.tf | 46 +++------- examples/azure-vm-from-user-image/outputs.tf | 11 +++ .../azure-vm-from-user-image/variables.tf | 54 +++++++++++ 7 files changed, 123 insertions(+), 126 deletions(-) delete mode 100644 examples/101-vm-from-user-image/variables.tf rename examples/{101-vm-from-user-image => azure-vm-from-user-image}/.gitignore (100%) rename examples/{101-vm-from-user-image => azure-vm-from-user-image}/README.md (75%) create mode 100644 examples/azure-vm-from-user-image/deploy.sh rename examples/{101-vm-from-user-image => azure-vm-from-user-image}/main.tf (61%) create mode 100644 examples/azure-vm-from-user-image/outputs.tf create mode 100644 examples/azure-vm-from-user-image/variables.tf diff --git a/examples/101-vm-from-user-image/variables.tf b/examples/101-vm-from-user-image/variables.tf deleted file mode 100644 index f15b77ff0d89..000000000000 --- a/examples/101-vm-from-user-image/variables.tf +++ /dev/null @@ -1,90 +0,0 @@ -variable "resource_group" { - description = "The name of the resource group in which to create the virtual network." - default = "myresourcegroup" -} - -variable "image_uri" { - description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." - default = "" -} - -variable "os_type" { - description = "Specifies the operating system Type, valid values are windows, linux." - default = "linux" -} - -variable "rg_prefix" { - description = "The shortened abbreviation to represent your resource group that will go on the front of some resources." - default = "rg" -} - -variable "location" { - description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." - default = "southcentralus" -} - -variable "virtual_network_name" { - description = "The name for the virtual network." - default = "vnet" -} - -# UNCERTAIN OF THIS VARIABLE -variable "address_space" { - description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." - default = "10.0.0.0/16" -} - -# UNCERTAIN OF THIS VARIABLE -variable "subnet_prefix" { - description = "The address prefix to use for the subnet." - default = "10.1.0.0/24" -} - -variable "storage_account_type" { - description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." - default = "Premium_LRS" -} - -variable "vm_size" { - description = "Specifies the name of the virtual machine resource. Changing this forces a new resource to be created." - default = "Standard_DS1_v2" -} - -variable "image_publisher" { - description = "name of the publisher of the image (az vm image list)" - default = "Canonical" -} - -variable "image_offer" { - description = "the name of the offer (az vm image list)" - default = "UbuntuServer" -} - -variable "image_sku" { - description = "image sku to apply (az vm image list)" - default = "12.04.5-LTS" -} - -variable "image_version" { - description = "version of the image to apply (az vm image list)" - default = "latest" -} - -variable "hostname" { - description = "VM name referenced also in storage-related names." - default = "myvm" -} - -variable "dns_name" { - description = " Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." -} - -variable "admin_username" { - description = "administrator user name" - default = "vmadmin" -} - -variable "admin_password" { - description = "administrator password (recommended to disable password auth)" - default = "T3rr@f0rmP@ssword" -} diff --git a/examples/101-vm-from-user-image/.gitignore b/examples/azure-vm-from-user-image/.gitignore similarity index 100% rename from examples/101-vm-from-user-image/.gitignore rename to examples/azure-vm-from-user-image/.gitignore diff --git a/examples/101-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md similarity index 75% rename from examples/101-vm-from-user-image/README.md rename to examples/azure-vm-from-user-image/README.md index c1c5423e5103..b115f2451032 100644 --- a/examples/101-vm-from-user-image/README.md +++ b/examples/azure-vm-from-user-image/README.md @@ -6,4 +6,7 @@ This template allows you to create a Virtual Machines from a User image. This te Azure requires that an application is added to Azure Active Directory to generate the client_id, client_secret, and tenant_id needed by Terraform (subscription_id can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this. `image_uri` - Specifies the `image_uri` in the form publisherName:offer:skus:version. `image_uri` can also specify the VHD uri of a custom VM image to clone. -`os_type` - When cloning a custom disk image the `os_type` documented below becomes required. Specifies the operating system Type, valid values are windows, linux. \ No newline at end of file +`os_type` - When cloning a custom disk image the `os_type` documented below becomes required. Specifies the operating system Type, valid values are windows, linux. + +**Storage Accounts can be imported using the resource id, e.g.** +`terraform import azurerm_storage_account.storageAcc1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount` \ No newline at end of file diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh new file mode 100644 index 000000000000..3160ca88ed43 --- /dev/null +++ b/examples/azure-vm-from-user-image/deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -o errexit -o nounset + +# generate a unique string for CI deployment +KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) +PASSWORD=KEY +PASSWORD+=$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2) +PASSWORD+=$(cat /dev/urandom | tr -cd '0-9' | head -c 2) + +terraform get + +terraform plan \ + -var 'dns_name='$KEY \ + -var 'admin_password='$PASSWORD \ + -var 'admin_username='$KEY \ + -var 'resource_group='$KEY \ + -out=out.tfplan + +terraform apply out.tfplan + + +# TODO: determine external validation, possibly Azure CLI + +# echo "Setting git user name" +# git config user.name $GH_USER_NAME +# +# echo "Setting git user email" +# git config user.email $GH_USER_EMAIL +# +# echo "Adding git upstream remote" +# git remote add upstream "https://$GH_TOKEN@github.com/$GH_REPO.git" +# +# git checkout master + + +# +# NOW=$(TZ=America/Chicago date) +# +# git commit -m "tfstate: $NOW [ci skip]" +# +# echo "Pushing changes to upstream master" +# git push upstream master \ No newline at end of file diff --git a/examples/101-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf similarity index 61% rename from examples/101-vm-from-user-image/main.tf rename to examples/azure-vm-from-user-image/main.tf index ce85956cb3e2..44464b5cd55b 100644 --- a/examples/101-vm-from-user-image/main.tf +++ b/examples/azure-vm-from-user-image/main.tf @@ -4,26 +4,26 @@ resource "azurerm_resource_group" "rg" { } resource "azurerm_virtual_network" "vnet" { - name = "${var.virtual_network_name}" + name = "${var.hostname}vnet" location = "${var.location}" address_space = ["${var.address_space}"] resource_group_name = "${azurerm_resource_group.rg.name}" } resource "azurerm_subnet" "subnet" { - name = "${var.rg_prefix}subnet" + name = "${var.hostname}subnet" virtual_network_name = "${azurerm_virtual_network.vnet.name}" resource_group_name = "${azurerm_resource_group.rg.name}" address_prefix = "${var.subnet_prefix}" } resource "azurerm_network_interface" "nic" { - name = "${var.rg_prefix}nic" + name = "${var.hostname}nic" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" ip_configuration { - name = "${var.rg_prefix}ipconfig" + name = "${var.hostname}ipconfig" subnet_id = "${azurerm_subnet.subnet.id}" private_ip_address_allocation = "Dynamic" public_ip_address_id = "${azurerm_public_ip.pip.id}" @@ -31,44 +31,32 @@ resource "azurerm_network_interface" "nic" { } resource "azurerm_public_ip" "pip" { - name = "${var.rg_prefix}-ip" + name = "${var.hostname}-ip" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" public_ip_address_allocation = "dynamic" - domain_name_label = "${var.dns_name}" + domain_name_label = "${var.hostname}" } resource "azurerm_storage_account" "stor" { - name = "${var.hostname}stor" + name = "${var.storage_account_name}" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" account_type = "${var.storage_account_type}" } -resource "azurerm_storage_container" "storc" { - name = "${var.hostname}-vhds" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_name = "${azurerm_storage_account.stor.name}" - container_access_type = "private" -} - resource "azurerm_virtual_machine" "vm" { - name = "${var.rg_prefix}vm" + name = "${var.hostname}" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" vm_size = "${var.vm_size}" network_interface_ids = ["${azurerm_network_interface.nic.id}"] - storage_image_reference { - publisher = "${var.image_publisher}" - offer = "${var.image_offer}" - sku = "${var.image_sku}" - version = "${var.image_version}" - } - storage_os_disk { name = "${var.hostname}-osdisk1" - image_uri = "${var.image_uri}" + image_uri = "${var.image_uri}" + vhd_uri = "" + os_type = "${var.os_type}" caching = "ReadWrite" create_option = "FromImage" } @@ -79,16 +67,4 @@ resource "azurerm_virtual_machine" "vm" { admin_password = "${var.admin_password}" } - boot_diagnostics { - enabled = "true" - storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" - } -} - -output "hostname" { - value = "${var.hostname}" } - -output "vm_fqdn" { - value = "${azurerm_public_ip.pip.fqdn}" -} \ No newline at end of file diff --git a/examples/azure-vm-from-user-image/outputs.tf b/examples/azure-vm-from-user-image/outputs.tf new file mode 100644 index 000000000000..125017a6f3f1 --- /dev/null +++ b/examples/azure-vm-from-user-image/outputs.tf @@ -0,0 +1,11 @@ +output "hostname" { + value = "${var.hostname}" +} + +output "vm_fqdn" { + value = "${azurerm_public_ip.pip.fqdn}" +} + +output "sshCommand" { + value = "${concat("ssh ", var.admin_username, "@", azurerm_public_ip.pip.fqdn)}" +} \ No newline at end of file diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf new file mode 100644 index 000000000000..2c10c9401875 --- /dev/null +++ b/examples/azure-vm-from-user-image/variables.tf @@ -0,0 +1,54 @@ +variable "resource_group" { + description = "The name of the resource group in which the image to clone resides." +} + +variable "image_uri" { + description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." +} + +variable "os_type" { + description = "Specifies the operating system Type, valid values are windows, linux." + default = "linux" +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "address_space" { + description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." + default = "10.0.0.0/16" +} + +variable "subnet_prefix" { + description = "The address prefix to use for the subnet." + default = "10.0.0.0/24" +} + +variable "storage_account_name" { + description = "The name of the storage account in which the image from which you are cloning resides." +} + +variable "storage_account_type" { + description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." + default = "Standard_LRS" +} + +variable "vm_size" { + description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." +} + +variable "hostname" { + description = "VM name referenced also in storage-related names. This is also used as the label for the Domain Name and to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." +} + +variable "admin_username" { + description = "administrator user name" + default = "vmadmin" +} + +variable "admin_password" { + description = "administrator password (recommended to disable password auth)" + default = "T3rr@f0rmP@ssword" +} From fdff23aeec4aa94ff3481f05ef49430cddcca300 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Fri, 21 Apr 2017 10:34:07 -0500 Subject: [PATCH 04/68] provisions vm but image not properly prepared --- examples/azure-vm-from-user-image/main.tf | 2 +- examples/azure-vm-from-user-image/variables.tf | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf index 44464b5cd55b..686ea83bac85 100644 --- a/examples/azure-vm-from-user-image/main.tf +++ b/examples/azure-vm-from-user-image/main.tf @@ -55,7 +55,7 @@ resource "azurerm_virtual_machine" "vm" { storage_os_disk { name = "${var.hostname}-osdisk1" image_uri = "${var.image_uri}" - vhd_uri = "" + vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}vhds/myosdisk1.vhd" os_type = "${var.os_type}" caching = "ReadWrite" create_option = "FromImage" diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf index 2c10c9401875..f25a42c66d6e 100644 --- a/examples/azure-vm-from-user-image/variables.tf +++ b/examples/azure-vm-from-user-image/variables.tf @@ -4,6 +4,7 @@ variable "resource_group" { variable "image_uri" { description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." + default = "https://myvmstor.blob.core.windows.net/vhds/armvm5yt3s3judzp66osDisk.vhd" } variable "os_type" { From 0dac5ecfa1864844390e1c0418407ce761a10fd4 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Fri, 21 Apr 2017 18:32:12 -0500 Subject: [PATCH 05/68] storage not correct --- examples/azure-vm-from-user-image/README.md | 2 +- examples/azure-vm-from-user-image/main.tf | 2 +- examples/azure-vm-from-user-image/variables.tf | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md index b115f2451032..e64165a0455f 100644 --- a/examples/azure-vm-from-user-image/README.md +++ b/examples/azure-vm-from-user-image/README.md @@ -1,4 +1,4 @@ -# Create a Virtual Machine from a User Image +# [Create a Virtual Machine from a User Image](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-deploy-templates#create-a-custom-vm-image) **Prerequisite - The Storage Account with the User Image VHD should already exist** This template allows you to create a Virtual Machines from a User image. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf index 686ea83bac85..184873130a5f 100644 --- a/examples/azure-vm-from-user-image/main.tf +++ b/examples/azure-vm-from-user-image/main.tf @@ -55,7 +55,7 @@ resource "azurerm_virtual_machine" "vm" { storage_os_disk { name = "${var.hostname}-osdisk1" image_uri = "${var.image_uri}" - vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}vhds/myosdisk1.vhd" + vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}vhds/${var.hostname}osdisk.vhd" os_type = "${var.os_type}" caching = "ReadWrite" create_option = "FromImage" diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf index f25a42c66d6e..57fc4f6fefba 100644 --- a/examples/azure-vm-from-user-image/variables.tf +++ b/examples/azure-vm-from-user-image/variables.tf @@ -4,7 +4,7 @@ variable "resource_group" { variable "image_uri" { description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." - default = "https://myvmstor.blob.core.windows.net/vhds/armvm5yt3s3judzp66osDisk.vhd" + default = "https://myrgdisks276.blob.core.windows.net/vhds/originalvm20170421170101.vhd" } variable "os_type" { @@ -29,6 +29,7 @@ variable "subnet_prefix" { variable "storage_account_name" { description = "The name of the storage account in which the image from which you are cloning resides." + default = "myrgsisks276" } variable "storage_account_type" { @@ -38,6 +39,7 @@ variable "storage_account_type" { variable "vm_size" { description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." + default = "Standard_DS1_v2" } variable "hostname" { From 81e2559ead58b1153ca3253474907db91ec3a0c4 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Sat, 22 Apr 2017 10:26:28 -0500 Subject: [PATCH 06/68] provisions properly --- examples/azure-vm-from-user-image/main.tf | 9 +-------- examples/azure-vm-from-user-image/variables.tf | 5 +++++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf index 184873130a5f..6bae761c1774 100644 --- a/examples/azure-vm-from-user-image/main.tf +++ b/examples/azure-vm-from-user-image/main.tf @@ -38,13 +38,6 @@ resource "azurerm_public_ip" "pip" { domain_name_label = "${var.hostname}" } -resource "azurerm_storage_account" "stor" { - name = "${var.storage_account_name}" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - account_type = "${var.storage_account_type}" -} - resource "azurerm_virtual_machine" "vm" { name = "${var.hostname}" location = "${var.location}" @@ -55,7 +48,7 @@ resource "azurerm_virtual_machine" "vm" { storage_os_disk { name = "${var.hostname}-osdisk1" image_uri = "${var.image_uri}" - vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}vhds/${var.hostname}osdisk.vhd" + vhd_uri = "${var.primary_blob_endpoint}vhds/${var.hostname}osdisk.vhd" os_type = "${var.os_type}" caching = "ReadWrite" create_option = "FromImage" diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf index 57fc4f6fefba..c09ad5ec15d0 100644 --- a/examples/azure-vm-from-user-image/variables.tf +++ b/examples/azure-vm-from-user-image/variables.tf @@ -7,6 +7,11 @@ variable "image_uri" { default = "https://myrgdisks276.blob.core.windows.net/vhds/originalvm20170421170101.vhd" } +variable "primary_blob_endpoint" { + description = "" + default = "https://myrgdisks276.blob.core.windows.net/" +} + variable "os_type" { description = "Specifies the operating system Type, valid values are windows, linux." default = "linux" From 7dc8150043b6c0c67a3976c6a22222eb44ea9009 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Sat, 22 Apr 2017 11:11:25 -0500 Subject: [PATCH 07/68] changed main.tf to azuredeploy.tf --- examples/azure-vm-from-user-image/README.md | 3 --- examples/azure-vm-from-user-image/{main.tf => azuredeploy.tf} | 0 2 files changed, 3 deletions(-) rename examples/azure-vm-from-user-image/{main.tf => azuredeploy.tf} (100%) diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md index e64165a0455f..41d5164c6cbe 100644 --- a/examples/azure-vm-from-user-image/README.md +++ b/examples/azure-vm-from-user-image/README.md @@ -7,6 +7,3 @@ Azure requires that an application is added to Azure Active Directory to generat `image_uri` - Specifies the `image_uri` in the form publisherName:offer:skus:version. `image_uri` can also specify the VHD uri of a custom VM image to clone. `os_type` - When cloning a custom disk image the `os_type` documented below becomes required. Specifies the operating system Type, valid values are windows, linux. - -**Storage Accounts can be imported using the resource id, e.g.** -`terraform import azurerm_storage_account.storageAcc1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount` \ No newline at end of file diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/azuredeploy.tf similarity index 100% rename from examples/azure-vm-from-user-image/main.tf rename to examples/azure-vm-from-user-image/azuredeploy.tf From 5c079fa1d3e73c7c3c830d795c5b6c63e48023a8 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Sat, 22 Apr 2017 12:37:05 -0500 Subject: [PATCH 08/68] added tfvars and info for README --- examples/azure-vm-from-user-image/.gitignore | 4 +- examples/azure-vm-from-user-image/README.md | 93 ++++++++++++++++++- .../azure-vm-from-user-image/azuredeploy.tf | 9 +- examples/azure-vm-from-user-image/outputs.tf | 2 +- .../provider.tf.example | 6 ++ .../terraform.tfvars.example | 13 +++ .../azure-vm-from-user-image/terraform.tvars | 0 .../azure-vm-from-user-image/variables.tf | 15 --- 8 files changed, 114 insertions(+), 28 deletions(-) create mode 100644 examples/azure-vm-from-user-image/provider.tf.example create mode 100644 examples/azure-vm-from-user-image/terraform.tfvars.example create mode 100644 examples/azure-vm-from-user-image/terraform.tvars diff --git a/examples/azure-vm-from-user-image/.gitignore b/examples/azure-vm-from-user-image/.gitignore index a4f6eebd0a98..7773fa9ecc5d 100644 --- a/examples/azure-vm-from-user-image/.gitignore +++ b/examples/azure-vm-from-user-image/.gitignore @@ -1,3 +1,3 @@ terraform.tfstate* -terraform.tfvars* -provider.tf* +terraform.tfvars +provider.tf diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md index 41d5164c6cbe..f391b0b8f40f 100644 --- a/examples/azure-vm-from-user-image/README.md +++ b/examples/azure-vm-from-user-image/README.md @@ -1,9 +1,92 @@ # [Create a Virtual Machine from a User Image](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-deploy-templates#create-a-custom-vm-image) -**Prerequisite - The Storage Account with the User Image VHD should already exist** -This template allows you to create a Virtual Machines from a User image. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. + + + + + + -Azure requires that an application is added to Azure Active Directory to generate the client_id, client_secret, and tenant_id needed by Terraform (subscription_id can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this. +> Prerequisite - The generalized image VHD should exist, as well as a Storage Account for boot diagnostics -`image_uri` - Specifies the `image_uri` in the form publisherName:offer:skus:version. `image_uri` can also specify the VHD uri of a custom VM image to clone. -`os_type` - When cloning a custom disk image the `os_type` documented below becomes required. Specifies the operating system Type, valid values are windows, linux. +This template allows you to create a Virtual Machine from an unmanaged User image vhd. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. + +If you are looking to accomplish the above scenario through PowerShell instead of a template, you can use a PowerShell script like below + +##### Variables + ## Global + $rgName = "testrg" + $location = "westus" + + ## Storage + $storageName = "teststore" + $storageType = "Standard_GRS" + + ## Network + $nicname = "testnic" + $subnet1Name = "subnet1" + $vnetName = "testnet" + $vnetAddressPrefix = "10.0.0.0/16" + $vnetSubnetAddressPrefix = "10.0.0.0/24" + + ## Compute + $vmName = "testvm" + $computerName = "testcomputer" + $vmSize = "Standard_A2" + $osDiskName = $vmName + "osDisk" + +##### Resource Group + New-AzureRmResourceGroup -Name $rgName -Location $location + +##### Storage + $storageacc = New-AzureRmStorageAccount -ResourceGroupName $rgName -Name $storageName -Type $storageType -Location $location + +##### Network + $pip = New-AzureRmPublicIpAddress -Name $nicname -ResourceGroupName $rgName -Location $location -AllocationMethod Dynamic + $subnetconfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet1Name -AddressPrefix $vnetSubnetAddressPrefix + $vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location -AddressPrefix $vnetAddressPrefix -Subnet $subnetconfig + $nic = New-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $rgName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id + +##### Compute + ## Setup local VM object + $cred = Get-Credential + $vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize + $vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $computerName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate + + $vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id + + $osDiskUri = "http://test.blob.core.windows.net/vmcontainer10798c80-131-1231-a94a-f9d2a712251f/osDisk.10798c80-2919-4100-a94a-f9d2a712251f.vhd" + $imageUri = "http://test.blob.core.windows.net/system/Microsoft.Compute/Images/captured/image-osDisk.8b021d87-913c-4f94-a01a-944ad92d7388.vhd" + $vm = Set-AzureRmVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri -CreateOption fromImage -SourceImageUri $imageUri -Windows + + $dataImageUri = "http://test.blob.core.windows.net/system/Microsoft.Compute/Images/captured/image-dataDisk-0.8b021d87-913c-4f94-a01a-944ad92d7388.vhd" + $dataDiskUri = "http://test.blob.core.windows.net/vmcontainer10798c80-sa11-41sa-dsad-f9d2a712251f/dataDisk-0.10798c80-2919-4100-a94a-f9d2a712251f.vhd" + $vm = Add-AzureRmVMDataDisk -VM $vm -Name "dd1" -VhdUri $dataDiskUri -SourceImageUri $dataImageUri -Lun 0 -CreateOption fromImage + + ## Create the VM in Azure + New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm -Verbose + + +## azuredeploy.tf +The `azuredeploy.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. + +## .gitignore +If you are committing this template to source control, please insure that the following files are added to your `.gitignore` file. + +``` +terraform.tfstate* +terraform.tfvars* +provider.tf* +``` diff --git a/examples/azure-vm-from-user-image/azuredeploy.tf b/examples/azure-vm-from-user-image/azuredeploy.tf index 6bae761c1774..28edf99204b5 100644 --- a/examples/azure-vm-from-user-image/azuredeploy.tf +++ b/examples/azure-vm-from-user-image/azuredeploy.tf @@ -18,9 +18,9 @@ resource "azurerm_subnet" "subnet" { } resource "azurerm_network_interface" "nic" { - name = "${var.hostname}nic" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" + name = "${var.hostname}nic" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" ip_configuration { name = "${var.hostname}ipconfig" @@ -48,7 +48,7 @@ resource "azurerm_virtual_machine" "vm" { storage_os_disk { name = "${var.hostname}-osdisk1" image_uri = "${var.image_uri}" - vhd_uri = "${var.primary_blob_endpoint}vhds/${var.hostname}osdisk.vhd" + vhd_uri = "https://${var.storage_account_name}.blob.core.windows.net/vhds/${var.hostname}osdisk.vhd" os_type = "${var.os_type}" caching = "ReadWrite" create_option = "FromImage" @@ -59,5 +59,4 @@ resource "azurerm_virtual_machine" "vm" { admin_username = "${var.admin_username}" admin_password = "${var.admin_password}" } - } diff --git a/examples/azure-vm-from-user-image/outputs.tf b/examples/azure-vm-from-user-image/outputs.tf index 125017a6f3f1..e0e255a9e01c 100644 --- a/examples/azure-vm-from-user-image/outputs.tf +++ b/examples/azure-vm-from-user-image/outputs.tf @@ -8,4 +8,4 @@ output "vm_fqdn" { output "sshCommand" { value = "${concat("ssh ", var.admin_username, "@", azurerm_public_ip.pip.fqdn)}" -} \ No newline at end of file +} diff --git a/examples/azure-vm-from-user-image/provider.tf.example b/examples/azure-vm-from-user-image/provider.tf.example new file mode 100644 index 000000000000..a0b5e46772f5 --- /dev/null +++ b/examples/azure-vm-from-user-image/provider.tf.example @@ -0,0 +1,6 @@ +provider "azurerm" { + subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" + client_id = "REPLACE-WITH-YOUR-CLIENT-ID" + client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" + tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +} diff --git a/examples/azure-vm-from-user-image/terraform.tfvars.example b/examples/azure-vm-from-user-image/terraform.tfvars.example new file mode 100644 index 000000000000..6cc72c9218be --- /dev/null +++ b/examples/azure-vm-from-user-image/terraform.tfvars.example @@ -0,0 +1,13 @@ +resource_group = "myresourcegroup" +image_uri = "https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd" +primary_blob_endpoint = "https://DISK.blob.core.windows.net/" +location = "southcentralus" +os_type = "linux" +address_space = "10.0.0.0/16" +subnet_prefix = "10.0.0.0/24" +storage_account_name = "STOR-ACCT-NAME" +storage_account_type = "Standard_LRS" +vm_size = "Standard_DS1_v2" +hostname = "HOSTNAME" +admin_username = "vmadmin" +admin_password = "T3rr@f0rmP@ssword" \ No newline at end of file diff --git a/examples/azure-vm-from-user-image/terraform.tvars b/examples/azure-vm-from-user-image/terraform.tvars new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf index c09ad5ec15d0..8bf04524f4fd 100644 --- a/examples/azure-vm-from-user-image/variables.tf +++ b/examples/azure-vm-from-user-image/variables.tf @@ -4,47 +4,34 @@ variable "resource_group" { variable "image_uri" { description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." - default = "https://myrgdisks276.blob.core.windows.net/vhds/originalvm20170421170101.vhd" -} - -variable "primary_blob_endpoint" { - description = "" - default = "https://myrgdisks276.blob.core.windows.net/" } variable "os_type" { description = "Specifies the operating system Type, valid values are windows, linux." - default = "linux" } variable "location" { description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." - default = "southcentralus" } variable "address_space" { description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." - default = "10.0.0.0/16" } variable "subnet_prefix" { description = "The address prefix to use for the subnet." - default = "10.0.0.0/24" } variable "storage_account_name" { description = "The name of the storage account in which the image from which you are cloning resides." - default = "myrgsisks276" } variable "storage_account_type" { description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." - default = "Standard_LRS" } variable "vm_size" { description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." - default = "Standard_DS1_v2" } variable "hostname" { @@ -53,10 +40,8 @@ variable "hostname" { variable "admin_username" { description = "administrator user name" - default = "vmadmin" } variable "admin_password" { description = "administrator password (recommended to disable password auth)" - default = "T3rr@f0rmP@ssword" } From c86ef6fce79d3dec6ad1614b5fd9c031d5950367 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Sat, 22 Apr 2017 12:43:36 -0500 Subject: [PATCH 09/68] tfvars ignored and corrected file ext --- examples/azure-vm-from-user-image/terraform.tvars | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/azure-vm-from-user-image/terraform.tvars diff --git a/examples/azure-vm-from-user-image/terraform.tvars b/examples/azure-vm-from-user-image/terraform.tvars deleted file mode 100644 index e69de29bb2d1..000000000000 From 534b23634db9774837055825ca23458934f2d3b1 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Mon, 24 Apr 2017 10:11:10 -0500 Subject: [PATCH 10/68] added CI config; added sane defaults for variables; updated deployment script, added mac specific deployment for local testing --- .travis.yml | 78 +++++++++---------- .../azure-vm-from-user-image/deploy.mac.sh | 17 ++++ examples/azure-vm-from-user-image/deploy.sh | 31 ++++---- .../azure-vm-from-user-image/variables.tf | 7 ++ 4 files changed, 76 insertions(+), 57 deletions(-) create mode 100644 examples/azure-vm-from-user-image/deploy.mac.sh diff --git a/.travis.yml b/.travis.yml index 04cc6f30960b..496f541775a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,42 @@ -dist: trusty -sudo: false -language: go -go: -- 1.8 - -# add TF_CONSUL_TEST=1 to run consul tests -# they were causing timouts in travis +sudo: required + +services: + - docker + +language: generic + +# on branches: ignore multiple commits that will queue build jobs, just run latest commit +git: + depth: 1 + +# establish environment variables env: - - CONSUL_VERSION=0.7.5 GOMAXPROCS=4 - -# Fetch consul for the backend and provider tests -before_install: - - curl -sLo consul.zip https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip - - unzip consul.zip - - mkdir ~/bin - - mv consul ~/bin - - export PATH="~/bin:$PATH" - -install: -# This script is used by the Travis build to install a cookie for -# go.googlesource.com so rate limits are higher when using `go get` to fetch -# packages that live there. -# See: https://github.com/golang/go/issues/12933 -- bash scripts/gogetcookie.sh -- go get github.com/kardianos/govendor -script: -- make vet vendor-status test -- GOOS=windows go build + - TEST_DIR=examples/azure-vm-from-user-image + branches: only: - - master -notifications: - irc: - channels: - - irc.freenode.org#terraform-tool - skip_join: true - use_notice: true -matrix: - fast_finish: true - allow_failures: - - go: tip + - /^(?i:topic)-.*$/ + +# install terraform +before_deploy: + - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) + - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) + - export IMAGE_URI='https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd' + - export PRIMARY_BLOB_ENDPOINT='https://DISK.blob.core.windows.net/' + + +# terraform deploy script +deploy: + - provider: script + skip_cleanup: true + script: cd $TEST_DIR && ./deploy.sh + on: + repo: 10thmagnitude/terraform + branch: topic-101-vm-from-user-image + +# destroy resources with Azure CLI +after_deploy: + - docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az group delete -y -n $KEY" diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh new file mode 100644 index 000000000000..6bb89bca9249 --- /dev/null +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -o errexit -o nounset + +# generate a unique string for CI deployment +export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) +export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) +export IMAGE_URI='https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd' +export PRIMARY_BLOB_ENDPOINT='https://DISK.blob.core.windows.net/' + + +/bin/sh ./deploy.sh + +# docker run --rm -it \ +# azuresdk/azure-cli-python \ +# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ +# az group delete -y -n $KEY" diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh index 3160ca88ed43..1e8c75d4d77e 100644 --- a/examples/azure-vm-from-user-image/deploy.sh +++ b/examples/azure-vm-from-user-image/deploy.sh @@ -2,23 +2,18 @@ set -o errexit -o nounset -# generate a unique string for CI deployment -KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) -PASSWORD=KEY -PASSWORD+=$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2) -PASSWORD+=$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - -terraform get - -terraform plan \ - -var 'dns_name='$KEY \ - -var 'admin_password='$PASSWORD \ - -var 'admin_username='$KEY \ - -var 'resource_group='$KEY \ - -out=out.tfplan - -terraform apply out.tfplan - +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "cd /data; \ + /bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$KEY -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$IMAGE_URI -var primary_blob_endpoint=$PRIMARY_BLOB_ENDPOINT -var storage_account_name=$KEY; /bin/terraform apply out.tfplan" # TODO: determine external validation, possibly Azure CLI @@ -40,4 +35,4 @@ terraform apply out.tfplan # git commit -m "tfstate: $NOW [ci skip]" # # echo "Pushing changes to upstream master" -# git push upstream master \ No newline at end of file +# git push upstream master diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf index 8bf04524f4fd..2f5cfca0f5a7 100644 --- a/examples/azure-vm-from-user-image/variables.tf +++ b/examples/azure-vm-from-user-image/variables.tf @@ -8,18 +8,22 @@ variable "image_uri" { variable "os_type" { description = "Specifies the operating system Type, valid values are windows, linux." + default="linux" } variable "location" { description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default="southcentralus" } variable "address_space" { description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." + default="10.0.0.0/16" } variable "subnet_prefix" { description = "The address prefix to use for the subnet." + default="10.0.0.0/24" } variable "storage_account_name" { @@ -28,10 +32,12 @@ variable "storage_account_name" { variable "storage_account_type" { description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." + default="Standard_LRS" } variable "vm_size" { description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." + default="Standard_DS1_v2" } variable "hostname" { @@ -40,6 +46,7 @@ variable "hostname" { variable "admin_username" { description = "administrator user name" + default="vmadmin" } variable "admin_password" { From 0cf888b6acbd04fc5e1c599abb77ad8e0027b0b3 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Mon, 24 Apr 2017 10:16:06 -0500 Subject: [PATCH 11/68] deploy.sh to be executable --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 496f541775a2..bb75e76235a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ before_deploy: deploy: - provider: script skip_cleanup: true - script: cd $TEST_DIR && ./deploy.sh + script: cd $TEST_DIR && chmod +X ./deploy.sh && ./deploy.sh on: repo: 10thmagnitude/terraform branch: topic-101-vm-from-user-image From 68f00035c9b9e9cd42e3dcba159d09f928f4734c Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Mon, 24 Apr 2017 10:25:46 -0500 Subject: [PATCH 12/68] executable deploy files --- .travis.yml | 2 +- examples/azure-vm-from-user-image/deploy.mac.sh | 0 examples/azure-vm-from-user-image/deploy.sh | 0 3 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 examples/azure-vm-from-user-image/deploy.mac.sh mode change 100644 => 100755 examples/azure-vm-from-user-image/deploy.sh diff --git a/.travis.yml b/.travis.yml index bb75e76235a5..496f541775a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ before_deploy: deploy: - provider: script skip_cleanup: true - script: cd $TEST_DIR && chmod +X ./deploy.sh && ./deploy.sh + script: cd $TEST_DIR && ./deploy.sh on: repo: 10thmagnitude/terraform branch: topic-101-vm-from-user-image diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh old mode 100644 new mode 100755 diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh old mode 100644 new mode 100755 From c898510f2471c59f03e4d5859bd060638455bb6c Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Mon, 24 Apr 2017 19:28:16 -0500 Subject: [PATCH 13/68] added CI files; changed vars --- .travis.yml | 6 +++--- examples/azure-vm-from-user-image/deploy.mac.sh | 6 +++--- examples/azure-vm-from-user-image/deploy.sh | 2 +- .../{azuredeploy.tf => main.tf} | 0 examples/azure-vm-from-user-image/variables.tf | 16 +++++++++------- 5 files changed, 16 insertions(+), 14 deletions(-) rename examples/azure-vm-from-user-image/{azuredeploy.tf => main.tf} (100%) diff --git a/.travis.yml b/.travis.yml index 496f541775a2..b7c7b7c23663 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,9 @@ branches: before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - - export IMAGE_URI='https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd' - - export PRIMARY_BLOB_ENDPOINT='https://DISK.blob.core.windows.net/' - + - export IMAGE_URI=https://myrgdisks640.blob.core.windows.net/vhds/original-vm20170424164303.vhd + - export STORAGE_ACCOUNT_NAME=myrgdisks640 + - export RG=myrg # terraform deploy script deploy: diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh index 6bb89bca9249..d66b85079b19 100755 --- a/examples/azure-vm-from-user-image/deploy.mac.sh +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -5,9 +5,9 @@ set -o errexit -o nounset # generate a unique string for CI deployment export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) -export IMAGE_URI='https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd' -export PRIMARY_BLOB_ENDPOINT='https://DISK.blob.core.windows.net/' - +export IMAGE_URI=https://myrgdisks640.blob.core.windows.net/vhds/original-vm20170424164303.vhd +export STORAGE_ACCOUNT_NAME=myrgdisks640 +export RG=myrg /bin/sh ./deploy.sh diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh index 1e8c75d4d77e..94a5d0a61aae 100755 --- a/examples/azure-vm-from-user-image/deploy.sh +++ b/examples/azure-vm-from-user-image/deploy.sh @@ -13,7 +13,7 @@ docker run --rm -it \ -c "cd /data; \ /bin/terraform get; \ /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$KEY -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$IMAGE_URI -var primary_blob_endpoint=$PRIMARY_BLOB_ENDPOINT -var storage_account_name=$KEY; /bin/terraform apply out.tfplan" + /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$RG -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$IMAGE_URI -var storage_account_name=$STORAGE_ACCOUNT_NAME; /bin/terraform apply out.tfplan" # TODO: determine external validation, possibly Azure CLI diff --git a/examples/azure-vm-from-user-image/azuredeploy.tf b/examples/azure-vm-from-user-image/main.tf similarity index 100% rename from examples/azure-vm-from-user-image/azuredeploy.tf rename to examples/azure-vm-from-user-image/main.tf diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf index 2f5cfca0f5a7..b3e94928978d 100644 --- a/examples/azure-vm-from-user-image/variables.tf +++ b/examples/azure-vm-from-user-image/variables.tf @@ -1,5 +1,6 @@ variable "resource_group" { description = "The name of the resource group in which the image to clone resides." + default = "myrg" } variable "image_uri" { @@ -8,22 +9,22 @@ variable "image_uri" { variable "os_type" { description = "Specifies the operating system Type, valid values are windows, linux." - default="linux" + default = "linux" } variable "location" { description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." - default="southcentralus" + default = "southcentralus" } variable "address_space" { description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." - default="10.0.0.0/16" + default = "10.0.0.0/24" } variable "subnet_prefix" { description = "The address prefix to use for the subnet." - default="10.0.0.0/24" + default = "10.0.0.0/24" } variable "storage_account_name" { @@ -32,12 +33,12 @@ variable "storage_account_name" { variable "storage_account_type" { description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." - default="Standard_LRS" + default = "Premium_LRS" } variable "vm_size" { description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." - default="Standard_DS1_v2" + default = "Standard_DS1_v2" } variable "hostname" { @@ -46,9 +47,10 @@ variable "hostname" { variable "admin_username" { description = "administrator user name" - default="vmadmin" + default = "vmadmin" } variable "admin_password" { description = "administrator password (recommended to disable password auth)" + default = "T3rr@f0rmP@ssword" } From 5c8ecd89384ec00514205e34eb45ca5de6b28f56 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Tue, 25 Apr 2017 13:07:01 -0500 Subject: [PATCH 14/68] prep for PR --- .travis.yml | 6 +++--- examples/azure-vm-from-user-image/after_deploy.sh | 9 +++++++++ examples/azure-vm-from-user-image/deploy.sh | 3 ++- 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 examples/azure-vm-from-user-image/after_deploy.sh diff --git a/.travis.yml b/.travis.yml index 2300d05045ec..a669ca462c75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,9 @@ branches: before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - - export IMAGE_URI=https://myrgdisks640.blob.core.windows.net/vhds/original-vm20170424164303.vhd - - export STORAGE_ACCOUNT_NAME=myrgdisks640 - - export RG=myrg + - export EXISTING_IMAGE_URI=https://myrgdisks640.blob.core.windows.net/vhds/original-vm20170424164303.vhd + - export EXISTING_STORAGE_ACCOUNT_NAME=myrgdisks640 + - export EXISTING_RESOURCE_GROUP=myrg # terraform deploy script deploy: diff --git a/examples/azure-vm-from-user-image/after_deploy.sh b/examples/azure-vm-from-user-image/after_deploy.sh new file mode 100644 index 000000000000..245aba38045e --- /dev/null +++ b/examples/azure-vm-from-user-image/after_deploy.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -o errexit -o nounset + +# cleanup deployed azure resources +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az group delete -y -n $KEY" diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh index 94a5d0a61aae..3adf165f8700 100755 --- a/examples/azure-vm-from-user-image/deploy.sh +++ b/examples/azure-vm-from-user-image/deploy.sh @@ -13,7 +13,8 @@ docker run --rm -it \ -c "cd /data; \ /bin/terraform get; \ /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$RG -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$IMAGE_URI -var storage_account_name=$STORAGE_ACCOUNT_NAME; /bin/terraform apply out.tfplan" + /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ + /bin/terraform apply out.tfplan" # TODO: determine external validation, possibly Azure CLI From 0267fcacf0f75dec5b8e2dfd06735c7e7489df8a Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Tue, 25 Apr 2017 13:42:34 -0500 Subject: [PATCH 15/68] removal of old folder --- examples/101-vm-simple-linux/.gitignore | 3 - examples/101-vm-simple-linux/README.md | 8 -- examples/101-vm-simple-linux/main.tf | 120 ---------------------- examples/101-vm-simple-linux/variables.tf | 78 -------------- 4 files changed, 209 deletions(-) delete mode 100644 examples/101-vm-simple-linux/.gitignore delete mode 100644 examples/101-vm-simple-linux/README.md delete mode 100644 examples/101-vm-simple-linux/main.tf delete mode 100644 examples/101-vm-simple-linux/variables.tf diff --git a/examples/101-vm-simple-linux/.gitignore b/examples/101-vm-simple-linux/.gitignore deleted file mode 100644 index a4f6eebd0a98..000000000000 --- a/examples/101-vm-simple-linux/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -terraform.tfstate* -terraform.tfvars* -provider.tf* diff --git a/examples/101-vm-simple-linux/README.md b/examples/101-vm-simple-linux/README.md deleted file mode 100644 index 92446ee9e970..000000000000 --- a/examples/101-vm-simple-linux/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Deploy a simple Linux VM -**ubuntu** - -This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy a A1 size VM in the resource group location and return the FQDN of the VM. - -This template takes a minimum amount of parameters and deploys a Linux VM, using the latest patched version. - -Azure requires that an application is added to Azure Active Directory to generate the client_id, client_secret, and tenant_id needed by Terraform (subscription_id can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this. \ No newline at end of file diff --git a/examples/101-vm-simple-linux/main.tf b/examples/101-vm-simple-linux/main.tf deleted file mode 100644 index f0ef742412d2..000000000000 --- a/examples/101-vm-simple-linux/main.tf +++ /dev/null @@ -1,120 +0,0 @@ -resource "azurerm_resource_group" "rg" { - name = "${var.resource_group}" - location = "${var.location}" -} - -resource "azurerm_virtual_network" "vnet" { - name = "${var.virtual_network_name}" - location = "${var.location}" - address_space = ["${var.address_space}"] - resource_group_name = "${azurerm_resource_group.rg.name}" -} - -resource "azurerm_subnet" "subnet" { - name = "${var.rg_prefix}subnet" - virtual_network_name = "${azurerm_virtual_network.vnet.name}" - resource_group_name = "${azurerm_resource_group.rg.name}" - address_prefix = "${var.subnet_prefix}" -} - -resource "azurerm_network_interface" "nic" { - name = "${var.rg_prefix}nic" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - - ip_configuration { - name = "${var.rg_prefix}ipconfig" - subnet_id = "${azurerm_subnet.subnet.id}" - private_ip_address_allocation = "Dynamic" - public_ip_address_id = "${azurerm_public_ip.pip.id}" - } -} - -resource "azurerm_public_ip" "pip" { - name = "${var.rg_prefix}-ip" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - public_ip_address_allocation = "dynamic" - domain_name_label = "${var.dns_name}" -} - -resource "azurerm_storage_account" "stor" { - name = "${var.hostname}stor" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - account_type = "${var.storage_account_type}" -} - -resource "azurerm_storage_container" "storc" { - name = "${var.hostname}-vhds" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_name = "${azurerm_storage_account.stor.name}" - container_access_type = "private" -} - -resource "azurerm_managed_disk" "disk1" { - name = "${var.hostname}-osdisk1" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "30" -} - -resource "azurerm_managed_disk" "disk2" { - name = "${var.hostname}-disk2" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "1023" -} - -resource "azurerm_virtual_machine" "vm" { - name = "${var.rg_prefix}vm" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - vm_size = "${var.vm_size}" - network_interface_ids = ["${azurerm_network_interface.nic.id}"] - - storage_image_reference { - publisher = "${var.image_publisher}" - offer = "${var.image_offer}" - sku = "${var.image_sku}" - version = "${var.image_version}" - } - - storage_os_disk { - name = "${var.hostname}-osdisk1" - vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}${azurerm_storage_container.storc.name}/${var.hostname}-osdisk1.vhd" - caching = "ReadWrite" - create_option = "FromImage" - } - - storage_data_disk { - name = "${var.hostname}-disk2" - vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}${azurerm_storage_container.storc.name}/${var.hostname}-disk2.vhd" - disk_size_gb = "1023" - create_option = "Empty" - lun = 0 - } - - os_profile { - computer_name = "${var.hostname}" - admin_username = "${var.admin_username}" - admin_password = "${var.admin_password}" - } - - boot_diagnostics { - enabled = "true" - storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" - } -} - -output "hostname" { - value = "${var.hostname}" -} - -output "vm_fqdn" { - value = "${azurerm_public_ip.pip.fqdn}" -} \ No newline at end of file diff --git a/examples/101-vm-simple-linux/variables.tf b/examples/101-vm-simple-linux/variables.tf deleted file mode 100644 index b2ab327217fa..000000000000 --- a/examples/101-vm-simple-linux/variables.tf +++ /dev/null @@ -1,78 +0,0 @@ -variable "resource_group" { - description = "The name of the resource group in which to create the virtual network." - default = "myresourcegroup" -} - -variable "rg_prefix" { - description = "The shortened abbreviation to represent your resource group that will go on the front of some resources." - default = "rg" -} - -variable "location" { - description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." - default = "southcentralus" -} - -variable "virtual_network_name" { - description = "The name for the virtual network." - default = "vnet" -} - -variable "address_space" { - description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." - default = "10.0.0.0/16" -} - -variable "subnet_prefix" { - description = "The address prefix to use for the subnet." - default = "10.0.10.0/24" -} - -variable "storage_account_type" { - description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." - default = "Standard_LRS" -} - -variable "vm_size" { - description = "Specifies the name of the virtual machine resource. Changing this forces a new resource to be created." - default = "Standard_A0" -} - -variable "image_publisher" { - description = "name of the publisher of the image (az vm image list)" - default = "Canonical" -} - -variable "image_offer" { - description = "the name of the offer (az vm image list)" - default = "UbuntuServer" -} - -variable "image_sku" { - description = "image sku to apply (az vm image list)" - default = "16.04-LTS" -} - -variable "image_version" { - description = "version of the image to apply (az vm image list)" - default = "latest" -} - -variable "hostname" { - description = "VM name referenced also in storage-related names." - default = "myvm" -} - -variable "dns_name" { - description = " Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." -} - -variable "admin_username" { - description = "administrator user name" - default = "vmadmin" -} - -variable "admin_password" { - description = "administrator password (recommended to disable password auth)" - default = "T3rr@f0rmP@ssword" -} From f9bf6baaf3724acc7bbc72cc015a7c40f79db2ab Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Tue, 25 Apr 2017 18:07:09 -0500 Subject: [PATCH 16/68] prep for PR --- examples/azure-vm-from-user-image/after_deploy.sh | 6 ++++-- examples/azure-vm-from-user-image/deploy.mac.sh | 13 ++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) mode change 100644 => 100755 examples/azure-vm-from-user-image/after_deploy.sh diff --git a/examples/azure-vm-from-user-image/after_deploy.sh b/examples/azure-vm-from-user-image/after_deploy.sh old mode 100644 new mode 100755 index 245aba38045e..8a5624eb7681 --- a/examples/azure-vm-from-user-image/after_deploy.sh +++ b/examples/azure-vm-from-user-image/after_deploy.sh @@ -2,8 +2,10 @@ set -o errexit -o nounset -# cleanup deployed azure resources docker run --rm -it \ azuresdk/azure-cli-python \ sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ - az group delete -y -n $KEY" + az vm delete --name $KEY --resource-group permanent -y; \ + az network nic delete --name $KEY'nic' --resource-group permanent; \ + az network vnet delete --name $KEY'vnet' --resource-group permanent; \ + az network public-ip delete --name $KEY'-ip' --resource-group permanent;" diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh index d66b85079b19..eb2808ef5502 100755 --- a/examples/azure-vm-from-user-image/deploy.mac.sh +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -5,13 +5,8 @@ set -o errexit -o nounset # generate a unique string for CI deployment export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) -export IMAGE_URI=https://myrgdisks640.blob.core.windows.net/vhds/original-vm20170424164303.vhd -export STORAGE_ACCOUNT_NAME=myrgdisks640 -export RG=myrg +export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd +export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor +export EXISTING_RESOURCE_GROUP=permanent -/bin/sh ./deploy.sh - -# docker run --rm -it \ -# azuresdk/azure-cli-python \ -# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ -# az group delete -y -n $KEY" +/bin/sh ./after_deploy.sh From cec06795654b98efca06c0235d42fb481e4f0718 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Tue, 25 Apr 2017 18:11:07 -0500 Subject: [PATCH 17/68] wrong args for travis --- .travis.yml | 6 +++--- examples/azure-vm-from-user-image/deploy.sh | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index a669ca462c75..b559eea4327c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,9 @@ branches: before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - - export EXISTING_IMAGE_URI=https://myrgdisks640.blob.core.windows.net/vhds/original-vm20170424164303.vhd - - export EXISTING_STORAGE_ACCOUNT_NAME=myrgdisks640 - - export EXISTING_RESOURCE_GROUP=myrg + - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd + - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor + - export EXISTING_RESOURCE_GROUP=permanent # terraform deploy script deploy: diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh index 3adf165f8700..2558ebce5ff1 100755 --- a/examples/azure-vm-from-user-image/deploy.sh +++ b/examples/azure-vm-from-user-image/deploy.sh @@ -16,8 +16,6 @@ docker run --rm -it \ /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ /bin/terraform apply out.tfplan" -# TODO: determine external validation, possibly Azure CLI - # echo "Setting git user name" # git config user.name $GH_USER_NAME # From d78e8bd4bdad292eff2a0dacc92299d5798e15d3 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 10:52:16 -0500 Subject: [PATCH 18/68] more PR prep --- examples/azure-vm-from-user-image/.gitignore | 3 --- examples/azure-vm-from-user-image/provider.tf | 6 ++++++ examples/azure-vm-from-user-image/provider.tf.example | 6 ------ .../{terraform.tfvars.example => terraform.tfvars} | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 examples/azure-vm-from-user-image/.gitignore create mode 100644 examples/azure-vm-from-user-image/provider.tf delete mode 100644 examples/azure-vm-from-user-image/provider.tf.example rename examples/azure-vm-from-user-image/{terraform.tfvars.example => terraform.tfvars} (92%) diff --git a/examples/azure-vm-from-user-image/.gitignore b/examples/azure-vm-from-user-image/.gitignore deleted file mode 100644 index 7773fa9ecc5d..000000000000 --- a/examples/azure-vm-from-user-image/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -terraform.tfstate* -terraform.tfvars -provider.tf diff --git a/examples/azure-vm-from-user-image/provider.tf b/examples/azure-vm-from-user-image/provider.tf new file mode 100644 index 000000000000..bdf0583f3259 --- /dev/null +++ b/examples/azure-vm-from-user-image/provider.tf @@ -0,0 +1,6 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } diff --git a/examples/azure-vm-from-user-image/provider.tf.example b/examples/azure-vm-from-user-image/provider.tf.example deleted file mode 100644 index a0b5e46772f5..000000000000 --- a/examples/azure-vm-from-user-image/provider.tf.example +++ /dev/null @@ -1,6 +0,0 @@ -provider "azurerm" { - subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" - client_id = "REPLACE-WITH-YOUR-CLIENT-ID" - client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" - tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -} diff --git a/examples/azure-vm-from-user-image/terraform.tfvars.example b/examples/azure-vm-from-user-image/terraform.tfvars similarity index 92% rename from examples/azure-vm-from-user-image/terraform.tfvars.example rename to examples/azure-vm-from-user-image/terraform.tfvars index 6cc72c9218be..d217db2f7a0a 100644 --- a/examples/azure-vm-from-user-image/terraform.tfvars.example +++ b/examples/azure-vm-from-user-image/terraform.tfvars @@ -10,4 +10,4 @@ storage_account_type = "Standard_LRS" vm_size = "Standard_DS1_v2" hostname = "HOSTNAME" admin_username = "vmadmin" -admin_password = "T3rr@f0rmP@ssword" \ No newline at end of file +admin_password = "YOURPASSWORDHERE" From 6bf2df2d6608eddf3c8707c848dab418927393f5 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Wed, 26 Apr 2017 10:54:22 -0500 Subject: [PATCH 19/68] updated README --- examples/azure-vm-from-user-image/README.md | 78 ++------------------- 1 file changed, 7 insertions(+), 71 deletions(-) diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md index f391b0b8f40f..455b0bcb1a5f 100644 --- a/examples/azure-vm-from-user-image/README.md +++ b/examples/azure-vm-from-user-image/README.md @@ -1,8 +1,7 @@ # [Create a Virtual Machine from a User Image](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-deploy-templates#create-a-custom-vm-image) - - - +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image) Azure Quickstart Template. Changes to the ARM template may have occured since the creation of this example may not be reflected here. + @@ -11,64 +10,8 @@ This template allows you to create a Virtual Machine from an unmanaged User image vhd. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. -If you are looking to accomplish the above scenario through PowerShell instead of a template, you can use a PowerShell script like below - -##### Variables - ## Global - $rgName = "testrg" - $location = "westus" - - ## Storage - $storageName = "teststore" - $storageType = "Standard_GRS" - - ## Network - $nicname = "testnic" - $subnet1Name = "subnet1" - $vnetName = "testnet" - $vnetAddressPrefix = "10.0.0.0/16" - $vnetSubnetAddressPrefix = "10.0.0.0/24" - - ## Compute - $vmName = "testvm" - $computerName = "testcomputer" - $vmSize = "Standard_A2" - $osDiskName = $vmName + "osDisk" - -##### Resource Group - New-AzureRmResourceGroup -Name $rgName -Location $location - -##### Storage - $storageacc = New-AzureRmStorageAccount -ResourceGroupName $rgName -Name $storageName -Type $storageType -Location $location - -##### Network - $pip = New-AzureRmPublicIpAddress -Name $nicname -ResourceGroupName $rgName -Location $location -AllocationMethod Dynamic - $subnetconfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet1Name -AddressPrefix $vnetSubnetAddressPrefix - $vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location -AddressPrefix $vnetAddressPrefix -Subnet $subnetconfig - $nic = New-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $rgName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id - -##### Compute - ## Setup local VM object - $cred = Get-Credential - $vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize - $vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $computerName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate - - $vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id - - $osDiskUri = "http://test.blob.core.windows.net/vmcontainer10798c80-131-1231-a94a-f9d2a712251f/osDisk.10798c80-2919-4100-a94a-f9d2a712251f.vhd" - $imageUri = "http://test.blob.core.windows.net/system/Microsoft.Compute/Images/captured/image-osDisk.8b021d87-913c-4f94-a01a-944ad92d7388.vhd" - $vm = Set-AzureRmVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri -CreateOption fromImage -SourceImageUri $imageUri -Windows - - $dataImageUri = "http://test.blob.core.windows.net/system/Microsoft.Compute/Images/captured/image-dataDisk-0.8b021d87-913c-4f94-a01a-944ad92d7388.vhd" - $dataDiskUri = "http://test.blob.core.windows.net/vmcontainer10798c80-sa11-41sa-dsad-f9d2a712251f/dataDisk-0.10798c80-2919-4100-a94a-f9d2a712251f.vhd" - $vm = Add-AzureRmVMDataDisk -VM $vm -Name "dd1" -VhdUri $dataDiskUri -SourceImageUri $dataImageUri -Lun 0 -CreateOption fromImage - - ## Create the VM in Azure - New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm -Verbose - - -## azuredeploy.tf -The `azuredeploy.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. ## outputs.tf This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. @@ -77,16 +20,9 @@ This data is outputted when `terraform apply` is called, and can be queried usin Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. ## terraform.tfvars -If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +If you are committing this template to source control, please insure that you add this file to your `.gitignore` file. ## variables.tf The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. - -## .gitignore -If you are committing this template to source control, please insure that the following files are added to your `.gitignore` file. - -``` -terraform.tfstate* -terraform.tfvars* -provider.tf* -``` From b22cff0d170f72e8f098f85d77daf1ac129f7df3 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 10:54:32 -0500 Subject: [PATCH 20/68] commented out variables in terraform.tfvars --- .../azure-vm-from-user-image/terraform.tfvars | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/azure-vm-from-user-image/terraform.tfvars b/examples/azure-vm-from-user-image/terraform.tfvars index d217db2f7a0a..15da2a9c6ca7 100644 --- a/examples/azure-vm-from-user-image/terraform.tfvars +++ b/examples/azure-vm-from-user-image/terraform.tfvars @@ -1,13 +1,13 @@ -resource_group = "myresourcegroup" -image_uri = "https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd" -primary_blob_endpoint = "https://DISK.blob.core.windows.net/" -location = "southcentralus" -os_type = "linux" -address_space = "10.0.0.0/16" -subnet_prefix = "10.0.0.0/24" -storage_account_name = "STOR-ACCT-NAME" -storage_account_type = "Standard_LRS" -vm_size = "Standard_DS1_v2" -hostname = "HOSTNAME" -admin_username = "vmadmin" -admin_password = "YOURPASSWORDHERE" +# resource_group = "myresourcegroup" +# image_uri = "https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd" +# primary_blob_endpoint = "https://DISK.blob.core.windows.net/" +# location = "southcentralus" +# os_type = "linux" +# address_space = "10.0.0.0/16" +# subnet_prefix = "10.0.0.0/24" +# storage_account_name = "STOR-ACCT-NAME" +# storage_account_type = "Standard_LRS" +# vm_size = "Standard_DS1_v2" +# hostname = "HOSTNAME" +# admin_username = "vmadmin" +# admin_password = "YOURPASSWORDHERE" From 0843f451307b4c2a9740c5a9dcba0c0adda69f7c Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 16:14:34 -0500 Subject: [PATCH 21/68] Topic 101 vm from user image (#2) * initial commit - 101-vm-from-user-image * added tfvars and info for README * added CI config; added sane defaults for variables; updated deployment script, added mac specific deployment for local testing * prep for PR --- .travis.yml | 15 +++-- examples/azure-vm-from-user-image/README.md | 28 +++++++++ .../azure-vm-from-user-image/after_deploy.sh | 11 ++++ .../azure-vm-from-user-image/deploy.mac.sh | 12 ++++ examples/azure-vm-from-user-image/deploy.sh | 37 +++++++++++ examples/azure-vm-from-user-image/main.tf | 62 +++++++++++++++++++ examples/azure-vm-from-user-image/outputs.tf | 11 ++++ examples/azure-vm-from-user-image/provider.tf | 6 ++ .../azure-vm-from-user-image/terraform.tfvars | 13 ++++ .../azure-vm-from-user-image/variables.tf | 56 +++++++++++++++++ 10 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 examples/azure-vm-from-user-image/README.md create mode 100755 examples/azure-vm-from-user-image/after_deploy.sh create mode 100755 examples/azure-vm-from-user-image/deploy.mac.sh create mode 100755 examples/azure-vm-from-user-image/deploy.sh create mode 100644 examples/azure-vm-from-user-image/main.tf create mode 100644 examples/azure-vm-from-user-image/outputs.tf create mode 100644 examples/azure-vm-from-user-image/provider.tf create mode 100644 examples/azure-vm-from-user-image/terraform.tfvars create mode 100644 examples/azure-vm-from-user-image/variables.tf diff --git a/.travis.yml b/.travis.yml index 688b223f7a98..b559eea4327c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,18 +5,25 @@ services: language: generic +# on branches: ignore multiple commits that will queue build jobs, just run latest commit +git: + depth: 1 + # establish environment variables env: - - TEST_DIR=examples/azure-vm-simple-linux + - TEST_DIR=examples/azure-vm-from-user-image branches: only: - - master + - /^(?i:topic)-.*$/ # install terraform before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) + - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd + - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor + - export EXISTING_RESOURCE_GROUP=permanent # terraform deploy script deploy: @@ -25,7 +32,7 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.sh on: repo: 10thmagnitude/terraform - branch: master + branch: topic-101-vm-from-user-image -# destroy resources with Azure CLI +# cleanup after_deploy: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./after_deploy.sh diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md new file mode 100644 index 000000000000..455b0bcb1a5f --- /dev/null +++ b/examples/azure-vm-from-user-image/README.md @@ -0,0 +1,28 @@ +# [Create a Virtual Machine from a User Image](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-deploy-templates#create-a-custom-vm-image) + +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image) Azure Quickstart Template. Changes to the ARM template may have occured since the creation of this example may not be reflected here. + + + + + +> Prerequisite - The generalized image VHD should exist, as well as a Storage Account for boot diagnostics + +This template allows you to create a Virtual Machine from an unmanaged User image vhd. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. + +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +If you are committing this template to source control, please insure that you add this file to your `.gitignore` file. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. diff --git a/examples/azure-vm-from-user-image/after_deploy.sh b/examples/azure-vm-from-user-image/after_deploy.sh new file mode 100755 index 000000000000..8a5624eb7681 --- /dev/null +++ b/examples/azure-vm-from-user-image/after_deploy.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -o errexit -o nounset + +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az vm delete --name $KEY --resource-group permanent -y; \ + az network nic delete --name $KEY'nic' --resource-group permanent; \ + az network vnet delete --name $KEY'vnet' --resource-group permanent; \ + az network public-ip delete --name $KEY'-ip' --resource-group permanent;" diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh new file mode 100755 index 000000000000..eb2808ef5502 --- /dev/null +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -o errexit -o nounset + +# generate a unique string for CI deployment +export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) +export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) +export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd +export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor +export EXISTING_RESOURCE_GROUP=permanent + +/bin/sh ./after_deploy.sh diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.sh new file mode 100755 index 000000000000..2558ebce5ff1 --- /dev/null +++ b/examples/azure-vm-from-user-image/deploy.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -o errexit -o nounset + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "cd /data; \ + /bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ + /bin/terraform apply out.tfplan" + +# echo "Setting git user name" +# git config user.name $GH_USER_NAME +# +# echo "Setting git user email" +# git config user.email $GH_USER_EMAIL +# +# echo "Adding git upstream remote" +# git remote add upstream "https://$GH_TOKEN@github.com/$GH_REPO.git" +# +# git checkout master + + +# +# NOW=$(TZ=America/Chicago date) +# +# git commit -m "tfstate: $NOW [ci skip]" +# +# echo "Pushing changes to upstream master" +# git push upstream master diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf new file mode 100644 index 000000000000..28edf99204b5 --- /dev/null +++ b/examples/azure-vm-from-user-image/main.tf @@ -0,0 +1,62 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_virtual_network" "vnet" { + name = "${var.hostname}vnet" + location = "${var.location}" + address_space = ["${var.address_space}"] + resource_group_name = "${azurerm_resource_group.rg.name}" +} + +resource "azurerm_subnet" "subnet" { + name = "${var.hostname}subnet" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + address_prefix = "${var.subnet_prefix}" +} + +resource "azurerm_network_interface" "nic" { + name = "${var.hostname}nic" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + + ip_configuration { + name = "${var.hostname}ipconfig" + subnet_id = "${azurerm_subnet.subnet.id}" + private_ip_address_allocation = "Dynamic" + public_ip_address_id = "${azurerm_public_ip.pip.id}" + } +} + +resource "azurerm_public_ip" "pip" { + name = "${var.hostname}-ip" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + public_ip_address_allocation = "dynamic" + domain_name_label = "${var.hostname}" +} + +resource "azurerm_virtual_machine" "vm" { + name = "${var.hostname}" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + vm_size = "${var.vm_size}" + network_interface_ids = ["${azurerm_network_interface.nic.id}"] + + storage_os_disk { + name = "${var.hostname}-osdisk1" + image_uri = "${var.image_uri}" + vhd_uri = "https://${var.storage_account_name}.blob.core.windows.net/vhds/${var.hostname}osdisk.vhd" + os_type = "${var.os_type}" + caching = "ReadWrite" + create_option = "FromImage" + } + + os_profile { + computer_name = "${var.hostname}" + admin_username = "${var.admin_username}" + admin_password = "${var.admin_password}" + } +} diff --git a/examples/azure-vm-from-user-image/outputs.tf b/examples/azure-vm-from-user-image/outputs.tf new file mode 100644 index 000000000000..e0e255a9e01c --- /dev/null +++ b/examples/azure-vm-from-user-image/outputs.tf @@ -0,0 +1,11 @@ +output "hostname" { + value = "${var.hostname}" +} + +output "vm_fqdn" { + value = "${azurerm_public_ip.pip.fqdn}" +} + +output "sshCommand" { + value = "${concat("ssh ", var.admin_username, "@", azurerm_public_ip.pip.fqdn)}" +} diff --git a/examples/azure-vm-from-user-image/provider.tf b/examples/azure-vm-from-user-image/provider.tf new file mode 100644 index 000000000000..bdf0583f3259 --- /dev/null +++ b/examples/azure-vm-from-user-image/provider.tf @@ -0,0 +1,6 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } diff --git a/examples/azure-vm-from-user-image/terraform.tfvars b/examples/azure-vm-from-user-image/terraform.tfvars new file mode 100644 index 000000000000..15da2a9c6ca7 --- /dev/null +++ b/examples/azure-vm-from-user-image/terraform.tfvars @@ -0,0 +1,13 @@ +# resource_group = "myresourcegroup" +# image_uri = "https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd" +# primary_blob_endpoint = "https://DISK.blob.core.windows.net/" +# location = "southcentralus" +# os_type = "linux" +# address_space = "10.0.0.0/16" +# subnet_prefix = "10.0.0.0/24" +# storage_account_name = "STOR-ACCT-NAME" +# storage_account_type = "Standard_LRS" +# vm_size = "Standard_DS1_v2" +# hostname = "HOSTNAME" +# admin_username = "vmadmin" +# admin_password = "YOURPASSWORDHERE" diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf new file mode 100644 index 000000000000..b3e94928978d --- /dev/null +++ b/examples/azure-vm-from-user-image/variables.tf @@ -0,0 +1,56 @@ +variable "resource_group" { + description = "The name of the resource group in which the image to clone resides." + default = "myrg" +} + +variable "image_uri" { + description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." +} + +variable "os_type" { + description = "Specifies the operating system Type, valid values are windows, linux." + default = "linux" +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "address_space" { + description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." + default = "10.0.0.0/24" +} + +variable "subnet_prefix" { + description = "The address prefix to use for the subnet." + default = "10.0.0.0/24" +} + +variable "storage_account_name" { + description = "The name of the storage account in which the image from which you are cloning resides." +} + +variable "storage_account_type" { + description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." + default = "Premium_LRS" +} + +variable "vm_size" { + description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." + default = "Standard_DS1_v2" +} + +variable "hostname" { + description = "VM name referenced also in storage-related names. This is also used as the label for the Domain Name and to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." +} + +variable "admin_username" { + description = "administrator user name" + default = "vmadmin" +} + +variable "admin_password" { + description = "administrator password (recommended to disable password auth)" + default = "T3rr@f0rmP@ssword" +} From 49caea553c384dc44f0d367c21bf7a2b1274df2c Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 16:29:11 -0500 Subject: [PATCH 22/68] added new template --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b559eea4327c..9412e69721ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ git: # establish environment variables env: + - TEST_DIR=examples/azure-vm-simple-linux - TEST_DIR=examples/azure-vm-from-user-image branches: @@ -32,7 +33,7 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.sh on: repo: 10thmagnitude/terraform - branch: topic-101-vm-from-user-image + branch: master # cleanup after_deploy: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./after_deploy.sh From 2236828c1f0d3231cb4d86a49213ba141f769bab Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 16:37:46 -0500 Subject: [PATCH 23/68] oops, left off master --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9412e69721ff..af6a783e4aa3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ env: branches: only: + - master - /^(?i:topic)-.*$/ # install terraform From 7f8fe25583bd941ec3ce1a0fa79eb557ed97a4bf Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 19:09:46 -0500 Subject: [PATCH 24/68] prep for PR --- examples/azure-vm-simple-linux/.gitignore | 3 - examples/azure-vm-simple-linux/README.md | 36 ------ .../azure-vm-simple-linux/after_deploy.sh | 9 -- examples/azure-vm-simple-linux/deploy.mac.sh | 14 --- examples/azure-vm-simple-linux/deploy.sh | 17 --- examples/azure-vm-simple-linux/main.tf | 112 ------------------ examples/azure-vm-simple-linux/outputs.tf | 11 -- .../azure-vm-simple-linux/provider.tf.example | 6 - .../terraform.tfvars.example | 6 - examples/azure-vm-simple-linux/variables.tf | 75 ------------ 10 files changed, 289 deletions(-) delete mode 100644 examples/azure-vm-simple-linux/.gitignore delete mode 100644 examples/azure-vm-simple-linux/README.md delete mode 100755 examples/azure-vm-simple-linux/after_deploy.sh delete mode 100755 examples/azure-vm-simple-linux/deploy.mac.sh delete mode 100755 examples/azure-vm-simple-linux/deploy.sh delete mode 100644 examples/azure-vm-simple-linux/main.tf delete mode 100644 examples/azure-vm-simple-linux/outputs.tf delete mode 100644 examples/azure-vm-simple-linux/provider.tf.example delete mode 100644 examples/azure-vm-simple-linux/terraform.tfvars.example delete mode 100644 examples/azure-vm-simple-linux/variables.tf diff --git a/examples/azure-vm-simple-linux/.gitignore b/examples/azure-vm-simple-linux/.gitignore deleted file mode 100644 index 7773fa9ecc5d..000000000000 --- a/examples/azure-vm-simple-linux/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -terraform.tfstate* -terraform.tfvars -provider.tf diff --git a/examples/azure-vm-simple-linux/README.md b/examples/azure-vm-simple-linux/README.md deleted file mode 100644 index a0ab5f63451e..000000000000 --- a/examples/azure-vm-simple-linux/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Very simple deployment of a Linux VM - - - - - - - - -This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy a A1 size VM in the resource group location and return the FQDN of the VM. - -This template takes a minimum amount of parameters and deploys a Linux VM, using the latest patched version. - -## main.tf -The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. - -## outputs.tf -This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. - -## provider.tf -Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. - -## terraform.tfvars -If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. - -## variables.tf -The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. - -## .gitignore -If you are committing this template to source control, please insure that the following files are added to your `.gitignore` file. - -``` -terraform.tfstate* -terraform.tfvars -provider.tf* -``` \ No newline at end of file diff --git a/examples/azure-vm-simple-linux/after_deploy.sh b/examples/azure-vm-simple-linux/after_deploy.sh deleted file mode 100755 index 245aba38045e..000000000000 --- a/examples/azure-vm-simple-linux/after_deploy.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -# cleanup deployed azure resources -docker run --rm -it \ - azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ - az group delete -y -n $KEY" diff --git a/examples/azure-vm-simple-linux/deploy.mac.sh b/examples/azure-vm-simple-linux/deploy.mac.sh deleted file mode 100755 index f0bb60f8bb8b..000000000000 --- a/examples/azure-vm-simple-linux/deploy.mac.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -# generate a unique string for CI deployment -export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) -export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) - -/bin/sh ./deploy.sh - -# docker run --rm -it \ -# azuresdk/azure-cli-python \ -# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ -# az group delete -y -n $KEY" diff --git a/examples/azure-vm-simple-linux/deploy.sh b/examples/azure-vm-simple-linux/deploy.sh deleted file mode 100755 index 5347f3a838c6..000000000000 --- a/examples/azure-vm-simple-linux/deploy.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -docker run --rm -it \ - -e ARM_CLIENT_ID \ - -e ARM_CLIENT_SECRET \ - -e ARM_SUBSCRIPTION_ID \ - -e ARM_TENANT_ID \ - -v $(pwd):/data \ - --entrypoint "/bin/sh" \ - hashicorp/terraform:light \ - -c "cd /data; \ - /bin/terraform get; \ - /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD; \ - /bin/terraform apply out.tfplan" diff --git a/examples/azure-vm-simple-linux/main.tf b/examples/azure-vm-simple-linux/main.tf deleted file mode 100644 index cf931d0f9e4e..000000000000 --- a/examples/azure-vm-simple-linux/main.tf +++ /dev/null @@ -1,112 +0,0 @@ -resource "azurerm_resource_group" "rg" { - name = "${var.resource_group}" - location = "${var.location}" -} - -resource "azurerm_virtual_network" "vnet" { - name = "${var.virtual_network_name}" - location = "${var.location}" - address_space = ["${var.address_space}"] - resource_group_name = "${azurerm_resource_group.rg.name}" -} - -resource "azurerm_subnet" "subnet" { - name = "${var.rg_prefix}subnet" - virtual_network_name = "${azurerm_virtual_network.vnet.name}" - resource_group_name = "${azurerm_resource_group.rg.name}" - address_prefix = "${var.subnet_prefix}" -} - -resource "azurerm_network_interface" "nic" { - name = "${var.rg_prefix}nic" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - - ip_configuration { - name = "${var.rg_prefix}ipconfig" - subnet_id = "${azurerm_subnet.subnet.id}" - private_ip_address_allocation = "Dynamic" - public_ip_address_id = "${azurerm_public_ip.pip.id}" - } -} - -resource "azurerm_public_ip" "pip" { - name = "${var.rg_prefix}-ip" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - public_ip_address_allocation = "dynamic" - domain_name_label = "${var.dns_name}" -} - -resource "azurerm_storage_account" "stor" { - name = "${var.dns_name}stor" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - account_type = "${var.storage_account_type}" -} - -resource "azurerm_storage_container" "storc" { - name = "${var.hostname}-vhds" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_name = "${azurerm_storage_account.stor.name}" - container_access_type = "private" -} - -resource "azurerm_managed_disk" "disk1" { - name = "${var.hostname}-osdisk1" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "30" -} - -resource "azurerm_managed_disk" "disk2" { - name = "${var.hostname}-disk2" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "1023" -} - -resource "azurerm_virtual_machine" "vm" { - name = "${var.rg_prefix}vm" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - vm_size = "${var.vm_size}" - network_interface_ids = ["${azurerm_network_interface.nic.id}"] - - storage_image_reference { - publisher = "${var.image_publisher}" - offer = "${var.image_offer}" - sku = "${var.image_sku}" - version = "${var.image_version}" - } - - storage_os_disk { - name = "${var.hostname}-osdisk1" - vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}${azurerm_storage_container.storc.name}/${var.hostname}-osdisk1.vhd" - caching = "ReadWrite" - create_option = "FromImage" - } - - storage_data_disk { - name = "${var.hostname}-disk2" - vhd_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}${azurerm_storage_container.storc.name}/${var.hostname}-disk2.vhd" - disk_size_gb = "1023" - create_option = "Empty" - lun = 0 - } - - os_profile { - computer_name = "${var.hostname}" - admin_username = "${var.admin_username}" - admin_password = "${var.admin_password}" - } - - boot_diagnostics { - enabled = "true" - storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" - } -} diff --git a/examples/azure-vm-simple-linux/outputs.tf b/examples/azure-vm-simple-linux/outputs.tf deleted file mode 100644 index 9e3c2f0712bc..000000000000 --- a/examples/azure-vm-simple-linux/outputs.tf +++ /dev/null @@ -1,11 +0,0 @@ -output "hostname" { - value = "${var.hostname}" -} - -output "vm_fqdn" { - value = "${azurerm_public_ip.pip.fqdn}" -} - -output "sshCommand" { - value = "ssh ${var.admin_username}@${azurerm_public_ip.pip.fqdn}" -} diff --git a/examples/azure-vm-simple-linux/provider.tf.example b/examples/azure-vm-simple-linux/provider.tf.example deleted file mode 100644 index 327ceb55eefa..000000000000 --- a/examples/azure-vm-simple-linux/provider.tf.example +++ /dev/null @@ -1,6 +0,0 @@ -provider "azurerm" { - subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" - client_id = "REPLACE-WITH-YOUR-CLIENT-ID" - client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" - tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -} \ No newline at end of file diff --git a/examples/azure-vm-simple-linux/terraform.tfvars.example b/examples/azure-vm-simple-linux/terraform.tfvars.example deleted file mode 100644 index 262093ba52f9..000000000000 --- a/examples/azure-vm-simple-linux/terraform.tfvars.example +++ /dev/null @@ -1,6 +0,0 @@ -resource_group = "myresourcegroup" -rg_prefix = "rg" -hostname = "myvm" -dns_name = "mydnsname" -location = "southcentralus" -admin_password = "T3rr@f0rmP@ssword" diff --git a/examples/azure-vm-simple-linux/variables.tf b/examples/azure-vm-simple-linux/variables.tf deleted file mode 100644 index 6d65a0277060..000000000000 --- a/examples/azure-vm-simple-linux/variables.tf +++ /dev/null @@ -1,75 +0,0 @@ -variable "resource_group" { - description = "The name of the resource group in which to create the virtual network." -} - -variable "rg_prefix" { - description = "The shortened abbreviation to represent your resource group that will go on the front of some resources." - default = "rg" -} - -variable "hostname" { - description = "VM name referenced also in storage-related names." -} - -variable "dns_name" { - description = " Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." -} - -variable "location" { - description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." - default = "southcentralus" -} - -variable "virtual_network_name" { - description = "The name for the virtual network." - default = "vnet" -} - -variable "address_space" { - description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." - default = "10.0.0.0/16" -} - -variable "subnet_prefix" { - description = "The address prefix to use for the subnet." - default = "10.0.10.0/24" -} - -variable "storage_account_type" { - description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." - default = "Standard_LRS" -} - -variable "vm_size" { - description = "Specifies the name of the virtual machine resource. Changing this forces a new resource to be created." - default = "Standard_A0" -} - -variable "image_publisher" { - description = "name of the publisher of the image (az vm image list)" - default = "Canonical" -} - -variable "image_offer" { - description = "the name of the offer (az vm image list)" - default = "UbuntuServer" -} - -variable "image_sku" { - description = "image sku to apply (az vm image list)" - default = "16.04-LTS" -} - -variable "image_version" { - description = "version of the image to apply (az vm image list)" - default = "latest" -} - -variable "admin_username" { - description = "administrator user name" - default = "vmadmin" -} - -variable "admin_password" { - description = "administrator password (recommended to disable password auth)" -} From eecb2d2bd2ccd793fecfac7b4628388febf7e035 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 20:50:48 -0500 Subject: [PATCH 25/68] correct repository for destination --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 875765d83b66..544b49bb33f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ deploy: skip_cleanup: true script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.sh on: - repo: 10thmagnitude/terraform + repo: harijayms/terraform branch: master # cleanup From 92e341d38bca428ada134091b262ad6937ff4d2f Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 21:38:23 -0500 Subject: [PATCH 26/68] renamed scripts to be more intuitive; added check for docker --- .travis.yml | 4 ++-- .../{after_deploy.sh => after_deploy.ci.sh} | 0 .../{deploy.sh => deploy.ci.sh} | 4 ++-- .../azure-vm-from-user-image/deploy.mac.sh | 22 ++++++++++++------- 4 files changed, 18 insertions(+), 12 deletions(-) rename examples/azure-vm-from-user-image/{after_deploy.sh => after_deploy.ci.sh} (100%) rename examples/azure-vm-from-user-image/{deploy.sh => deploy.ci.sh} (95%) diff --git a/.travis.yml b/.travis.yml index 544b49bb33f5..2e9151fa24c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,10 +31,10 @@ before_deploy: deploy: - provider: script skip_cleanup: true - script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.sh + script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform branch: master # cleanup -after_deploy: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./after_deploy.sh +after_deploy: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./after_deploy.ci.sh diff --git a/examples/azure-vm-from-user-image/after_deploy.sh b/examples/azure-vm-from-user-image/after_deploy.ci.sh similarity index 100% rename from examples/azure-vm-from-user-image/after_deploy.sh rename to examples/azure-vm-from-user-image/after_deploy.ci.sh diff --git a/examples/azure-vm-from-user-image/deploy.sh b/examples/azure-vm-from-user-image/deploy.ci.sh similarity index 95% rename from examples/azure-vm-from-user-image/deploy.sh rename to examples/azure-vm-from-user-image/deploy.ci.sh index 2558ebce5ff1..f45c5bb2a6cd 100755 --- a/examples/azure-vm-from-user-image/deploy.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -8,10 +8,10 @@ docker run --rm -it \ -e ARM_SUBSCRIPTION_ID \ -e ARM_TENANT_ID \ -v $(pwd):/data \ + --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "cd /data; \ - /bin/terraform get; \ + -c "/bin/terraform get; \ /bin/terraform validate; \ /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ /bin/terraform apply out.tfplan" diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh index eb2808ef5502..acd4ca7028fc 100755 --- a/examples/azure-vm-from-user-image/deploy.mac.sh +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -2,11 +2,17 @@ set -o errexit -o nounset -# generate a unique string for CI deployment -export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) -export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) -export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd -export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor -export EXISTING_RESOURCE_GROUP=permanent - -/bin/sh ./after_deploy.sh +if docker -v; then + + # generate a unique string for CI deployment + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) + export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd + export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor + export EXISTING_RESOURCE_GROUP=permanent + + /bin/sh ./deploy.ci.sh + +else + echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" +fi From 23627c80a8acab7b32ec66a3267f00edf08972f4 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Wed, 26 Apr 2017 22:15:44 -0500 Subject: [PATCH 27/68] merge vm simple; vm from image --- .travis.yml | 2 +- .../README.md | 24 ++++ .../after_deploy.ci.sh | 9 ++ .../deploy.ci.sh | 17 +++ .../deploy.mac.sh | 15 +++ .../main.tf | 104 ++++++++++++++++++ .../outputs.tf | 11 ++ .../provider.tf | 7 ++ .../terraform.tfvars | 8 ++ .../variables.tf | 75 +++++++++++++ 10 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 examples/azure-vm-simple-linux-managed-disk/README.md create mode 100755 examples/azure-vm-simple-linux-managed-disk/after_deploy.ci.sh create mode 100755 examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh create mode 100755 examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh create mode 100644 examples/azure-vm-simple-linux-managed-disk/main.tf create mode 100644 examples/azure-vm-simple-linux-managed-disk/outputs.tf create mode 100644 examples/azure-vm-simple-linux-managed-disk/provider.tf create mode 100644 examples/azure-vm-simple-linux-managed-disk/terraform.tfvars create mode 100644 examples/azure-vm-simple-linux-managed-disk/variables.tf diff --git a/.travis.yml b/.travis.yml index 2e9151fa24c4..d54a0592b1e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ deploy: skip_cleanup: true script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: - repo: harijayms/terraform + repo: 10thmagnitude/terraform branch: master # cleanup diff --git a/examples/azure-vm-simple-linux-managed-disk/README.md b/examples/azure-vm-simple-linux-managed-disk/README.md new file mode 100644 index 000000000000..0492e3edccb9 --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/README.md @@ -0,0 +1,24 @@ +# Very simple deployment of a Linux VM + + + + + +This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy a A1 size VM in the resource group location and return the FQDN of the VM. + +This template takes a minimum amount of parameters and deploys a Linux VM, using the latest patched version. + +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. diff --git a/examples/azure-vm-simple-linux-managed-disk/after_deploy.ci.sh b/examples/azure-vm-simple-linux-managed-disk/after_deploy.ci.sh new file mode 100755 index 000000000000..245aba38045e --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/after_deploy.ci.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -o errexit -o nounset + +# cleanup deployed azure resources +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az group delete -y -n $KEY" diff --git a/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh b/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh new file mode 100755 index 000000000000..8fa08573faad --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -o errexit -o nounset + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD; \ + /bin/terraform apply out.tfplan" diff --git a/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh b/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh new file mode 100755 index 000000000000..9c6563f07d71 --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -o errexit -o nounset + +if docker -v; then + + # generate a unique string for CI deployment + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) + + /bin/sh ./deploy.ci.sh + +else + echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" +fi diff --git a/examples/azure-vm-simple-linux-managed-disk/main.tf b/examples/azure-vm-simple-linux-managed-disk/main.tf new file mode 100644 index 000000000000..e9c0877d5a39 --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/main.tf @@ -0,0 +1,104 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_virtual_network" "vnet" { + name = "${var.virtual_network_name}" + location = "${var.location}" + address_space = ["${var.address_space}"] + resource_group_name = "${azurerm_resource_group.rg.name}" +} + +resource "azurerm_subnet" "subnet" { + name = "${var.rg_prefix}subnet" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + address_prefix = "${var.subnet_prefix}" +} + +resource "azurerm_network_interface" "nic" { + name = "${var.rg_prefix}nic" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + + ip_configuration { + name = "${var.rg_prefix}ipconfig" + subnet_id = "${azurerm_subnet.subnet.id}" + private_ip_address_allocation = "Dynamic" + public_ip_address_id = "${azurerm_public_ip.pip.id}" + } +} + +resource "azurerm_public_ip" "pip" { + name = "${var.rg_prefix}-ip" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + public_ip_address_allocation = "dynamic" + domain_name_label = "${var.dns_name}" +} + +resource "azurerm_storage_account" "stor" { + name = "${var.dns_name}stor" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + account_type = "${var.storage_account_type}" +} + +resource "azurerm_storage_container" "storc" { + name = "${var.hostname}-vhds" + resource_group_name = "${azurerm_resource_group.rg.name}" + storage_account_name = "${azurerm_storage_account.stor.name}" + container_access_type = "private" +} + +resource "azurerm_managed_disk" "datadisk" { + name = "${var.hostname}-datadisk" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + storage_account_type = "Standard_LRS" + create_option = "Empty" + disk_size_gb = "1023" +} + +resource "azurerm_virtual_machine" "vm" { + name = "${var.rg_prefix}vm" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + vm_size = "${var.vm_size}" + network_interface_ids = ["${azurerm_network_interface.nic.id}"] + + storage_image_reference { + publisher = "${var.image_publisher}" + offer = "${var.image_offer}" + sku = "${var.image_sku}" + version = "${var.image_version}" + } + + storage_os_disk { + name = "${var.hostname}-osdisk" + managed_disk_type = "Standard_LRS" + caching = "ReadWrite" + create_option = "FromImage" + } + + storage_data_disk { + name = "${var.hostname}-datadisk" + managed_disk_id = "${azurerm_managed_disk.datadisk.id}" + managed_disk_type = "Standard_LRS" + disk_size_gb = "1023" + create_option = "Attach" + lun = 0 + } + + os_profile { + computer_name = "${var.hostname}" + admin_username = "${var.admin_username}" + admin_password = "${var.admin_password}" + } + + boot_diagnostics { + enabled = "true" + storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" + } +} diff --git a/examples/azure-vm-simple-linux-managed-disk/outputs.tf b/examples/azure-vm-simple-linux-managed-disk/outputs.tf new file mode 100644 index 000000000000..9e3c2f0712bc --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/outputs.tf @@ -0,0 +1,11 @@ +output "hostname" { + value = "${var.hostname}" +} + +output "vm_fqdn" { + value = "${azurerm_public_ip.pip.fqdn}" +} + +output "sshCommand" { + value = "ssh ${var.admin_username}@${azurerm_public_ip.pip.fqdn}" +} diff --git a/examples/azure-vm-simple-linux-managed-disk/provider.tf b/examples/azure-vm-simple-linux-managed-disk/provider.tf new file mode 100644 index 000000000000..79291f7ca895 --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/provider.tf @@ -0,0 +1,7 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + diff --git a/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars b/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars new file mode 100644 index 000000000000..bee98e4e11bc --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars @@ -0,0 +1,8 @@ +# Replace with relevant values + +# resource_group = "myresourcegroup" +# rg_prefix = "rg" +# hostname = "myvm" +# dns_name = "mydnsname" +# location = "southcentralus" +# admin_password = "T3rr@f0rmP@ssword" diff --git a/examples/azure-vm-simple-linux-managed-disk/variables.tf b/examples/azure-vm-simple-linux-managed-disk/variables.tf new file mode 100644 index 000000000000..6d65a0277060 --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/variables.tf @@ -0,0 +1,75 @@ +variable "resource_group" { + description = "The name of the resource group in which to create the virtual network." +} + +variable "rg_prefix" { + description = "The shortened abbreviation to represent your resource group that will go on the front of some resources." + default = "rg" +} + +variable "hostname" { + description = "VM name referenced also in storage-related names." +} + +variable "dns_name" { + description = " Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "virtual_network_name" { + description = "The name for the virtual network." + default = "vnet" +} + +variable "address_space" { + description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." + default = "10.0.0.0/16" +} + +variable "subnet_prefix" { + description = "The address prefix to use for the subnet." + default = "10.0.10.0/24" +} + +variable "storage_account_type" { + description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." + default = "Standard_LRS" +} + +variable "vm_size" { + description = "Specifies the name of the virtual machine resource. Changing this forces a new resource to be created." + default = "Standard_A0" +} + +variable "image_publisher" { + description = "name of the publisher of the image (az vm image list)" + default = "Canonical" +} + +variable "image_offer" { + description = "the name of the offer (az vm image list)" + default = "UbuntuServer" +} + +variable "image_sku" { + description = "image sku to apply (az vm image list)" + default = "16.04-LTS" +} + +variable "image_version" { + description = "version of the image to apply (az vm image list)" + default = "latest" +} + +variable "admin_username" { + description = "administrator user name" + default = "vmadmin" +} + +variable "admin_password" { + description = "administrator password (recommended to disable password auth)" +} From ac2e5c25debc793e3c4affda1c624819ef83fd95 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 27 Apr 2017 14:28:16 -0500 Subject: [PATCH 28/68] initial commit --- .../azure-cdn-with-storage-account/README.md | 32 +++++++++++++++++ .../after_deploy.ci.sh | 9 +++++ .../deploy.ci.sh | 17 ++++++++++ .../deploy.mac.sh | 15 ++++++++ .../azure-cdn-with-storage-account/main.tf | 34 +++++++++++++++++++ .../provider.tf.example | 7 ++++ .../terraform.tfvars | 8 +++++ .../variables.tf | 27 +++++++++++++++ 8 files changed, 149 insertions(+) create mode 100644 examples/azure-cdn-with-storage-account/README.md create mode 100755 examples/azure-cdn-with-storage-account/after_deploy.ci.sh create mode 100755 examples/azure-cdn-with-storage-account/deploy.ci.sh create mode 100755 examples/azure-cdn-with-storage-account/deploy.mac.sh create mode 100644 examples/azure-cdn-with-storage-account/main.tf create mode 100644 examples/azure-cdn-with-storage-account/provider.tf.example create mode 100644 examples/azure-cdn-with-storage-account/terraform.tfvars create mode 100644 examples/azure-cdn-with-storage-account/variables.tf diff --git a/examples/azure-cdn-with-storage-account/README.md b/examples/azure-cdn-with-storage-account/README.md new file mode 100644 index 000000000000..287a09b4e7ea --- /dev/null +++ b/examples/azure-cdn-with-storage-account/README.md @@ -0,0 +1,32 @@ +# Create a CDN Profile, a CDN Endpoint with a Storage Account as origin + +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-cdn-with-storage-account) Azure Quickstart Template. Changes to the ARM template may have occurred since the creation of this example may not be reflected here. + + + + + +This template creates a [CDN Profile](https://docs.microsoft.com/en-us/azure/cdn/cdn-overview) and a CDN Endpoint with origin as a Storage Account. Note that user needs to create a public container in the Storage Account in order for CDN Endpoint to serve content from the Storage Account. + +# Important + +The endpoint will not immediately be available for use, as it takes time for the registration to propagate through the CDN. For Azure CDN from Akamai profiles, propagation will usually complete within one minute. For Azure CDN from Verizon profiles, propagation will usually complete within 90 minutes, but in some cases can take longer. + +Users who try to use the CDN domain name before the endpoint configuration has propagated to the POPs will receive HTTP 404 response codes. If it's been several hours since you created your endpoint and you're still receiving 404 responses, please see [Troubleshooting CDN endpoints returning 404 statuses](https://docs.microsoft.com/en-us/azure/cdn/cdn-troubleshoot-endpoint). + +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +If you are committing this template to source control, please insure that you add this file to your `.gitignore` file. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. diff --git a/examples/azure-cdn-with-storage-account/after_deploy.ci.sh b/examples/azure-cdn-with-storage-account/after_deploy.ci.sh new file mode 100755 index 000000000000..245aba38045e --- /dev/null +++ b/examples/azure-cdn-with-storage-account/after_deploy.ci.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -o errexit -o nounset + +# cleanup deployed azure resources +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az group delete -y -n $KEY" diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh new file mode 100755 index 000000000000..8fa08573faad --- /dev/null +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -o errexit -o nounset + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD; \ + /bin/terraform apply out.tfplan" diff --git a/examples/azure-cdn-with-storage-account/deploy.mac.sh b/examples/azure-cdn-with-storage-account/deploy.mac.sh new file mode 100755 index 000000000000..9c6563f07d71 --- /dev/null +++ b/examples/azure-cdn-with-storage-account/deploy.mac.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -o errexit -o nounset + +if docker -v; then + + # generate a unique string for CI deployment + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) + + /bin/sh ./deploy.ci.sh + +else + echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" +fi diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf new file mode 100644 index 000000000000..6073b2710690 --- /dev/null +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -0,0 +1,34 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_storage_account" "stor" { + name = "${var.hostname}stor" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + account_type = "${var.storage_account_type}" +} + +resource "azurerm_cdn_profile" "cdn" { + name = "${var.hostname}CdnProfile1" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + sku = "Standard_Akamai" +} + +resource "azurerm_cdn_endpoint" "cdnendpt" { + name = "${var.hostname}CdnEndpoint1" + profile_name = "${azurerm_cdn_profile.cdn.name}" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + # content_types_to_compress = ["text/plain", "text/html", "text/css", "application/x-javascript", "text/javascript"] + # is_compression_enabled = true + # is_https_allowed = false + + origin { + name = "${var.hostname}Origin1" + host_name = "vmforcdn.southcentralus.cloudapp.azure.com" + http_port = 80 + } +} diff --git a/examples/azure-cdn-with-storage-account/provider.tf.example b/examples/azure-cdn-with-storage-account/provider.tf.example new file mode 100644 index 000000000000..79291f7ca895 --- /dev/null +++ b/examples/azure-cdn-with-storage-account/provider.tf.example @@ -0,0 +1,7 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + diff --git a/examples/azure-cdn-with-storage-account/terraform.tfvars b/examples/azure-cdn-with-storage-account/terraform.tfvars new file mode 100644 index 000000000000..bee98e4e11bc --- /dev/null +++ b/examples/azure-cdn-with-storage-account/terraform.tfvars @@ -0,0 +1,8 @@ +# Replace with relevant values + +# resource_group = "myresourcegroup" +# rg_prefix = "rg" +# hostname = "myvm" +# dns_name = "mydnsname" +# location = "southcentralus" +# admin_password = "T3rr@f0rmP@ssword" diff --git a/examples/azure-cdn-with-storage-account/variables.tf b/examples/azure-cdn-with-storage-account/variables.tf new file mode 100644 index 000000000000..1793b6b24654 --- /dev/null +++ b/examples/azure-cdn-with-storage-account/variables.tf @@ -0,0 +1,27 @@ +variable "resource_group" { + description = "The name of the resource group in which to create the virtual network." +} + +variable "hostname" { + description = "VM name referenced also in storage-related names." +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "storage_account_type" { + description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." + default = "Standard_LRS" +} + +variable "admin_username" { + description = "administrator user name" + default = "vmadmin" +} + +variable "admin_password" { + description = "administrator password (recommended to disable password auth)" + default = "T3rraform!!!" +} From 935c19a25904d7ca3ff79f7e9c803698765c778a Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 27 Apr 2017 16:16:23 -0500 Subject: [PATCH 29/68] deploys locally --- .travis.yml | 8 ++------ .../azure-cdn-with-storage-account/deploy.ci.sh | 2 +- examples/azure-cdn-with-storage-account/main.tf | 15 +++++++-------- .../azure-cdn-with-storage-account/variables.tf | 17 ++++------------- 4 files changed, 14 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index d54a0592b1e7..5f63df3aebad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,7 @@ git: # establish environment variables env: - - TEST_DIR=examples/azure-vm-simple-linux-managed-disk - - TEST_DIR=examples/azure-vm-from-user-image + - TEST_DIR=examples/azure-cdn-with-storage-account branches: only: @@ -23,9 +22,6 @@ branches: before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd - - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor - - export EXISTING_RESOURCE_GROUP=permanent # terraform deploy script deploy: @@ -34,7 +30,7 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: 10thmagnitude/terraform - branch: master + branch: topic-201-cdn-with-storage-account # cleanup after_deploy: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./after_deploy.ci.sh diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh index 8fa08573faad..3abf813936c6 100755 --- a/examples/azure-cdn-with-storage-account/deploy.ci.sh +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -13,5 +13,5 @@ docker run --rm -it \ hashicorp/terraform:light \ -c "/bin/terraform get; \ /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD; \ + /bin/terraform plan -out=out.tfplan -var resource_group=$KEY; \ /bin/terraform apply out.tfplan" diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf index 6073b2710690..d5b69558b0a7 100644 --- a/examples/azure-cdn-with-storage-account/main.tf +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -4,31 +4,30 @@ resource "azurerm_resource_group" "rg" { } resource "azurerm_storage_account" "stor" { - name = "${var.hostname}stor" + name = "${var.resource_group}stor" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" account_type = "${var.storage_account_type}" } resource "azurerm_cdn_profile" "cdn" { - name = "${var.hostname}CdnProfile1" + name = "${var.resource_group}CdnProfile1" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" sku = "Standard_Akamai" } resource "azurerm_cdn_endpoint" "cdnendpt" { - name = "${var.hostname}CdnEndpoint1" + name = "${var.resource_group}CdnEndpoint1" profile_name = "${azurerm_cdn_profile.cdn.name}" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" - # content_types_to_compress = ["text/plain", "text/html", "text/css", "application/x-javascript", "text/javascript"] - # is_compression_enabled = true - # is_https_allowed = false + is_https_allowed = false origin { - name = "${var.hostname}Origin1" - host_name = "vmforcdn.southcentralus.cloudapp.azure.com" + name = "${var.resource_group}Origin1" + host_name = "${var.host_name}" http_port = 80 + https_port = 443 } } diff --git a/examples/azure-cdn-with-storage-account/variables.tf b/examples/azure-cdn-with-storage-account/variables.tf index 1793b6b24654..9b69787ef788 100644 --- a/examples/azure-cdn-with-storage-account/variables.tf +++ b/examples/azure-cdn-with-storage-account/variables.tf @@ -2,10 +2,6 @@ variable "resource_group" { description = "The name of the resource group in which to create the virtual network." } -variable "hostname" { - description = "VM name referenced also in storage-related names." -} - variable "location" { description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." default = "southcentralus" @@ -16,12 +12,7 @@ variable "storage_account_type" { default = "Standard_LRS" } -variable "admin_username" { - description = "administrator user name" - default = "vmadmin" -} - -variable "admin_password" { - description = "administrator password (recommended to disable password auth)" - default = "T3rraform!!!" -} +variable "host_name" { + description = "A string that determines the hostname/IP address of the origin server. This string could be a domain name, IPv4 address or IPv6 address." + default = "www.example.com" +} \ No newline at end of file From 66b74413034b49764f8aa6f6f620f79a6c7e8b9c Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 27 Apr 2017 16:27:21 -0500 Subject: [PATCH 30/68] updated deploy --- .../after_deploy.ci.sh | 9 --------- .../deploy.ci.sh | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 9 deletions(-) delete mode 100755 examples/azure-cdn-with-storage-account/after_deploy.ci.sh diff --git a/examples/azure-cdn-with-storage-account/after_deploy.ci.sh b/examples/azure-cdn-with-storage-account/after_deploy.ci.sh deleted file mode 100755 index 245aba38045e..000000000000 --- a/examples/azure-cdn-with-storage-account/after_deploy.ci.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -# cleanup deployed azure resources -docker run --rm -it \ - azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ - az group delete -y -n $KEY" diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh index 3abf813936c6..d4a8bf244087 100755 --- a/examples/azure-cdn-with-storage-account/deploy.ci.sh +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -15,3 +15,22 @@ docker run --rm -it \ /bin/terraform validate; \ /bin/terraform plan -out=out.tfplan -var resource_group=$KEY; \ /bin/terraform apply out.tfplan" + +# cleanup deployed azure resources via terraform +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform destroy -force -var resource_group=$KEY;" + + +# cleanup deployed azure resources via azure-cli +# docker run --rm -it \ +# azuresdk/azure-cli-python \ +# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ +# az group delete -y -n $KEY" \ No newline at end of file From c98b1d11780976d1bba35b3537831102f5ef475d Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Thu, 27 Apr 2017 16:29:02 -0500 Subject: [PATCH 31/68] consolidated deploy and after_deploy into a single script; simplified ci process; added os_profile_linux_config --- .../after_deploy.ci.sh | 11 ------ .../azure-vm-from-user-image/deploy.ci.sh | 36 ++++++++++--------- .../azure-vm-from-user-image/deploy.mac.sh | 2 +- examples/azure-vm-from-user-image/main.tf | 4 +++ 4 files changed, 24 insertions(+), 29 deletions(-) delete mode 100755 examples/azure-vm-from-user-image/after_deploy.ci.sh diff --git a/examples/azure-vm-from-user-image/after_deploy.ci.sh b/examples/azure-vm-from-user-image/after_deploy.ci.sh deleted file mode 100755 index 8a5624eb7681..000000000000 --- a/examples/azure-vm-from-user-image/after_deploy.ci.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -docker run --rm -it \ - azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ - az vm delete --name $KEY --resource-group permanent -y; \ - az network nic delete --name $KEY'nic' --resource-group permanent; \ - az network vnet delete --name $KEY'vnet' --resource-group permanent; \ - az network public-ip delete --name $KEY'-ip' --resource-group permanent;" diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index f45c5bb2a6cd..6c315809aadf 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -16,22 +16,24 @@ docker run --rm -it \ /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ /bin/terraform apply out.tfplan" -# echo "Setting git user name" -# git config user.name $GH_USER_NAME -# -# echo "Setting git user email" -# git config user.email $GH_USER_EMAIL -# -# echo "Adding git upstream remote" -# git remote add upstream "https://$GH_TOKEN@github.com/$GH_REPO.git" -# -# git checkout master +# cleanup deployed azure resources via terraform +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform destroy -force -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME -target=azurerm_virtual_machine.vm -target=azurerm_network_interface.nic -target=azurerm_virtual_network.vnet -target=azurerm_public_ip.pip;" -# -# NOW=$(TZ=America/Chicago date) -# -# git commit -m "tfstate: $NOW [ci skip]" -# -# echo "Pushing changes to upstream master" -# git push upstream master +## cleanup deployed azure resources via azure-cli +# docker run --rm -it \ +# azuresdk/azure-cli-python \ +# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ +# az vm delete --name $KEY --resource-group permanent -y; \ +# az network nic delete --name $KEY'nic' --resource-group permanent; \ +# az network vnet delete --name $KEY'vnet' --resource-group permanent; \ +# az network public-ip delete --name $KEY'-ip' --resource-group permanent;" diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh index acd4ca7028fc..079c7f1bbe60 100755 --- a/examples/azure-vm-from-user-image/deploy.mac.sh +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -5,7 +5,7 @@ set -o errexit -o nounset if docker -v; then # generate a unique string for CI deployment - export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export KEY=jcnkmmscfkrw export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf index 28edf99204b5..929a87fa7134 100644 --- a/examples/azure-vm-from-user-image/main.tf +++ b/examples/azure-vm-from-user-image/main.tf @@ -59,4 +59,8 @@ resource "azurerm_virtual_machine" "vm" { admin_username = "${var.admin_username}" admin_password = "${var.admin_password}" } + + os_profile_linux_config { + disable_password_authentication = false + } } From 0ef07bcbe131ef32663d11c36cd9f325029c7cb0 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Thu, 27 Apr 2017 17:22:22 -0500 Subject: [PATCH 32/68] added terraform show --- examples/azure-vm-from-user-image/deploy.ci.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index 6c315809aadf..faa3086987ba 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -14,7 +14,8 @@ docker run --rm -it \ -c "/bin/terraform get; \ /bin/terraform validate; \ /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ - /bin/terraform apply out.tfplan" + /bin/terraform apply out.tfplan \ + /bin/terraform show;" # cleanup deployed azure resources via terraform docker run --rm -it \ From 50e8d8a5f6777581c85d89055b5d79005a6c07f8 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 27 Apr 2017 18:12:45 -0500 Subject: [PATCH 33/68] changed to allow http & https (like ARM tmplt) --- examples/azure-cdn-with-storage-account/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf index d5b69558b0a7..1f9c9ecbf843 100644 --- a/examples/azure-cdn-with-storage-account/main.tf +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -22,7 +22,6 @@ resource "azurerm_cdn_endpoint" "cdnendpt" { profile_name = "${azurerm_cdn_profile.cdn.name}" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" - is_https_allowed = false origin { name = "${var.resource_group}Origin1" From ace9b0bd91019122d098ba02d53c561365c4b613 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 27 Apr 2017 18:39:39 -0500 Subject: [PATCH 34/68] changed host_name & host_name variable desc --- examples/azure-cdn-with-storage-account/outputs.tf | 3 +++ examples/azure-cdn-with-storage-account/variables.tf | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 examples/azure-cdn-with-storage-account/outputs.tf diff --git a/examples/azure-cdn-with-storage-account/outputs.tf b/examples/azure-cdn-with-storage-account/outputs.tf new file mode 100644 index 000000000000..8f7c1e5c8ad1 --- /dev/null +++ b/examples/azure-cdn-with-storage-account/outputs.tf @@ -0,0 +1,3 @@ +output "CDN Endpoint ID" { + value = "${azurerm_cdn_endpoint.cdnendpt.name}.azureedge.net" +} diff --git a/examples/azure-cdn-with-storage-account/variables.tf b/examples/azure-cdn-with-storage-account/variables.tf index 9b69787ef788..be6fd57487a6 100644 --- a/examples/azure-cdn-with-storage-account/variables.tf +++ b/examples/azure-cdn-with-storage-account/variables.tf @@ -13,6 +13,6 @@ variable "storage_account_type" { } variable "host_name" { - description = "A string that determines the hostname/IP address of the origin server. This string could be a domain name, IPv4 address or IPv6 address." - default = "www.example.com" + description = "Storage account endpoint. This template requires that the user creates a public container in the Storage Account in order for CDN Endpoint to serve content from the Storage Account." + default = "https://example.blob.core.windows.net/" } \ No newline at end of file From 5e99f8166ea6961a69eddc33bcd7b16eeb4ceb1e Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Thu, 27 Apr 2017 19:09:55 -0500 Subject: [PATCH 35/68] added az cli check --- examples/azure-vm-from-user-image/deploy.ci.sh | 17 ++++++----------- examples/azure-vm-from-user-image/deploy.mac.sh | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index faa3086987ba..a9f19bd7ed3e 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -14,9 +14,14 @@ docker run --rm -it \ -c "/bin/terraform get; \ /bin/terraform validate; \ /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ - /bin/terraform apply out.tfplan \ + /bin/terraform apply out.tfplan; \ /bin/terraform show;" +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az vm show --name $KEY --resource-group permanent" + # cleanup deployed azure resources via terraform docker run --rm -it \ -e ARM_CLIENT_ID \ @@ -28,13 +33,3 @@ docker run --rm -it \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ -c "/bin/terraform destroy -force -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME -target=azurerm_virtual_machine.vm -target=azurerm_network_interface.nic -target=azurerm_virtual_network.vnet -target=azurerm_public_ip.pip;" - - -## cleanup deployed azure resources via azure-cli -# docker run --rm -it \ -# azuresdk/azure-cli-python \ -# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ -# az vm delete --name $KEY --resource-group permanent -y; \ -# az network nic delete --name $KEY'nic' --resource-group permanent; \ -# az network vnet delete --name $KEY'vnet' --resource-group permanent; \ -# az network public-ip delete --name $KEY'-ip' --resource-group permanent;" diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh index 079c7f1bbe60..acd4ca7028fc 100755 --- a/examples/azure-vm-from-user-image/deploy.mac.sh +++ b/examples/azure-vm-from-user-image/deploy.mac.sh @@ -5,7 +5,7 @@ set -o errexit -o nounset if docker -v; then # generate a unique string for CI deployment - export KEY=jcnkmmscfkrw + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor From 65826c136151f4822f72b3cad3dd60cadee1c4ac Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Thu, 27 Apr 2017 20:28:33 -0500 Subject: [PATCH 36/68] on this branch, only build test_dir; master will aggregate all the examples --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f17d0ca9930d..d7f21a323fff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ git: # establish environment variables env: - - TEST_DIR=examples/azure-vm-simple-linux-managed-disk - TEST_DIR=examples/azure-vm-from-user-image branches: From 2675c55d5c22abb71bdd859a830f789e5f3b0eb9 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 10:16:01 -0500 Subject: [PATCH 37/68] merge master --- .travis.yml | 9 ++-- examples/azure-vnet-two-subnets/.gitignore | 3 ++ examples/azure-vnet-two-subnets/README.md | 22 ++++++++++ examples/azure-vnet-two-subnets/deploy.mac.sh | 14 ++++++ examples/azure-vnet-two-subnets/deploy.sh | 43 +++++++++++++++++++ examples/azure-vnet-two-subnets/main.tf | 25 +++++++++++ .../provider.tf.example | 6 +++ examples/azure-vnet-two-subnets/variables.tf | 9 ++++ 8 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 examples/azure-vnet-two-subnets/.gitignore create mode 100644 examples/azure-vnet-two-subnets/README.md create mode 100644 examples/azure-vnet-two-subnets/deploy.mac.sh create mode 100755 examples/azure-vnet-two-subnets/deploy.sh create mode 100644 examples/azure-vnet-two-subnets/main.tf create mode 100644 examples/azure-vnet-two-subnets/provider.tf.example create mode 100644 examples/azure-vnet-two-subnets/variables.tf diff --git a/.travis.yml b/.travis.yml index dc362203e9b2..33cdfdab3d17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,13 +9,16 @@ services: language: generic +# on branches: ignore multiple commits that will queue build jobs, just run latest commit +git: + depth: 1 + # establish environment variables env: - - TEST_DIR=examples/azure-vm-simple-linux-managed-disk + - TEST_DIR=examples/azure-vnet-two-subnets branches: only: - - master - /^(?i:topic)-.*$/ # install terraform @@ -30,4 +33,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: master + branch: topic-101-vnet-two-subnets diff --git a/examples/azure-vnet-two-subnets/.gitignore b/examples/azure-vnet-two-subnets/.gitignore new file mode 100644 index 000000000000..4893d38ff8fc --- /dev/null +++ b/examples/azure-vnet-two-subnets/.gitignore @@ -0,0 +1,3 @@ +terraform.tfstate* +provider.tf +out.tfplan diff --git a/examples/azure-vnet-two-subnets/README.md b/examples/azure-vnet-two-subnets/README.md new file mode 100644 index 000000000000..dc1c50277301 --- /dev/null +++ b/examples/azure-vnet-two-subnets/README.md @@ -0,0 +1,22 @@ +# Virtual Network with two Subnets + + + + + +This template allows you to create a Virtual Network with two subnets. + +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. \ No newline at end of file diff --git a/examples/azure-vnet-two-subnets/deploy.mac.sh b/examples/azure-vnet-two-subnets/deploy.mac.sh new file mode 100644 index 000000000000..e712aa6aa8f1 --- /dev/null +++ b/examples/azure-vnet-two-subnets/deploy.mac.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -o errexit -o nounset + +# generate a unique string for CI deployment +export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) +export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) + +/bin/sh ./deploy.sh + +# docker run --rm -it \ +# azuresdk/azure-cli-python \ +# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ +# az group delete -y -n $KEY" \ No newline at end of file diff --git a/examples/azure-vnet-two-subnets/deploy.sh b/examples/azure-vnet-two-subnets/deploy.sh new file mode 100755 index 000000000000..c267eaea7986 --- /dev/null +++ b/examples/azure-vnet-two-subnets/deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -o errexit -o nounset + +# generate a unique string for CI deployment +# KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) +# PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "cd /data; \ + /bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan; \ + /bin/terraform apply out.tfplan" + +# TODO: determine external validation, possibly Azure CLI + +# echo "Setting git user name" +# git config user.name $GH_USER_NAME +# +# echo "Setting git user email" +# git config user.email $GH_USER_EMAIL +# +# echo "Adding git upstream remote" +# git remote add upstream "https://$GH_TOKEN@github.com/$GH_REPO.git" +# +# git checkout master + + +# +# NOW=$(TZ=America/Chicago date) +# +# git commit -m "tfstate: $NOW [ci skip]" +# +# echo "Pushing changes to upstream master" +# git push upstream master \ No newline at end of file diff --git a/examples/azure-vnet-two-subnets/main.tf b/examples/azure-vnet-two-subnets/main.tf new file mode 100644 index 000000000000..eb83a4bf35b3 --- /dev/null +++ b/examples/azure-vnet-two-subnets/main.tf @@ -0,0 +1,25 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_virtual_network" "vnet" { + name = "${var.resource_group}vnet" + location = "${var.location}" + address_space = ["10.0.0.0/16"] + resource_group_name = "${azurerm_resource_group.rg.name}" +} + +resource "azurerm_subnet" "subnet1" { + name = "${var.resource_group}subnet1" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + address_prefix = "10.0.0.0/24" +} + +resource "azurerm_subnet" "subnet2" { + name = "${var.resource_group}subnet2" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + address_prefix = "10.0.1.0/24" +} diff --git a/examples/azure-vnet-two-subnets/provider.tf.example b/examples/azure-vnet-two-subnets/provider.tf.example new file mode 100644 index 000000000000..327ceb55eefa --- /dev/null +++ b/examples/azure-vnet-two-subnets/provider.tf.example @@ -0,0 +1,6 @@ +provider "azurerm" { + subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" + client_id = "REPLACE-WITH-YOUR-CLIENT-ID" + client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" + tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +} \ No newline at end of file diff --git a/examples/azure-vnet-two-subnets/variables.tf b/examples/azure-vnet-two-subnets/variables.tf new file mode 100644 index 000000000000..ee64ffbc28e2 --- /dev/null +++ b/examples/azure-vnet-two-subnets/variables.tf @@ -0,0 +1,9 @@ +variable "resource_group" { + description = "The name of the resource group in which to create the virtual network." + default = "rg2" +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} From 072a51a9845b72754142436bde091409676885b7 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 10:44:07 -0500 Subject: [PATCH 38/68] added new constructs/naming for deploy scripts, etc. --- examples/azure-vnet-two-subnets/deploy.ci.sh | 41 ++++++++++++++++++ examples/azure-vnet-two-subnets/deploy.mac.sh | 17 ++++---- examples/azure-vnet-two-subnets/deploy.sh | 43 ------------------- examples/azure-vnet-two-subnets/main.tf | 4 +- examples/azure-vnet-two-subnets/variables.tf | 1 - 5 files changed, 52 insertions(+), 54 deletions(-) create mode 100755 examples/azure-vnet-two-subnets/deploy.ci.sh mode change 100644 => 100755 examples/azure-vnet-two-subnets/deploy.mac.sh delete mode 100755 examples/azure-vnet-two-subnets/deploy.sh diff --git a/examples/azure-vnet-two-subnets/deploy.ci.sh b/examples/azure-vnet-two-subnets/deploy.ci.sh new file mode 100755 index 000000000000..b77b4135cf3a --- /dev/null +++ b/examples/azure-vnet-two-subnets/deploy.ci.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -o errexit -o nounset + +# generate a unique string for CI deployment +# KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) +# PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var resource_group=$KEY; \ + /bin/terraform apply out.tfplan; \ + /bin/terraform show;" + +# check that resources exist via azure cli +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + az network vnet subnet show -n subnet1 -g $KEY --vnet-name '$KEY'vnet; \ + az network vnet subnet show -n subnet2 -g $KEY --vnet-name '$KEY'vnet;" + +# cleanup deployed azure resources via terraform +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform destroy -force -var resource_group=$KEY;" diff --git a/examples/azure-vnet-two-subnets/deploy.mac.sh b/examples/azure-vnet-two-subnets/deploy.mac.sh old mode 100644 new mode 100755 index e712aa6aa8f1..9c6563f07d71 --- a/examples/azure-vnet-two-subnets/deploy.mac.sh +++ b/examples/azure-vnet-two-subnets/deploy.mac.sh @@ -2,13 +2,14 @@ set -o errexit -o nounset -# generate a unique string for CI deployment -export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) -export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) +if docker -v; then -/bin/sh ./deploy.sh + # generate a unique string for CI deployment + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) -# docker run --rm -it \ -# azuresdk/azure-cli-python \ -# sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ -# az group delete -y -n $KEY" \ No newline at end of file + /bin/sh ./deploy.ci.sh + +else + echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" +fi diff --git a/examples/azure-vnet-two-subnets/deploy.sh b/examples/azure-vnet-two-subnets/deploy.sh deleted file mode 100755 index c267eaea7986..000000000000 --- a/examples/azure-vnet-two-subnets/deploy.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -# generate a unique string for CI deployment -# KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) -# PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - -docker run --rm -it \ - -e ARM_CLIENT_ID \ - -e ARM_CLIENT_SECRET \ - -e ARM_SUBSCRIPTION_ID \ - -e ARM_TENANT_ID \ - -v $(pwd):/data \ - --entrypoint "/bin/sh" \ - hashicorp/terraform:light \ - -c "cd /data; \ - /bin/terraform get; \ - /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan; \ - /bin/terraform apply out.tfplan" - -# TODO: determine external validation, possibly Azure CLI - -# echo "Setting git user name" -# git config user.name $GH_USER_NAME -# -# echo "Setting git user email" -# git config user.email $GH_USER_EMAIL -# -# echo "Adding git upstream remote" -# git remote add upstream "https://$GH_TOKEN@github.com/$GH_REPO.git" -# -# git checkout master - - -# -# NOW=$(TZ=America/Chicago date) -# -# git commit -m "tfstate: $NOW [ci skip]" -# -# echo "Pushing changes to upstream master" -# git push upstream master \ No newline at end of file diff --git a/examples/azure-vnet-two-subnets/main.tf b/examples/azure-vnet-two-subnets/main.tf index eb83a4bf35b3..ef74357ce256 100644 --- a/examples/azure-vnet-two-subnets/main.tf +++ b/examples/azure-vnet-two-subnets/main.tf @@ -11,14 +11,14 @@ resource "azurerm_virtual_network" "vnet" { } resource "azurerm_subnet" "subnet1" { - name = "${var.resource_group}subnet1" + name = "subnet1" virtual_network_name = "${azurerm_virtual_network.vnet.name}" resource_group_name = "${azurerm_resource_group.rg.name}" address_prefix = "10.0.0.0/24" } resource "azurerm_subnet" "subnet2" { - name = "${var.resource_group}subnet2" + name = "subnet2" virtual_network_name = "${azurerm_virtual_network.vnet.name}" resource_group_name = "${azurerm_resource_group.rg.name}" address_prefix = "10.0.1.0/24" diff --git a/examples/azure-vnet-two-subnets/variables.tf b/examples/azure-vnet-two-subnets/variables.tf index ee64ffbc28e2..8d5dd4131636 100644 --- a/examples/azure-vnet-two-subnets/variables.tf +++ b/examples/azure-vnet-two-subnets/variables.tf @@ -1,6 +1,5 @@ variable "resource_group" { description = "The name of the resource group in which to create the virtual network." - default = "rg2" } variable "location" { From 06f1a7f11258b912c56006a69bdf2fcb99397dc8 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 11:59:31 -0500 Subject: [PATCH 39/68] suppress az login output --- examples/azure-vnet-two-subnets/deploy.ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/azure-vnet-two-subnets/deploy.ci.sh b/examples/azure-vnet-two-subnets/deploy.ci.sh index b77b4135cf3a..ee119ea4269f 100755 --- a/examples/azure-vnet-two-subnets/deploy.ci.sh +++ b/examples/azure-vnet-two-subnets/deploy.ci.sh @@ -24,7 +24,7 @@ docker run --rm -it \ # check that resources exist via azure cli docker run --rm -it \ azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ az network vnet subnet show -n subnet1 -g $KEY --vnet-name '$KEY'vnet; \ az network vnet subnet show -n subnet2 -g $KEY --vnet-name '$KEY'vnet;" From 3523ed3305ff908e242388946298c823ec694863 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 12:40:25 -0500 Subject: [PATCH 40/68] suppress az login output --- examples/azure-vm-from-user-image/deploy.ci.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index a9f19bd7ed3e..cf4a9c814511 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -19,7 +19,7 @@ docker run --rm -it \ docker run --rm -it \ azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ az vm show --name $KEY --resource-group permanent" # cleanup deployed azure resources via terraform @@ -32,4 +32,14 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME -target=azurerm_virtual_machine.vm -target=azurerm_network_interface.nic -target=azurerm_virtual_network.vnet -target=azurerm_public_ip.pip;" + -c "/bin/terraform destroy -force \ + -var hostname=$KEY + -var resource_group=$EXISTING_RESOURCE_GROUP + -var admin_username=$KEY + -var admin_password=$PASSWORD + -var image_uri=$EXISTING_IMAGE_URI + -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME + -target=azurerm_virtual_machine.vm + -target=azurerm_network_interface.nic + -target=azurerm_virtual_network.vnet + -target=azurerm_public_ip.pip;" From 21837a95bc02adca7b4d9dfb357a65499b8d24d5 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 12:47:10 -0500 Subject: [PATCH 41/68] forgot about line breaks --- examples/azure-vm-from-user-image/deploy.ci.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index cf4a9c814511..37578ed7db12 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -33,13 +33,13 @@ docker run --rm -it \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ -c "/bin/terraform destroy -force \ - -var hostname=$KEY - -var resource_group=$EXISTING_RESOURCE_GROUP - -var admin_username=$KEY - -var admin_password=$PASSWORD - -var image_uri=$EXISTING_IMAGE_URI - -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME - -target=azurerm_virtual_machine.vm - -target=azurerm_network_interface.nic - -target=azurerm_virtual_network.vnet + -var hostname=$KEY \ + -var resource_group=$EXISTING_RESOURCE_GROUP \ + -var admin_username=$KEY \ + -var admin_password=$PASSWORD \ + -var image_uri=$EXISTING_IMAGE_URI \ + -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME \ + -target=azurerm_virtual_machine.vm \ + -target=azurerm_network_interface.nic \ + -target=azurerm_virtual_network.vnet \ -target=azurerm_public_ip.pip;" From e1e3aa2cdfd18ece7f3e7edb292785470d85ad7d Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 13:34:56 -0500 Subject: [PATCH 42/68] breaking build as an example --- examples/azure-vm-from-user-image/deploy.ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index 37578ed7db12..1f0c4782d210 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -19,7 +19,7 @@ docker run --rm -it \ docker run --rm -it \ azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p WRONG --tenant $ARM_TENANT_ID > /dev/null; \ az vm show --name $KEY --resource-group permanent" # cleanup deployed azure resources via terraform From a0a7643e081dcab1a93433fbc86e822a1aacfebf Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 28 Apr 2017 13:40:41 -0500 Subject: [PATCH 43/68] fixing broken build example --- examples/azure-vm-from-user-image/deploy.ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh index 1f0c4782d210..37578ed7db12 100755 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ b/examples/azure-vm-from-user-image/deploy.ci.sh @@ -19,7 +19,7 @@ docker run --rm -it \ docker run --rm -it \ azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p WRONG --tenant $ARM_TENANT_ID > /dev/null; \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ az vm show --name $KEY --resource-group permanent" # cleanup deployed azure resources via terraform From 2c02115a92c4e25648a91882457ce7b3165f585c Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Mon, 1 May 2017 10:35:36 -0500 Subject: [PATCH 44/68] merge of CI config --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 33cdfdab3d17..86488119349f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,10 +15,12 @@ git: # establish environment variables env: + - TEST_DIR=examples/azure-vm-simple-linux-managed-disk - TEST_DIR=examples/azure-vnet-two-subnets branches: only: + - master - /^(?i:topic)-.*$/ # install terraform @@ -33,4 +35,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: topic-101-vnet-two-subnets + branch: master From 487d9cd1eeeeb4a03d0dcaa08fd07d21580b8b7b Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Mon, 1 May 2017 15:58:45 -0500 Subject: [PATCH 45/68] fixed grammar in readme --- examples/azure-vm-from-user-image/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md index 455b0bcb1a5f..7f575a7926de 100644 --- a/examples/azure-vm-from-user-image/README.md +++ b/examples/azure-vm-from-user-image/README.md @@ -1,6 +1,6 @@ # [Create a Virtual Machine from a User Image](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-deploy-templates#create-a-custom-vm-image) -This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image) Azure Quickstart Template. Changes to the ARM template may have occured since the creation of this example may not be reflected here. +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image) Azure Quickstart Template. Changes to the ARM template that may have occured since the creation of this example may not be reflected here. @@ -11,7 +11,7 @@ This Terraform template was based on [this](https://github.com/Azure/azure-quick This template allows you to create a Virtual Machine from an unmanaged User image vhd. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. ## main.tf -The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. ## outputs.tf This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. @@ -20,7 +20,7 @@ This data is outputted when `terraform apply` is called, and can be queried usin Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. ## terraform.tfvars -If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. If you are committing this template to source control, please insure that you add this file to your `.gitignore` file. From d8ef7b121ce959e8363937085896d40367542d92 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Mon, 1 May 2017 18:14:53 -0500 Subject: [PATCH 46/68] prep for PR --- .travis.yml | 1 - examples/azure-cdn-with-storage-account/README.md | 2 +- examples/azure-cdn-with-storage-account/deploy.ci.sh | 6 ++++-- examples/azure-cdn-with-storage-account/deploy.mac.sh | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index f9dec25566ff..42e207da6b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,6 @@ branches: before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - - export VM_HOST_NAME=anniecdn.southcentralus.cloudapp.azure.com # terraform deploy + script deploy: diff --git a/examples/azure-cdn-with-storage-account/README.md b/examples/azure-cdn-with-storage-account/README.md index 287a09b4e7ea..6536f729385c 100644 --- a/examples/azure-cdn-with-storage-account/README.md +++ b/examples/azure-cdn-with-storage-account/README.md @@ -1,6 +1,6 @@ # Create a CDN Profile, a CDN Endpoint with a Storage Account as origin -This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-cdn-with-storage-account) Azure Quickstart Template. Changes to the ARM template may have occurred since the creation of this example may not be reflected here. +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-cdn-with-storage-account) Azure Quickstart Template. Changes to the ARM template that may have occurred since the creation of this example may not be reflected here. diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh index 4f8f967ab289..dcb4de86e3b9 100755 --- a/examples/azure-cdn-with-storage-account/deploy.ci.sh +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -13,9 +13,11 @@ docker run --rm -it \ hashicorp/terraform:light \ -c "/bin/terraform get; \ /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var resource_group=$KEY -var host_name=$VM_HOST_NAME; \ + /bin/terraform plan -out=out.tfplan -var resource_group=$KEY -var host_name=$KEY; \ /bin/terraform apply out.tfplan" +#TODO: how do we validate? + # cleanup deployed azure resources via terraform docker run --rm -it \ -e ARM_CLIENT_ID \ @@ -26,4 +28,4 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var resource_group=$KEY -var host_name=$VM_HOST_NAME;" + -c "/bin/terraform destroy -force -var resource_group=$KEY -var host_name=$KEY;" diff --git a/examples/azure-cdn-with-storage-account/deploy.mac.sh b/examples/azure-cdn-with-storage-account/deploy.mac.sh index 11ec6e0967b3..9c6563f07d71 100755 --- a/examples/azure-cdn-with-storage-account/deploy.mac.sh +++ b/examples/azure-cdn-with-storage-account/deploy.mac.sh @@ -7,7 +7,6 @@ if docker -v; then # generate a unique string for CI deployment export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) - export VM_HOST_NAME=anniecdn.southcentralus.cloudapp.azure.com /bin/sh ./deploy.ci.sh From 25ef50c256a212c13ec6ac60175f46d2a577d73b Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Tue, 2 May 2017 15:18:48 -0500 Subject: [PATCH 47/68] took out armviz button and minor README changes --- examples/azure-cdn-with-storage-account/README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/examples/azure-cdn-with-storage-account/README.md b/examples/azure-cdn-with-storage-account/README.md index 6536f729385c..8d2d0377caa3 100644 --- a/examples/azure-cdn-with-storage-account/README.md +++ b/examples/azure-cdn-with-storage-account/README.md @@ -1,18 +1,14 @@ # Create a CDN Profile, a CDN Endpoint with a Storage Account as origin -This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-cdn-with-storage-account) Azure Quickstart Template. Changes to the ARM template that may have occurred since the creation of this example may not be reflected here. +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-cdn-with-storage-account) Azure Quickstart Template. Changes to the ARM template that may have occurred since the creation of this example may not be reflected in this Terraform template. - - - - -This template creates a [CDN Profile](https://docs.microsoft.com/en-us/azure/cdn/cdn-overview) and a CDN Endpoint with origin as a Storage Account. Note that user needs to create a public container in the Storage Account in order for CDN Endpoint to serve content from the Storage Account. +This template creates a [CDN Profile](https://docs.microsoft.com/en-us/azure/cdn/cdn-overview) and a CDN Endpoint with the origin as a Storage Account. Note that the user needs to create a public container in the Storage Account in order for CDN Endpoint to serve content from the Storage Account. # Important The endpoint will not immediately be available for use, as it takes time for the registration to propagate through the CDN. For Azure CDN from Akamai profiles, propagation will usually complete within one minute. For Azure CDN from Verizon profiles, propagation will usually complete within 90 minutes, but in some cases can take longer. -Users who try to use the CDN domain name before the endpoint configuration has propagated to the POPs will receive HTTP 404 response codes. If it's been several hours since you created your endpoint and you're still receiving 404 responses, please see [Troubleshooting CDN endpoints returning 404 statuses](https://docs.microsoft.com/en-us/azure/cdn/cdn-troubleshoot-endpoint). +Users who try to use the CDN domain name before the endpoint configuration has propagated to the POPs will receive HTTP 404 response codes. If it has been several hours since you created your endpoint and you're still receiving 404 responses, please see [Troubleshooting CDN endpoints returning 404 statuses](https://docs.microsoft.com/en-us/azure/cdn/cdn-troubleshoot-endpoint). ## main.tf The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. From 63c494dc58b24a0dd6723fdd80955de60609b4eb Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Tue, 2 May 2017 15:31:03 -0500 Subject: [PATCH 48/68] changed host_name --- examples/azure-cdn-with-storage-account/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf index 1f9c9ecbf843..b161e37258d3 100644 --- a/examples/azure-cdn-with-storage-account/main.tf +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -25,7 +25,7 @@ resource "azurerm_cdn_endpoint" "cdnendpt" { origin { name = "${var.resource_group}Origin1" - host_name = "${var.host_name}" + host_name = "www.${var.host_name}.com" http_port = 80 https_port = 443 } From 9a5a15a99ffaf0715900e2adc37af26d2d385962 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Tue, 2 May 2017 16:54:13 -0500 Subject: [PATCH 49/68] fixed merge conflicts --- .../deploy.ci.sh | 8 ++------ .../azure-vm-simple-linux-managed-disk/main.tf | 15 +-------------- .../variables.tf | 10 +--------- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh b/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh index 8ffbeae2ad9f..71e407526186 100755 --- a/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh +++ b/examples/azure-vm-simple-linux-managed-disk/deploy.ci.sh @@ -14,14 +14,13 @@ docker run --rm -it \ -c "/bin/terraform get; \ /bin/terraform validate; \ /bin/terraform plan -out=out.tfplan -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD; \ -<<<<<<< HEAD /bin/terraform apply out.tfplan; \ /bin/terraform show;" # cleanup deployed azure resources via azure-cli docker run --rm -it \ azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ az vm show -g $KEY -n rgvm" # cleanup deployed azure resources via terraform @@ -34,7 +33,4 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD;" -======= - /bin/terraform apply out.tfplan" ->>>>>>> ace9b0bd91019122d098ba02d53c561365c4b613 + -c "/bin/terraform destroy -force -var dns_name=$KEY -var hostname=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD;" \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/main.tf b/examples/azure-vm-simple-linux-managed-disk/main.tf index e39e6f16cfe8..8ef283c7819c 100644 --- a/examples/azure-vm-simple-linux-managed-disk/main.tf +++ b/examples/azure-vm-simple-linux-managed-disk/main.tf @@ -45,16 +45,6 @@ resource "azurerm_storage_account" "stor" { account_type = "${var.storage_account_type}" } -<<<<<<< HEAD -======= -resource "azurerm_storage_container" "storc" { - name = "${var.hostname}-vhds" - resource_group_name = "${azurerm_resource_group.rg.name}" - storage_account_name = "${azurerm_storage_account.stor.name}" - container_access_type = "private" -} - ->>>>>>> ace9b0bd91019122d098ba02d53c561365c4b613 resource "azurerm_managed_disk" "datadisk" { name = "${var.hostname}-datadisk" location = "${var.location}" @@ -100,15 +90,12 @@ resource "azurerm_virtual_machine" "vm" { admin_password = "${var.admin_password}" } -<<<<<<< HEAD os_profile_linux_config { disable_password_authentication = false } -======= ->>>>>>> ace9b0bd91019122d098ba02d53c561365c4b613 boot_diagnostics { enabled = "true" storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" } -} +} \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/variables.tf b/examples/azure-vm-simple-linux-managed-disk/variables.tf index 09cf59f8f834..91024000bc03 100644 --- a/examples/azure-vm-simple-linux-managed-disk/variables.tf +++ b/examples/azure-vm-simple-linux-managed-disk/variables.tf @@ -36,20 +36,12 @@ variable "subnet_prefix" { } variable "storage_account_type" { -<<<<<<< HEAD description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." -======= - description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." ->>>>>>> ace9b0bd91019122d098ba02d53c561365c4b613 default = "Standard_LRS" } variable "vm_size" { -<<<<<<< HEAD description = "Specifies the size of the virtual machine." -======= - description = "Specifies the name of the virtual machine resource. Changing this forces a new resource to be created." ->>>>>>> ace9b0bd91019122d098ba02d53c561365c4b613 default = "Standard_A0" } @@ -80,4 +72,4 @@ variable "admin_username" { variable "admin_password" { description = "administrator password (recommended to disable password auth)" -} +} \ No newline at end of file From d7e2acb5cbe1608b45d9429f78ac318e29ca661d Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Tue, 2 May 2017 17:45:06 -0500 Subject: [PATCH 50/68] changed host_name variable --- examples/azure-cdn-with-storage-account/deploy.ci.sh | 4 ++-- examples/azure-cdn-with-storage-account/main.tf | 2 +- examples/azure-cdn-with-storage-account/variables.tf | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh index dcb4de86e3b9..3fd0efac3f6d 100755 --- a/examples/azure-cdn-with-storage-account/deploy.ci.sh +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -13,7 +13,7 @@ docker run --rm -it \ hashicorp/terraform:light \ -c "/bin/terraform get; \ /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var resource_group=$KEY -var host_name=$KEY; \ + /bin/terraform plan -out=out.tfplan -var resource_group=$KEY; \ /bin/terraform apply out.tfplan" #TODO: how do we validate? @@ -28,4 +28,4 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var resource_group=$KEY -var host_name=$KEY;" + -c "/bin/terraform destroy -force -var resource_group=$KEY;" diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf index b161e37258d3..1f9c9ecbf843 100644 --- a/examples/azure-cdn-with-storage-account/main.tf +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -25,7 +25,7 @@ resource "azurerm_cdn_endpoint" "cdnendpt" { origin { name = "${var.resource_group}Origin1" - host_name = "www.${var.host_name}.com" + host_name = "${var.host_name}" http_port = 80 https_port = 443 } diff --git a/examples/azure-cdn-with-storage-account/variables.tf b/examples/azure-cdn-with-storage-account/variables.tf index e42c937ab0d7..d9bf51015d93 100644 --- a/examples/azure-cdn-with-storage-account/variables.tf +++ b/examples/azure-cdn-with-storage-account/variables.tf @@ -8,10 +8,11 @@ variable "location" { } variable "storage_account_type" { - description = "Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group." + description = "Specifies the type of the storage account" default = "Standard_LRS" } variable "host_name" { - description = "Storage account endpoint. This template requires that the user creates a public container in the Storage Account in order for CDN Endpoint to serve content from the Storage Account." + description = "A string that determines the hostname/IP address of the origin server. This string could be a domain name, IPv4 address or IPv6 address." + default = "www.hostnameoforiginserver.com" } \ No newline at end of file From dbaf8d14a9cdfcef0281919671357f6171ebd4e6 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Wed, 3 May 2017 13:17:55 -0500 Subject: [PATCH 51/68] updating Hashicorp's changes to merged simple linux branch --- examples/azure-vm-simple-linux-managed-disk/README.md | 8 ++------ .../azure-vm-simple-linux-managed-disk/deploy.mac.sh | 2 +- examples/azure-vm-simple-linux-managed-disk/main.tf | 11 +++++++++-- .../azure-vm-simple-linux-managed-disk/outputs.tf | 4 ++-- .../azure-vm-simple-linux-managed-disk/provider.tf | 7 ------- .../terraform.tfvars | 8 -------- 6 files changed, 14 insertions(+), 26 deletions(-) delete mode 100644 examples/azure-vm-simple-linux-managed-disk/provider.tf delete mode 100644 examples/azure-vm-simple-linux-managed-disk/terraform.tfvars diff --git a/examples/azure-vm-simple-linux-managed-disk/README.md b/examples/azure-vm-simple-linux-managed-disk/README.md index 0492e3edccb9..cde5c458e82d 100644 --- a/examples/azure-vm-simple-linux-managed-disk/README.md +++ b/examples/azure-vm-simple-linux-managed-disk/README.md @@ -1,10 +1,6 @@ # Very simple deployment of a Linux VM - - - - -This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy a A1 size VM in the resource group location and return the FQDN of the VM. +This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy an A0 size VM in the resource group location and return the FQDN of the VM. This template takes a minimum amount of parameters and deploys a Linux VM, using the latest patched version. @@ -21,4 +17,4 @@ Azure requires that an application is added to Azure Active Directory to generat If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. ## variables.tf -The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh b/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh index 9c6563f07d71..dfc34c2be2fc 100755 --- a/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh +++ b/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh @@ -12,4 +12,4 @@ if docker -v; then else echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" -fi +fi \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/main.tf b/examples/azure-vm-simple-linux-managed-disk/main.tf index 8ef283c7819c..5dc9ce1cb086 100644 --- a/examples/azure-vm-simple-linux-managed-disk/main.tf +++ b/examples/azure-vm-simple-linux-managed-disk/main.tf @@ -1,3 +1,10 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + resource "azurerm_resource_group" "rg" { name = "${var.resource_group}" location = "${var.location}" @@ -34,7 +41,7 @@ resource "azurerm_public_ip" "pip" { name = "${var.rg_prefix}-ip" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" - public_ip_address_allocation = "dynamic" + public_ip_address_allocation = "Dynamic" domain_name_label = "${var.dns_name}" } @@ -95,7 +102,7 @@ resource "azurerm_virtual_machine" "vm" { } boot_diagnostics { - enabled = "true" + enabled = true storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" } } \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/outputs.tf b/examples/azure-vm-simple-linux-managed-disk/outputs.tf index 9e3c2f0712bc..32c6294ceeab 100644 --- a/examples/azure-vm-simple-linux-managed-disk/outputs.tf +++ b/examples/azure-vm-simple-linux-managed-disk/outputs.tf @@ -6,6 +6,6 @@ output "vm_fqdn" { value = "${azurerm_public_ip.pip.fqdn}" } -output "sshCommand" { +output "ssh_command" { value = "ssh ${var.admin_username}@${azurerm_public_ip.pip.fqdn}" -} +} \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/provider.tf b/examples/azure-vm-simple-linux-managed-disk/provider.tf deleted file mode 100644 index 79291f7ca895..000000000000 --- a/examples/azure-vm-simple-linux-managed-disk/provider.tf +++ /dev/null @@ -1,7 +0,0 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } - diff --git a/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars b/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars deleted file mode 100644 index bee98e4e11bc..000000000000 --- a/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars +++ /dev/null @@ -1,8 +0,0 @@ -# Replace with relevant values - -# resource_group = "myresourcegroup" -# rg_prefix = "rg" -# hostname = "myvm" -# dns_name = "mydnsname" -# location = "southcentralus" -# admin_password = "T3rr@f0rmP@ssword" From b850cd5d2a858eff073fc5a1097a6813d0f8b362 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Wed, 3 May 2017 13:35:37 -0500 Subject: [PATCH 52/68] updating files to merge w/master and prep for Hashicorp pr --- .travis.yml | 17 +++++++++++++---- .../azure-cdn-with-storage-account/deploy.ci.sh | 2 +- .../deploy.mac.sh | 2 +- examples/azure-cdn-with-storage-account/main.tf | 7 +++++++ .../provider.tf.example | 7 ------- .../terraform.tfvars | 8 -------- 6 files changed, 22 insertions(+), 21 deletions(-) delete mode 100644 examples/azure-cdn-with-storage-account/provider.tf.example delete mode 100644 examples/azure-cdn-with-storage-account/terraform.tfvars diff --git a/.travis.yml b/.travis.yml index 42e207da6b9c..6180da4dec64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,7 @@ +#################################################################################### +## NOT FOR UPSTREAM PROPOSAL; INTENDED FOR CI OF AZURE EXAMPLES IN THIS REPO ONLY ## +#################################################################################### + sudo: required services: @@ -5,14 +9,19 @@ services: language: generic +# on branches: ignore multiple commits that will queue build jobs, just run latest commit +git: + depth: 1 + # establish environment variables env: - - TEST_DIR=examples/azure-cdn-with-storage-account + - TEST_DIR=examples/azure-vm-simple-linux-managed-disk + - TEST_DIR=examples/azure-vnet-two-subnets branches: only: -# - master - - /^(?i:topic)-.*$/ + - master + - /^(?i:topic)-.*$/ # install terraform before_deploy: @@ -26,4 +35,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: topic-201-cdn-with-storage-account + branch: master \ No newline at end of file diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh index 3fd0efac3f6d..3ccc9b9ecef2 100755 --- a/examples/azure-cdn-with-storage-account/deploy.ci.sh +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -28,4 +28,4 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var resource_group=$KEY;" + -c "/bin/terraform destroy -force -var resource_group=$KEY;" \ No newline at end of file diff --git a/examples/azure-cdn-with-storage-account/deploy.mac.sh b/examples/azure-cdn-with-storage-account/deploy.mac.sh index 9c6563f07d71..dfc34c2be2fc 100755 --- a/examples/azure-cdn-with-storage-account/deploy.mac.sh +++ b/examples/azure-cdn-with-storage-account/deploy.mac.sh @@ -12,4 +12,4 @@ if docker -v; then else echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" -fi +fi \ No newline at end of file diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf index 1f9c9ecbf843..2e7f56954c3c 100644 --- a/examples/azure-cdn-with-storage-account/main.tf +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -1,3 +1,10 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + resource "azurerm_resource_group" "rg" { name = "${var.resource_group}" location = "${var.location}" diff --git a/examples/azure-cdn-with-storage-account/provider.tf.example b/examples/azure-cdn-with-storage-account/provider.tf.example deleted file mode 100644 index 79291f7ca895..000000000000 --- a/examples/azure-cdn-with-storage-account/provider.tf.example +++ /dev/null @@ -1,7 +0,0 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } - diff --git a/examples/azure-cdn-with-storage-account/terraform.tfvars b/examples/azure-cdn-with-storage-account/terraform.tfvars deleted file mode 100644 index bee98e4e11bc..000000000000 --- a/examples/azure-cdn-with-storage-account/terraform.tfvars +++ /dev/null @@ -1,8 +0,0 @@ -# Replace with relevant values - -# resource_group = "myresourcegroup" -# rg_prefix = "rg" -# hostname = "myvm" -# dns_name = "mydnsname" -# location = "southcentralus" -# admin_password = "T3rr@f0rmP@ssword" From a6151bcc5970a2a5262fcbe3ed8908315ac54187 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Wed, 3 May 2017 17:48:18 -0500 Subject: [PATCH 53/68] Revert "updating files to merge w/master and prep for Hashicorp pr" This reverts commit b850cd5d2a858eff073fc5a1097a6813d0f8b362. --- .travis.yml | 17 ++++------------- .../azure-cdn-with-storage-account/deploy.ci.sh | 2 +- .../deploy.mac.sh | 2 +- examples/azure-cdn-with-storage-account/main.tf | 7 ------- .../provider.tf.example | 7 +++++++ .../terraform.tfvars | 8 ++++++++ 6 files changed, 21 insertions(+), 22 deletions(-) create mode 100644 examples/azure-cdn-with-storage-account/provider.tf.example create mode 100644 examples/azure-cdn-with-storage-account/terraform.tfvars diff --git a/.travis.yml b/.travis.yml index 6180da4dec64..42e207da6b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,3 @@ -#################################################################################### -## NOT FOR UPSTREAM PROPOSAL; INTENDED FOR CI OF AZURE EXAMPLES IN THIS REPO ONLY ## -#################################################################################### - sudo: required services: @@ -9,19 +5,14 @@ services: language: generic -# on branches: ignore multiple commits that will queue build jobs, just run latest commit -git: - depth: 1 - # establish environment variables env: - - TEST_DIR=examples/azure-vm-simple-linux-managed-disk - - TEST_DIR=examples/azure-vnet-two-subnets + - TEST_DIR=examples/azure-cdn-with-storage-account branches: only: - - master - - /^(?i:topic)-.*$/ +# - master + - /^(?i:topic)-.*$/ # install terraform before_deploy: @@ -35,4 +26,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: master \ No newline at end of file + branch: topic-201-cdn-with-storage-account diff --git a/examples/azure-cdn-with-storage-account/deploy.ci.sh b/examples/azure-cdn-with-storage-account/deploy.ci.sh index 3ccc9b9ecef2..3fd0efac3f6d 100755 --- a/examples/azure-cdn-with-storage-account/deploy.ci.sh +++ b/examples/azure-cdn-with-storage-account/deploy.ci.sh @@ -28,4 +28,4 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var resource_group=$KEY;" \ No newline at end of file + -c "/bin/terraform destroy -force -var resource_group=$KEY;" diff --git a/examples/azure-cdn-with-storage-account/deploy.mac.sh b/examples/azure-cdn-with-storage-account/deploy.mac.sh index dfc34c2be2fc..9c6563f07d71 100755 --- a/examples/azure-cdn-with-storage-account/deploy.mac.sh +++ b/examples/azure-cdn-with-storage-account/deploy.mac.sh @@ -12,4 +12,4 @@ if docker -v; then else echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" -fi \ No newline at end of file +fi diff --git a/examples/azure-cdn-with-storage-account/main.tf b/examples/azure-cdn-with-storage-account/main.tf index 2e7f56954c3c..1f9c9ecbf843 100644 --- a/examples/azure-cdn-with-storage-account/main.tf +++ b/examples/azure-cdn-with-storage-account/main.tf @@ -1,10 +1,3 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } - resource "azurerm_resource_group" "rg" { name = "${var.resource_group}" location = "${var.location}" diff --git a/examples/azure-cdn-with-storage-account/provider.tf.example b/examples/azure-cdn-with-storage-account/provider.tf.example new file mode 100644 index 000000000000..79291f7ca895 --- /dev/null +++ b/examples/azure-cdn-with-storage-account/provider.tf.example @@ -0,0 +1,7 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + diff --git a/examples/azure-cdn-with-storage-account/terraform.tfvars b/examples/azure-cdn-with-storage-account/terraform.tfvars new file mode 100644 index 000000000000..bee98e4e11bc --- /dev/null +++ b/examples/azure-cdn-with-storage-account/terraform.tfvars @@ -0,0 +1,8 @@ +# Replace with relevant values + +# resource_group = "myresourcegroup" +# rg_prefix = "rg" +# hostname = "myvm" +# dns_name = "mydnsname" +# location = "southcentralus" +# admin_password = "T3rr@f0rmP@ssword" From 542673967d74e18c5e8759b685288596c243381a Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Wed, 3 May 2017 17:49:04 -0500 Subject: [PATCH 54/68] Revert "updating Hashicorp's changes to merged simple linux branch" This reverts commit dbaf8d14a9cdfcef0281919671357f6171ebd4e6. --- examples/azure-vm-simple-linux-managed-disk/README.md | 8 ++++++-- .../azure-vm-simple-linux-managed-disk/deploy.mac.sh | 2 +- examples/azure-vm-simple-linux-managed-disk/main.tf | 11 ++--------- .../azure-vm-simple-linux-managed-disk/outputs.tf | 4 ++-- .../azure-vm-simple-linux-managed-disk/provider.tf | 7 +++++++ .../terraform.tfvars | 8 ++++++++ 6 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 examples/azure-vm-simple-linux-managed-disk/provider.tf create mode 100644 examples/azure-vm-simple-linux-managed-disk/terraform.tfvars diff --git a/examples/azure-vm-simple-linux-managed-disk/README.md b/examples/azure-vm-simple-linux-managed-disk/README.md index cde5c458e82d..0492e3edccb9 100644 --- a/examples/azure-vm-simple-linux-managed-disk/README.md +++ b/examples/azure-vm-simple-linux-managed-disk/README.md @@ -1,6 +1,10 @@ # Very simple deployment of a Linux VM -This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy an A0 size VM in the resource group location and return the FQDN of the VM. + + + + +This template allows you to deploy a simple Linux VM using a few different options for the Ubuntu version, using the latest patched version. This will deploy a A1 size VM in the resource group location and return the FQDN of the VM. This template takes a minimum amount of parameters and deploys a Linux VM, using the latest patched version. @@ -17,4 +21,4 @@ Azure requires that an application is added to Azure Active Directory to generat If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. ## variables.tf -The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. \ No newline at end of file +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. diff --git a/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh b/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh index dfc34c2be2fc..9c6563f07d71 100755 --- a/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh +++ b/examples/azure-vm-simple-linux-managed-disk/deploy.mac.sh @@ -12,4 +12,4 @@ if docker -v; then else echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" -fi \ No newline at end of file +fi diff --git a/examples/azure-vm-simple-linux-managed-disk/main.tf b/examples/azure-vm-simple-linux-managed-disk/main.tf index 5dc9ce1cb086..8ef283c7819c 100644 --- a/examples/azure-vm-simple-linux-managed-disk/main.tf +++ b/examples/azure-vm-simple-linux-managed-disk/main.tf @@ -1,10 +1,3 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } - resource "azurerm_resource_group" "rg" { name = "${var.resource_group}" location = "${var.location}" @@ -41,7 +34,7 @@ resource "azurerm_public_ip" "pip" { name = "${var.rg_prefix}-ip" location = "${var.location}" resource_group_name = "${azurerm_resource_group.rg.name}" - public_ip_address_allocation = "Dynamic" + public_ip_address_allocation = "dynamic" domain_name_label = "${var.dns_name}" } @@ -102,7 +95,7 @@ resource "azurerm_virtual_machine" "vm" { } boot_diagnostics { - enabled = true + enabled = "true" storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}" } } \ No newline at end of file diff --git a/examples/azure-vm-simple-linux-managed-disk/outputs.tf b/examples/azure-vm-simple-linux-managed-disk/outputs.tf index 32c6294ceeab..9e3c2f0712bc 100644 --- a/examples/azure-vm-simple-linux-managed-disk/outputs.tf +++ b/examples/azure-vm-simple-linux-managed-disk/outputs.tf @@ -6,6 +6,6 @@ output "vm_fqdn" { value = "${azurerm_public_ip.pip.fqdn}" } -output "ssh_command" { +output "sshCommand" { value = "ssh ${var.admin_username}@${azurerm_public_ip.pip.fqdn}" -} \ No newline at end of file +} diff --git a/examples/azure-vm-simple-linux-managed-disk/provider.tf b/examples/azure-vm-simple-linux-managed-disk/provider.tf new file mode 100644 index 000000000000..79291f7ca895 --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/provider.tf @@ -0,0 +1,7 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + diff --git a/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars b/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars new file mode 100644 index 000000000000..bee98e4e11bc --- /dev/null +++ b/examples/azure-vm-simple-linux-managed-disk/terraform.tfvars @@ -0,0 +1,8 @@ +# Replace with relevant values + +# resource_group = "myresourcegroup" +# rg_prefix = "rg" +# hostname = "myvm" +# dns_name = "mydnsname" +# location = "southcentralus" +# admin_password = "T3rr@f0rmP@ssword" From 5174369a32b753c9980b01165b1d3a12e9ee4c10 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 4 May 2017 11:47:57 -0500 Subject: [PATCH 55/68] removing vm from user image example from this branch --- examples/azure-vm-from-user-image/README.md | 28 --------- .../after_deploy.ci.sh | 11 ---- .../azure-vm-from-user-image/deploy.ci.sh | 37 ----------- .../azure-vm-from-user-image/deploy.mac.sh | 18 ------ examples/azure-vm-from-user-image/main.tf | 62 ------------------- examples/azure-vm-from-user-image/outputs.tf | 11 ---- examples/azure-vm-from-user-image/provider.tf | 6 -- .../azure-vm-from-user-image/terraform.tfvars | 13 ---- .../azure-vm-from-user-image/variables.tf | 56 ----------------- 9 files changed, 242 deletions(-) delete mode 100644 examples/azure-vm-from-user-image/README.md delete mode 100755 examples/azure-vm-from-user-image/after_deploy.ci.sh delete mode 100755 examples/azure-vm-from-user-image/deploy.ci.sh delete mode 100755 examples/azure-vm-from-user-image/deploy.mac.sh delete mode 100644 examples/azure-vm-from-user-image/main.tf delete mode 100644 examples/azure-vm-from-user-image/outputs.tf delete mode 100644 examples/azure-vm-from-user-image/provider.tf delete mode 100644 examples/azure-vm-from-user-image/terraform.tfvars delete mode 100644 examples/azure-vm-from-user-image/variables.tf diff --git a/examples/azure-vm-from-user-image/README.md b/examples/azure-vm-from-user-image/README.md deleted file mode 100644 index 455b0bcb1a5f..000000000000 --- a/examples/azure-vm-from-user-image/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# [Create a Virtual Machine from a User Image](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-deploy-templates#create-a-custom-vm-image) - -This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image) Azure Quickstart Template. Changes to the ARM template may have occured since the creation of this example may not be reflected here. - - - - - -> Prerequisite - The generalized image VHD should exist, as well as a Storage Account for boot diagnostics - -This template allows you to create a Virtual Machine from an unmanaged User image vhd. This template also deploys a Virtual Network, Public IP addresses and a Network Interface. - -## main.tf -The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. - -## outputs.tf -This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. - -## provider.tf -Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. - -## terraform.tfvars -If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. - -If you are committing this template to source control, please insure that you add this file to your `.gitignore` file. - -## variables.tf -The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. diff --git a/examples/azure-vm-from-user-image/after_deploy.ci.sh b/examples/azure-vm-from-user-image/after_deploy.ci.sh deleted file mode 100755 index 8a5624eb7681..000000000000 --- a/examples/azure-vm-from-user-image/after_deploy.ci.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -docker run --rm -it \ - azuresdk/azure-cli-python \ - sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID; \ - az vm delete --name $KEY --resource-group permanent -y; \ - az network nic delete --name $KEY'nic' --resource-group permanent; \ - az network vnet delete --name $KEY'vnet' --resource-group permanent; \ - az network public-ip delete --name $KEY'-ip' --resource-group permanent;" diff --git a/examples/azure-vm-from-user-image/deploy.ci.sh b/examples/azure-vm-from-user-image/deploy.ci.sh deleted file mode 100755 index f45c5bb2a6cd..000000000000 --- a/examples/azure-vm-from-user-image/deploy.ci.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -docker run --rm -it \ - -e ARM_CLIENT_ID \ - -e ARM_CLIENT_SECRET \ - -e ARM_SUBSCRIPTION_ID \ - -e ARM_TENANT_ID \ - -v $(pwd):/data \ - --workdir=/data \ - --entrypoint "/bin/sh" \ - hashicorp/terraform:light \ - -c "/bin/terraform get; \ - /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var hostname=$KEY -var resource_group=$EXISTING_RESOURCE_GROUP -var admin_username=$KEY -var admin_password=$PASSWORD -var image_uri=$EXISTING_IMAGE_URI -var storage_account_name=$EXISTING_STORAGE_ACCOUNT_NAME; \ - /bin/terraform apply out.tfplan" - -# echo "Setting git user name" -# git config user.name $GH_USER_NAME -# -# echo "Setting git user email" -# git config user.email $GH_USER_EMAIL -# -# echo "Adding git upstream remote" -# git remote add upstream "https://$GH_TOKEN@github.com/$GH_REPO.git" -# -# git checkout master - - -# -# NOW=$(TZ=America/Chicago date) -# -# git commit -m "tfstate: $NOW [ci skip]" -# -# echo "Pushing changes to upstream master" -# git push upstream master diff --git a/examples/azure-vm-from-user-image/deploy.mac.sh b/examples/azure-vm-from-user-image/deploy.mac.sh deleted file mode 100755 index acd4ca7028fc..000000000000 --- a/examples/azure-vm-from-user-image/deploy.mac.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -o errexit -o nounset - -if docker -v; then - - # generate a unique string for CI deployment - export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) - export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor - export EXISTING_RESOURCE_GROUP=permanent - - /bin/sh ./deploy.ci.sh - -else - echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" -fi diff --git a/examples/azure-vm-from-user-image/main.tf b/examples/azure-vm-from-user-image/main.tf deleted file mode 100644 index 28edf99204b5..000000000000 --- a/examples/azure-vm-from-user-image/main.tf +++ /dev/null @@ -1,62 +0,0 @@ -resource "azurerm_resource_group" "rg" { - name = "${var.resource_group}" - location = "${var.location}" -} - -resource "azurerm_virtual_network" "vnet" { - name = "${var.hostname}vnet" - location = "${var.location}" - address_space = ["${var.address_space}"] - resource_group_name = "${azurerm_resource_group.rg.name}" -} - -resource "azurerm_subnet" "subnet" { - name = "${var.hostname}subnet" - virtual_network_name = "${azurerm_virtual_network.vnet.name}" - resource_group_name = "${azurerm_resource_group.rg.name}" - address_prefix = "${var.subnet_prefix}" -} - -resource "azurerm_network_interface" "nic" { - name = "${var.hostname}nic" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - - ip_configuration { - name = "${var.hostname}ipconfig" - subnet_id = "${azurerm_subnet.subnet.id}" - private_ip_address_allocation = "Dynamic" - public_ip_address_id = "${azurerm_public_ip.pip.id}" - } -} - -resource "azurerm_public_ip" "pip" { - name = "${var.hostname}-ip" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - public_ip_address_allocation = "dynamic" - domain_name_label = "${var.hostname}" -} - -resource "azurerm_virtual_machine" "vm" { - name = "${var.hostname}" - location = "${var.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - vm_size = "${var.vm_size}" - network_interface_ids = ["${azurerm_network_interface.nic.id}"] - - storage_os_disk { - name = "${var.hostname}-osdisk1" - image_uri = "${var.image_uri}" - vhd_uri = "https://${var.storage_account_name}.blob.core.windows.net/vhds/${var.hostname}osdisk.vhd" - os_type = "${var.os_type}" - caching = "ReadWrite" - create_option = "FromImage" - } - - os_profile { - computer_name = "${var.hostname}" - admin_username = "${var.admin_username}" - admin_password = "${var.admin_password}" - } -} diff --git a/examples/azure-vm-from-user-image/outputs.tf b/examples/azure-vm-from-user-image/outputs.tf deleted file mode 100644 index e0e255a9e01c..000000000000 --- a/examples/azure-vm-from-user-image/outputs.tf +++ /dev/null @@ -1,11 +0,0 @@ -output "hostname" { - value = "${var.hostname}" -} - -output "vm_fqdn" { - value = "${azurerm_public_ip.pip.fqdn}" -} - -output "sshCommand" { - value = "${concat("ssh ", var.admin_username, "@", azurerm_public_ip.pip.fqdn)}" -} diff --git a/examples/azure-vm-from-user-image/provider.tf b/examples/azure-vm-from-user-image/provider.tf deleted file mode 100644 index bdf0583f3259..000000000000 --- a/examples/azure-vm-from-user-image/provider.tf +++ /dev/null @@ -1,6 +0,0 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } diff --git a/examples/azure-vm-from-user-image/terraform.tfvars b/examples/azure-vm-from-user-image/terraform.tfvars deleted file mode 100644 index 15da2a9c6ca7..000000000000 --- a/examples/azure-vm-from-user-image/terraform.tfvars +++ /dev/null @@ -1,13 +0,0 @@ -# resource_group = "myresourcegroup" -# image_uri = "https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd" -# primary_blob_endpoint = "https://DISK.blob.core.windows.net/" -# location = "southcentralus" -# os_type = "linux" -# address_space = "10.0.0.0/16" -# subnet_prefix = "10.0.0.0/24" -# storage_account_name = "STOR-ACCT-NAME" -# storage_account_type = "Standard_LRS" -# vm_size = "Standard_DS1_v2" -# hostname = "HOSTNAME" -# admin_username = "vmadmin" -# admin_password = "YOURPASSWORDHERE" diff --git a/examples/azure-vm-from-user-image/variables.tf b/examples/azure-vm-from-user-image/variables.tf deleted file mode 100644 index b3e94928978d..000000000000 --- a/examples/azure-vm-from-user-image/variables.tf +++ /dev/null @@ -1,56 +0,0 @@ -variable "resource_group" { - description = "The name of the resource group in which the image to clone resides." - default = "myrg" -} - -variable "image_uri" { - description = "Specifies the image_uri in the form publisherName:offer:skus:version. image_uri can also specify the VHD uri of a custom VM image to clone." -} - -variable "os_type" { - description = "Specifies the operating system Type, valid values are windows, linux." - default = "linux" -} - -variable "location" { - description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." - default = "southcentralus" -} - -variable "address_space" { - description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." - default = "10.0.0.0/24" -} - -variable "subnet_prefix" { - description = "The address prefix to use for the subnet." - default = "10.0.0.0/24" -} - -variable "storage_account_name" { - description = "The name of the storage account in which the image from which you are cloning resides." -} - -variable "storage_account_type" { - description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." - default = "Premium_LRS" -} - -variable "vm_size" { - description = "Specifies the size of the virtual machine. This must be the same as the vm image from which you are copying." - default = "Standard_DS1_v2" -} - -variable "hostname" { - description = "VM name referenced also in storage-related names. This is also used as the label for the Domain Name and to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." -} - -variable "admin_username" { - description = "administrator user name" - default = "vmadmin" -} - -variable "admin_password" { - description = "administrator password (recommended to disable password auth)" - default = "T3rr@f0rmP@ssword" -} From 1366980b8b8a03eadd4472d9d9346d50eeebb9c0 Mon Sep 17 00:00:00 2001 From: Annie Hedgpeth Date: Thu, 4 May 2017 18:10:14 -0500 Subject: [PATCH 56/68] removed old branch --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 907dafde5d25..2432ad83a56b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,5 +36,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: topic-101-vm-from-user-image - branch: master \ No newline at end of file + branch: master From 6a1813e07fa3412b86d523973c96374c1976ea64 Mon Sep 17 00:00:00 2001 From: Scott Nowicki Date: Fri, 5 May 2017 15:08:09 -0500 Subject: [PATCH 57/68] azure-2-vms-loadbalancer-lbrules (#13) * initial commit * need to change lb_rule & nic * deploys locally * updated README * updated travis and deploy scripts for Hari's repo * renamed deploy script * clean up * prep for PR * updated readme * fixing conflict in .travis.yml --- .travis.yml | 2 +- .../README.md | 26 ++++ .../deploy.ci.sh | 36 +++++ .../deploy.mac.sh | 15 ++ .../azure-2-vms-loadbalancer-lbrules/main.tf | 138 ++++++++++++++++++ .../outputs.tf | 11 ++ .../provider.tf | 6 + .../terraform.tfvars | 6 + .../variables.tf | 80 ++++++++++ 9 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 examples/azure-2-vms-loadbalancer-lbrules/README.md create mode 100755 examples/azure-2-vms-loadbalancer-lbrules/deploy.ci.sh create mode 100755 examples/azure-2-vms-loadbalancer-lbrules/deploy.mac.sh create mode 100644 examples/azure-2-vms-loadbalancer-lbrules/main.tf create mode 100644 examples/azure-2-vms-loadbalancer-lbrules/outputs.tf create mode 100644 examples/azure-2-vms-loadbalancer-lbrules/provider.tf create mode 100644 examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars create mode 100644 examples/azure-2-vms-loadbalancer-lbrules/variables.tf diff --git a/.travis.yml b/.travis.yml index 2432ad83a56b..93e8b1d03795 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,4 +36,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: master + branch: master \ No newline at end of file diff --git a/examples/azure-2-vms-loadbalancer-lbrules/README.md b/examples/azure-2-vms-loadbalancer-lbrules/README.md new file mode 100644 index 000000000000..d7ca3d4d3cb6 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/README.md @@ -0,0 +1,26 @@ +# Create 2 Virtual Machines under a Load balancer and configures Load Balancing rules for the VMs + +This Terraform template was based on [this](https://github.com/Azure/azure-quickstart-templates/tree/master/201-2-vms-loadbalancer-lbrules) Azure Quickstart Template. Changes to the ARM template may have occured since the creation of this example may not be reflected here. + + + + + +This template allows you to create 2 Virtual Machines under a Load balancer and configure a load balancing rule on Port 80. This template also deploys a Storage Account, Virtual Network, Public IP address, Availability Set, and Network Interfaces. + +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +If you are committing this template to source control, please insure that you add this file to your .gitignore file. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. diff --git a/examples/azure-2-vms-loadbalancer-lbrules/deploy.ci.sh b/examples/azure-2-vms-loadbalancer-lbrules/deploy.ci.sh new file mode 100755 index 000000000000..57e0dc9b1a42 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/deploy.ci.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +set -o errexit -o nounset + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "cd /data; \ + /bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var dns_name=$KEY -var hostname=$KEY -var lb_ip_dns_name=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD; \ + /bin/terraform apply out.tfplan" + +# cleanup deployed azure resources via azure-cli +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ + az network lb show -g $KEY -n rglb; \ + az network lb rule list -g $KEY --lb-name rglb;" + +# cleanup deployed azure resources via terraform +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform destroy -force -var dns_name=$KEY -var hostname=$KEY -var lb_ip_dns_name=$KEY -var resource_group=$KEY -var admin_password=$PASSWORD;" diff --git a/examples/azure-2-vms-loadbalancer-lbrules/deploy.mac.sh b/examples/azure-2-vms-loadbalancer-lbrules/deploy.mac.sh new file mode 100755 index 000000000000..cf5cdc32279f --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/deploy.mac.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -o errexit -o nounset + +if docker -v; then + + # generate a unique string for CI deployment + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export PASSWORD=$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) + +/bin/sh ./deploy.ci.sh + +else + echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" +fi \ No newline at end of file diff --git a/examples/azure-2-vms-loadbalancer-lbrules/main.tf b/examples/azure-2-vms-loadbalancer-lbrules/main.tf new file mode 100644 index 000000000000..24981118d3e2 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/main.tf @@ -0,0 +1,138 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_storage_account" "stor" { + name = "${var.dns_name}stor" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + account_type = "${var.storage_account_type}" +} + +resource "azurerm_availability_set" "avset" { + name = "${var.dns_name}avset" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + platform_fault_domain_count = 2 + platform_update_domain_count = 2 + managed = true +} + +resource "azurerm_public_ip" "lbpip" { + name = "${var.rg_prefix}-ip" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + public_ip_address_allocation = "dynamic" + domain_name_label = "${var.lb_ip_dns_name}" +} + +resource "azurerm_virtual_network" "vnet" { + name = "${var.virtual_network_name}" + location = "${var.location}" + address_space = ["${var.address_space}"] + resource_group_name = "${azurerm_resource_group.rg.name}" +} + +resource "azurerm_subnet" "subnet" { + name = "${var.rg_prefix}subnet" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + address_prefix = "${var.subnet_prefix}" +} + +resource "azurerm_lb" "lb" { + resource_group_name = "${azurerm_resource_group.rg.name}" + name = "${var.rg_prefix}lb" + location = "${var.location}" + + frontend_ip_configuration { + name = "LoadBalancerFrontEnd" + public_ip_address_id = "${azurerm_public_ip.lbpip.id}" + } +} + +resource "azurerm_lb_backend_address_pool" "backend_pool" { + resource_group_name = "${azurerm_resource_group.rg.name}" + loadbalancer_id = "${azurerm_lb.lb.id}" + name = "BackendPool1" +} + +resource "azurerm_lb_nat_rule" "tcp" { + resource_group_name = "${azurerm_resource_group.rg.name}" + loadbalancer_id = "${azurerm_lb.lb.id}" + name = "RDP-VM-${count.index}" + protocol = "tcp" + frontend_port = "5000${count.index + 1}" + backend_port = 3389 + frontend_ip_configuration_name = "LoadBalancerFrontEnd" + count = 2 +} + +resource "azurerm_lb_rule" "lb_rule" { + resource_group_name = "${azurerm_resource_group.rg.name}" + loadbalancer_id = "${azurerm_lb.lb.id}" + name = "LBRule" + protocol = "tcp" + frontend_port = 80 + backend_port = 80 + frontend_ip_configuration_name = "LoadBalancerFrontEnd" + enable_floating_ip = false + backend_address_pool_id = "${azurerm_lb_backend_address_pool.backend_pool.id}" + idle_timeout_in_minutes = 5 + probe_id = "${azurerm_lb_probe.lb_probe.id}" + depends_on = ["azurerm_lb_probe.lb_probe"] +} + +resource "azurerm_lb_probe" "lb_probe" { + resource_group_name = "${azurerm_resource_group.rg.name}" + loadbalancer_id = "${azurerm_lb.lb.id}" + name = "tcpProbe" + protocol = "tcp" + port = 80 + interval_in_seconds = 5 + number_of_probes = 2 +} + +resource "azurerm_network_interface" "nic" { + name = "nic${count.index}" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + count = 2 + + ip_configuration { + name = "ipconfig${count.index}" + subnet_id = "${azurerm_subnet.subnet.id}" + private_ip_address_allocation = "Dynamic" + load_balancer_backend_address_pools_ids = ["${azurerm_lb_backend_address_pool.backend_pool.id}"] + load_balancer_inbound_nat_rules_ids = ["${element(azurerm_lb_nat_rule.tcp.*.id, count.index)}"] + } +} + +resource "azurerm_virtual_machine" "vm" { + name = "vm${count.index}" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + availability_set_id = "${azurerm_availability_set.avset.id}" + vm_size = "${var.vm_size}" + network_interface_ids = ["${element(azurerm_network_interface.nic.*.id, count.index)}"] + count = 2 + + storage_image_reference { + publisher = "${var.image_publisher}" + offer = "${var.image_offer}" + sku = "${var.image_sku}" + version = "${var.image_version}" + } + + storage_os_disk { + name = "osdisk${count.index}" + create_option = "FromImage" + } + + os_profile { + computer_name = "${var.hostname}" + admin_username = "${var.admin_username}" + admin_password = "${var.admin_password}" + } +} diff --git a/examples/azure-2-vms-loadbalancer-lbrules/outputs.tf b/examples/azure-2-vms-loadbalancer-lbrules/outputs.tf new file mode 100644 index 000000000000..a21a9568b688 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/outputs.tf @@ -0,0 +1,11 @@ +output "hostname" { + value = "${var.hostname}" +} + +output "vm_fqdn" { + value = "${azurerm_public_ip.lbpip.fqdn}" +} + +output "sshCommand" { + value = "ssh ${var.admin_username}@${azurerm_public_ip.lbpip.fqdn}" +} diff --git a/examples/azure-2-vms-loadbalancer-lbrules/provider.tf b/examples/azure-2-vms-loadbalancer-lbrules/provider.tf new file mode 100644 index 000000000000..bdf0583f3259 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/provider.tf @@ -0,0 +1,6 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } diff --git a/examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars b/examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars new file mode 100644 index 000000000000..824d4a691b61 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars @@ -0,0 +1,6 @@ +# resource_group = "myresourcegroup" +# rg_prefix = "rg" +# hostname = "myvm" +# dns_name = "mydnsname" +# location = "southcentralus" +# admin_password = "T3rr@f0rmP@ssword" diff --git a/examples/azure-2-vms-loadbalancer-lbrules/variables.tf b/examples/azure-2-vms-loadbalancer-lbrules/variables.tf new file mode 100644 index 000000000000..55320c2653a4 --- /dev/null +++ b/examples/azure-2-vms-loadbalancer-lbrules/variables.tf @@ -0,0 +1,80 @@ +variable "resource_group" { + description = "The name of the resource group in which to create the virtual network." +} + +variable "rg_prefix" { + description = "The shortened abbreviation to represent your resource group that will go on the front of some resources." + default = "rg" +} + +variable "hostname" { + description = "VM name referenced also in storage-related names." +} + +variable "dns_name" { + description = " Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." +} + +variable "lb_ip_dns_name" { + description = "DNS for Load Balancer IP" +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "virtual_network_name" { + description = "The name for the virtual network." + default = "vnet" +} + +variable "address_space" { + description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created." + default = "10.0.0.0/16" +} + +variable "subnet_prefix" { + description = "The address prefix to use for the subnet." + default = "10.0.10.0/24" +} + +variable "storage_account_type" { + description = "Defines the type of storage account to be created. Valid options are Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Premium_LRS. Changing this is sometimes valid - see the Azure documentation for more information on which types of accounts can be converted into other types." + default = "Standard_LRS" +} + +variable "vm_size" { + description = "Specifies the size of the virtual machine." + default = "Standard_D1" +} + +variable "image_publisher" { + description = "name of the publisher of the image (az vm image list)" + default = "MicrosoftWindowsServer" +} + +variable "image_offer" { + description = "the name of the offer (az vm image list)" + default = "WindowsServer" +} + +variable "image_sku" { + description = "image sku to apply (az vm image list)" + default = "2012-R2-Datacenter" +} + +variable "image_version" { + description = "version of the image to apply (az vm image list)" + default = "latest" +} + +variable "admin_username" { + description = "administrator user name" + default = "vmadmin" +} + +variable "admin_password" { + description = "administrator password (recommended to disable password auth)" + default = "T3rr@f0rmP@ssword" +} From 49d51b45b97b4aa7d5747432513f9120f2fa514e Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Fri, 5 May 2017 21:27:32 -0500 Subject: [PATCH 58/68] initial commit; missing resource for transparentDataEncryption --- .../README.md | 22 +++++++++ .../deploy.ci.sh | 37 +++++++++++++++ .../deploy.mac.sh | 16 +++++++ .../main.tf | 46 +++++++++++++++++++ .../outputs.tf | 7 +++ .../variables.tf | 16 +++++++ 6 files changed, 144 insertions(+) create mode 100644 examples/azure-sql-database-tranparent-encryption-create/README.md create mode 100755 examples/azure-sql-database-tranparent-encryption-create/deploy.ci.sh create mode 100755 examples/azure-sql-database-tranparent-encryption-create/deploy.mac.sh create mode 100644 examples/azure-sql-database-tranparent-encryption-create/main.tf create mode 100644 examples/azure-sql-database-tranparent-encryption-create/outputs.tf create mode 100644 examples/azure-sql-database-tranparent-encryption-create/variables.tf diff --git a/examples/azure-sql-database-tranparent-encryption-create/README.md b/examples/azure-sql-database-tranparent-encryption-create/README.md new file mode 100644 index 000000000000..944449ac741d --- /dev/null +++ b/examples/azure-sql-database-tranparent-encryption-create/README.md @@ -0,0 +1,22 @@ +# Provision a SQL Database with Transparent Data Encryption + +This sample creates a SQL Database at the "Basic" service level. The template can support other tiers of service, details for each service can be found here: + +[SQL Database Pricing](https://azure.microsoft.com/en-us/pricing/details/sql-database/) + +For more information about Transparent Data Encryption (TDE), see [Transparent Data Encryption with Azure SQL Database](https://msdn.microsoft.com/en-us/library/dn948096.aspx). + +## main.tf +The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. + +## outputs.tf +This data is outputted when `terraform apply` is called, and can be queried using the `terraform output` command. + +## provider.tf +Azure requires that an application is added to Azure Active Directory to generate the `client_id`, `client_secret`, and `tenant_id` needed by Terraform (`subscription_id` can be recovered from your Azure account details). Please go [here](https://www.terraform.io/docs/providers/azurerm/) for full instructions on how to create this to populate your `provider.tf` file. + +## terraform.tfvars +If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. + +## variables.tf +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. \ No newline at end of file diff --git a/examples/azure-sql-database-tranparent-encryption-create/deploy.ci.sh b/examples/azure-sql-database-tranparent-encryption-create/deploy.ci.sh new file mode 100755 index 000000000000..68b7fa42c708 --- /dev/null +++ b/examples/azure-sql-database-tranparent-encryption-create/deploy.ci.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -o errexit -o nounset + +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform get; \ + /bin/terraform validate; \ + /bin/terraform plan -out=out.tfplan -var resource_group=$KEY -var sql_admin=$KEY -var sql_password=$PASSWORD; \ + /bin/terraform apply out.tfplan; \ + /bin/terraform show;" + +# check that resources exist via azure cli +docker run --rm -it \ + azuresdk/azure-cli-python \ + sh -c "az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID > /dev/null; \ + az sql db show -g $KEY -n MySQLDatabase -s $KEY-sqlsvr; \ + az sql server show -g $KEY -n $KEY-sqlsvr;" + +# cleanup deployed azure resources via terraform +docker run --rm -it \ + -e ARM_CLIENT_ID \ + -e ARM_CLIENT_SECRET \ + -e ARM_SUBSCRIPTION_ID \ + -e ARM_TENANT_ID \ + -v $(pwd):/data \ + --workdir=/data \ + --entrypoint "/bin/sh" \ + hashicorp/terraform:light \ + -c "/bin/terraform destroy -force -var resource_group=$KEY -var sql_admin=$KEY -var sql_password=$PASSWORD;" \ No newline at end of file diff --git a/examples/azure-sql-database-tranparent-encryption-create/deploy.mac.sh b/examples/azure-sql-database-tranparent-encryption-create/deploy.mac.sh new file mode 100755 index 000000000000..ff2d162a1308 --- /dev/null +++ b/examples/azure-sql-database-tranparent-encryption-create/deploy.mac.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -o errexit -o nounset + +if docker -v; then + + # generate a unique string for CI deployment + export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) + export PASSWORD=$#@abcd9753w0w@h@ + # =$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) + + /bin/sh ./deploy.ci.sh + +else + echo "Docker is used to run terraform commands, please install before run: https://docs.docker.com/docker-for-mac/install/" +fi \ No newline at end of file diff --git a/examples/azure-sql-database-tranparent-encryption-create/main.tf b/examples/azure-sql-database-tranparent-encryption-create/main.tf new file mode 100644 index 000000000000..39ad1dcc9ce7 --- /dev/null +++ b/examples/azure-sql-database-tranparent-encryption-create/main.tf @@ -0,0 +1,46 @@ +# provider "azurerm" { +# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" +# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" +# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" +# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" +# } + +resource "azurerm_resource_group" "rg" { + name = "${var.resource_group}" + location = "${var.location}" +} + +resource "azurerm_sql_database" "db" { + name = "mysqldatabase" + resource_group_name = "${azurerm_resource_group.rg.name}" + location = "${var.location}" + edition = "Basic" + collation = "SQL_Latin1_General_CP1_CI_AS" + create_mode = "Default" + requested_service_objective_name = "Basic" + server_name = "${azurerm_sql_server.server.name}" +} + +resource "azurerm_sql_server" "server" { + name = "${var.resource_group}-sqlsvr" + resource_group_name = "${azurerm_resource_group.rg.name}" + location = "${var.location}" + version = "12.0" + administrator_login = "${var.sql_admin}" + administrator_login_password = "${var.sql_password}" +} + +resource "azurerm_sql_firewall_rule" "fw" { + name = "firewallrules" + resource_group_name = "${azurerm_resource_group.rg.name}" + server_name = "${azurerm_sql_server.server.name}" + start_ip_address = "0.0.0.0" + end_ip_address = "0.0.0.0" +} + +# "comments": "Transparent Data Encryption", +# "name": "current", +# "type": "transparentDataEncryption", +# "apiVersion": "2014-04-01-preview", +# "properties": { +# "status": "[parameters('transparentDataEncryption')]" \ No newline at end of file diff --git a/examples/azure-sql-database-tranparent-encryption-create/outputs.tf b/examples/azure-sql-database-tranparent-encryption-create/outputs.tf new file mode 100644 index 000000000000..89d7e3cc068d --- /dev/null +++ b/examples/azure-sql-database-tranparent-encryption-create/outputs.tf @@ -0,0 +1,7 @@ +output "database_name" { + value = "${azurerm_sql_database.db.name}" +} + +output "sql_server_fqdn" { + value = "${azurerm_sql_server.server.fully_qualified_domain_name}" +} diff --git a/examples/azure-sql-database-tranparent-encryption-create/variables.tf b/examples/azure-sql-database-tranparent-encryption-create/variables.tf new file mode 100644 index 000000000000..8b8622fc553d --- /dev/null +++ b/examples/azure-sql-database-tranparent-encryption-create/variables.tf @@ -0,0 +1,16 @@ +variable "resource_group" { + description = "The name of the resource group in which to create the virtual network." +} + +variable "location" { + description = "The location/region where the virtual network is created. Changing this forces a new resource to be created." + default = "southcentralus" +} + +variable "sql_admin" { + description = "The administrator username of the SQL Server." +} + +variable "sql_password" { + description = "The administrator password of the SQL Server." +} From bf1cb877451635b74e9b9798bfcc8a40e0faab37 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 16:59:57 -0500 Subject: [PATCH 59/68] commented out missing resources for TDE --- .../README.md | 2 ++ .../main.tf | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/examples/azure-sql-database-tranparent-encryption-create/README.md b/examples/azure-sql-database-tranparent-encryption-create/README.md index 944449ac741d..d9eb911d626e 100644 --- a/examples/azure-sql-database-tranparent-encryption-create/README.md +++ b/examples/azure-sql-database-tranparent-encryption-create/README.md @@ -1,5 +1,7 @@ # Provision a SQL Database with Transparent Data Encryption +*Terraform does not currently have a resource for Transparent Data Encryption. When [this feature request](https://github.com/hashicorp/terraform/issues/14595) is fulfilled, this example will be able to be used.* + This sample creates a SQL Database at the "Basic" service level. The template can support other tiers of service, details for each service can be found here: [SQL Database Pricing](https://azure.microsoft.com/en-us/pricing/details/sql-database/) diff --git a/examples/azure-sql-database-tranparent-encryption-create/main.tf b/examples/azure-sql-database-tranparent-encryption-create/main.tf index 39ad1dcc9ce7..36946741ab30 100644 --- a/examples/azure-sql-database-tranparent-encryption-create/main.tf +++ b/examples/azure-sql-database-tranparent-encryption-create/main.tf @@ -19,6 +19,13 @@ resource "azurerm_sql_database" "db" { create_mode = "Default" requested_service_objective_name = "Basic" server_name = "${azurerm_sql_server.server.name}" + + # Terraform does not currently support this resource. + # transparent_data_encryption { + # name = "current" + # type = "transparentDataEncryption" + # status = "Enabled" + # } } resource "azurerm_sql_server" "server" { @@ -37,10 +44,3 @@ resource "azurerm_sql_firewall_rule" "fw" { start_ip_address = "0.0.0.0" end_ip_address = "0.0.0.0" } - -# "comments": "Transparent Data Encryption", -# "name": "current", -# "type": "transparentDataEncryption", -# "apiVersion": "2014-04-01-preview", -# "properties": { -# "status": "[parameters('transparentDataEncryption')]" \ No newline at end of file From f49497220d15888cbe66ffb8d87716dcb3ef35f1 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 17:07:18 -0500 Subject: [PATCH 60/68] updated .travis.yml --- .travis.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 93e8b1d03795..19f00c89f6f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,15 @@ git: # establish environment variables env: - - TEST_DIR=examples/azure-vm-from-user-image - - TEST_DIR=examples/azure-cdn-with-storage-account - - TEST_DIR=examples/azure-vm-simple-linux-managed-disk - - TEST_DIR=examples/azure-vnet-two-subnets + - TEST_DIR=examples/azure-sql-database-transparent-encryption-create + # - TEST_DIR=examples/azure-servicebus-create-topic-and-subscription + # - TEST_DIR=examples/azure-search-create + # - TEST_DIR=examples/azure-vnet-to-vnet-peering + # - TEST_DIR=examples/azure-traffic-manager-vm + # - TEST_DIR=examples/azure-vm-from-user-image + # - TEST_DIR=examples/azure-cdn-with-storage-account + # - TEST_DIR=examples/azure-vm-simple-linux-managed-disk + # - TEST_DIR=examples/azure-vnet-two-subnets branches: only: @@ -36,4 +41,4 @@ deploy: script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh on: repo: harijayms/terraform - branch: master \ No newline at end of file + branch: topic-201-sql-database \ No newline at end of file From 62f1892d6c0d1fbf9bbc52b61cbec795b6685ffa Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 17:21:38 -0500 Subject: [PATCH 61/68] typo fix on .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 19f00c89f6f8..37b07e197356 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ git: # establish environment variables env: - - TEST_DIR=examples/azure-sql-database-transparent-encryption-create + - TEST_DIR=examples/azure-sql-database-tranparent-encryption-create # - TEST_DIR=examples/azure-servicebus-create-topic-and-subscription # - TEST_DIR=examples/azure-search-create # - TEST_DIR=examples/azure-vnet-to-vnet-peering From 78d30cc8ca1b440a518a691cae9f12444bfb1847 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 17:29:40 -0500 Subject: [PATCH 62/68] changed directory name to omit TDE --- .travis.yml | 2 +- .../README.md | 6 +----- .../deploy.ci.sh | 0 .../deploy.mac.sh | 0 .../main.tf | 7 ------- .../outputs.tf | 0 .../variables.tf | 0 7 files changed, 2 insertions(+), 13 deletions(-) rename examples/{azure-sql-database-tranparent-encryption-create => azure-sql-database}/README.md (75%) rename examples/{azure-sql-database-tranparent-encryption-create => azure-sql-database}/deploy.ci.sh (100%) rename examples/{azure-sql-database-tranparent-encryption-create => azure-sql-database}/deploy.mac.sh (100%) rename examples/{azure-sql-database-tranparent-encryption-create => azure-sql-database}/main.tf (89%) rename examples/{azure-sql-database-tranparent-encryption-create => azure-sql-database}/outputs.tf (100%) rename examples/{azure-sql-database-tranparent-encryption-create => azure-sql-database}/variables.tf (100%) diff --git a/.travis.yml b/.travis.yml index 37b07e197356..02a1900e41ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ git: # establish environment variables env: - - TEST_DIR=examples/azure-sql-database-tranparent-encryption-create + - TEST_DIR=examples/azure-sql-database # - TEST_DIR=examples/azure-servicebus-create-topic-and-subscription # - TEST_DIR=examples/azure-search-create # - TEST_DIR=examples/azure-vnet-to-vnet-peering diff --git a/examples/azure-sql-database-tranparent-encryption-create/README.md b/examples/azure-sql-database/README.md similarity index 75% rename from examples/azure-sql-database-tranparent-encryption-create/README.md rename to examples/azure-sql-database/README.md index d9eb911d626e..a390fd5c5937 100644 --- a/examples/azure-sql-database-tranparent-encryption-create/README.md +++ b/examples/azure-sql-database/README.md @@ -1,13 +1,9 @@ -# Provision a SQL Database with Transparent Data Encryption - -*Terraform does not currently have a resource for Transparent Data Encryption. When [this feature request](https://github.com/hashicorp/terraform/issues/14595) is fulfilled, this example will be able to be used.* +# Provision a SQL Database This sample creates a SQL Database at the "Basic" service level. The template can support other tiers of service, details for each service can be found here: [SQL Database Pricing](https://azure.microsoft.com/en-us/pricing/details/sql-database/) -For more information about Transparent Data Encryption (TDE), see [Transparent Data Encryption with Azure SQL Database](https://msdn.microsoft.com/en-us/library/dn948096.aspx). - ## main.tf The `main.tf` file contains the actual resources that will be deployed. It also contains the Azure Resource Group definition and any defined variables. diff --git a/examples/azure-sql-database-tranparent-encryption-create/deploy.ci.sh b/examples/azure-sql-database/deploy.ci.sh similarity index 100% rename from examples/azure-sql-database-tranparent-encryption-create/deploy.ci.sh rename to examples/azure-sql-database/deploy.ci.sh diff --git a/examples/azure-sql-database-tranparent-encryption-create/deploy.mac.sh b/examples/azure-sql-database/deploy.mac.sh similarity index 100% rename from examples/azure-sql-database-tranparent-encryption-create/deploy.mac.sh rename to examples/azure-sql-database/deploy.mac.sh diff --git a/examples/azure-sql-database-tranparent-encryption-create/main.tf b/examples/azure-sql-database/main.tf similarity index 89% rename from examples/azure-sql-database-tranparent-encryption-create/main.tf rename to examples/azure-sql-database/main.tf index 36946741ab30..8c5d08e6bb3c 100644 --- a/examples/azure-sql-database-tranparent-encryption-create/main.tf +++ b/examples/azure-sql-database/main.tf @@ -19,13 +19,6 @@ resource "azurerm_sql_database" "db" { create_mode = "Default" requested_service_objective_name = "Basic" server_name = "${azurerm_sql_server.server.name}" - - # Terraform does not currently support this resource. - # transparent_data_encryption { - # name = "current" - # type = "transparentDataEncryption" - # status = "Enabled" - # } } resource "azurerm_sql_server" "server" { diff --git a/examples/azure-sql-database-tranparent-encryption-create/outputs.tf b/examples/azure-sql-database/outputs.tf similarity index 100% rename from examples/azure-sql-database-tranparent-encryption-create/outputs.tf rename to examples/azure-sql-database/outputs.tf diff --git a/examples/azure-sql-database-tranparent-encryption-create/variables.tf b/examples/azure-sql-database/variables.tf similarity index 100% rename from examples/azure-sql-database-tranparent-encryption-create/variables.tf rename to examples/azure-sql-database/variables.tf From 7110f86c3c11fea2ded8575e27779df428c3bc71 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 17:40:29 -0500 Subject: [PATCH 63/68] deploy troubleshooting --- .travis.yml | 2 +- examples/azure-sql-database/deploy.mac.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 02a1900e41ea..ff11dfb0ccb4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ branches: # install terraform before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) + - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2)%!@123%$! - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor - export EXISTING_RESOURCE_GROUP=permanent diff --git a/examples/azure-sql-database/deploy.mac.sh b/examples/azure-sql-database/deploy.mac.sh index ff2d162a1308..2c6ecc525343 100755 --- a/examples/azure-sql-database/deploy.mac.sh +++ b/examples/azure-sql-database/deploy.mac.sh @@ -6,7 +6,7 @@ if docker -v; then # generate a unique string for CI deployment export KEY=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-z' | head -c 12) - export PASSWORD=$#@abcd9753w0w@h@ + export PASSWORD=$a@abcd9753w0w@h@12 # =$KEY$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | env LC_CTYPE=C tr -cd '0-9' | head -c 2) /bin/sh ./deploy.ci.sh From 9b7062d8f94ec765bdfc6f443cfbc5096ba0a52c Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 17:48:43 -0500 Subject: [PATCH 64/68] password troubleshooting --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff11dfb0ccb4..7324020ebcc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ branches: # install terraform before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2)%!@123%$! + - export PASSWORD="${KEY}$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2)!" - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor - export EXISTING_RESOURCE_GROUP=permanent From 420989493444f206c47d482775e027459be6e2f6 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 17:53:12 -0500 Subject: [PATCH 65/68] troubleshooting password --- .travis.yml | 2 +- examples/azure-sql-database/deploy.ci.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7324020ebcc9..02a1900e41ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ branches: # install terraform before_deploy: - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - - export PASSWORD="${KEY}$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2)!" + - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor - export EXISTING_RESOURCE_GROUP=permanent diff --git a/examples/azure-sql-database/deploy.ci.sh b/examples/azure-sql-database/deploy.ci.sh index 68b7fa42c708..d1dc01df5a57 100755 --- a/examples/azure-sql-database/deploy.ci.sh +++ b/examples/azure-sql-database/deploy.ci.sh @@ -13,7 +13,7 @@ docker run --rm -it \ hashicorp/terraform:light \ -c "/bin/terraform get; \ /bin/terraform validate; \ - /bin/terraform plan -out=out.tfplan -var resource_group=$KEY -var sql_admin=$KEY -var sql_password=$PASSWORD; \ + /bin/terraform plan -out=out.tfplan -var resource_group=$KEY -var sql_admin=$KEY -var sql_password=a!@abcd9753w0w@h@12; \ /bin/terraform apply out.tfplan; \ /bin/terraform show;" @@ -34,4 +34,4 @@ docker run --rm -it \ --workdir=/data \ --entrypoint "/bin/sh" \ hashicorp/terraform:light \ - -c "/bin/terraform destroy -force -var resource_group=$KEY -var sql_admin=$KEY -var sql_password=$PASSWORD;" \ No newline at end of file + -c "/bin/terraform destroy -force -var resource_group=$KEY -var sql_admin=$KEY -var sql_password=a!@abcd9753w0w@h@12;" \ No newline at end of file From 3f092803cc8101d60bf16eee55c496251bb1c84a Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 19:02:05 -0500 Subject: [PATCH 66/68] merging hashi master into this branch --- .../azure-2-vms-loadbalancer-lbrules/provider.tf | 6 ------ .../terraform.tfvars | 6 ------ .../provider.tf.example | 7 ------- .../azure-cdn-with-storage-account/terraform.tfvars | 8 -------- examples/azure-vm-from-user-image/provider.tf | 6 ------ examples/azure-vm-from-user-image/terraform.tfvars | 13 ------------- 6 files changed, 46 deletions(-) delete mode 100644 examples/azure-2-vms-loadbalancer-lbrules/provider.tf delete mode 100644 examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars delete mode 100644 examples/azure-cdn-with-storage-account/provider.tf.example delete mode 100644 examples/azure-cdn-with-storage-account/terraform.tfvars delete mode 100644 examples/azure-vm-from-user-image/provider.tf delete mode 100644 examples/azure-vm-from-user-image/terraform.tfvars diff --git a/examples/azure-2-vms-loadbalancer-lbrules/provider.tf b/examples/azure-2-vms-loadbalancer-lbrules/provider.tf deleted file mode 100644 index bdf0583f3259..000000000000 --- a/examples/azure-2-vms-loadbalancer-lbrules/provider.tf +++ /dev/null @@ -1,6 +0,0 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } diff --git a/examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars b/examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars deleted file mode 100644 index 824d4a691b61..000000000000 --- a/examples/azure-2-vms-loadbalancer-lbrules/terraform.tfvars +++ /dev/null @@ -1,6 +0,0 @@ -# resource_group = "myresourcegroup" -# rg_prefix = "rg" -# hostname = "myvm" -# dns_name = "mydnsname" -# location = "southcentralus" -# admin_password = "T3rr@f0rmP@ssword" diff --git a/examples/azure-cdn-with-storage-account/provider.tf.example b/examples/azure-cdn-with-storage-account/provider.tf.example deleted file mode 100644 index 79291f7ca895..000000000000 --- a/examples/azure-cdn-with-storage-account/provider.tf.example +++ /dev/null @@ -1,7 +0,0 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } - diff --git a/examples/azure-cdn-with-storage-account/terraform.tfvars b/examples/azure-cdn-with-storage-account/terraform.tfvars deleted file mode 100644 index bee98e4e11bc..000000000000 --- a/examples/azure-cdn-with-storage-account/terraform.tfvars +++ /dev/null @@ -1,8 +0,0 @@ -# Replace with relevant values - -# resource_group = "myresourcegroup" -# rg_prefix = "rg" -# hostname = "myvm" -# dns_name = "mydnsname" -# location = "southcentralus" -# admin_password = "T3rr@f0rmP@ssword" diff --git a/examples/azure-vm-from-user-image/provider.tf b/examples/azure-vm-from-user-image/provider.tf deleted file mode 100644 index bdf0583f3259..000000000000 --- a/examples/azure-vm-from-user-image/provider.tf +++ /dev/null @@ -1,6 +0,0 @@ -# provider "azurerm" { -# subscription_id = "REPLACE-WITH-YOUR-SUBSCRIPTION-ID" -# client_id = "REPLACE-WITH-YOUR-CLIENT-ID" -# client_secret = "REPLACE-WITH-YOUR-CLIENT-SECRET" -# tenant_id = "REPLACE-WITH-YOUR-TENANT-ID" -# } diff --git a/examples/azure-vm-from-user-image/terraform.tfvars b/examples/azure-vm-from-user-image/terraform.tfvars deleted file mode 100644 index 15da2a9c6ca7..000000000000 --- a/examples/azure-vm-from-user-image/terraform.tfvars +++ /dev/null @@ -1,13 +0,0 @@ -# resource_group = "myresourcegroup" -# image_uri = "https://DISK.blob.core.windows.net/vhds/ORIGINAL-VM.vhd" -# primary_blob_endpoint = "https://DISK.blob.core.windows.net/" -# location = "southcentralus" -# os_type = "linux" -# address_space = "10.0.0.0/16" -# subnet_prefix = "10.0.0.0/24" -# storage_account_name = "STOR-ACCT-NAME" -# storage_account_type = "Standard_LRS" -# vm_size = "Standard_DS1_v2" -# hostname = "HOSTNAME" -# admin_username = "vmadmin" -# admin_password = "YOURPASSWORDHERE" From db258ed34d8519787550274745521243e0253dd5 Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 19:10:44 -0500 Subject: [PATCH 67/68] reverting to Hashicorp's .travis.yml --- .travis.yml | 76 ++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/.travis.yml b/.travis.yml index 02a1900e41ea..411407aa9ef1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,44 +1,42 @@ -sudo: required +dist: trusty +sudo: false +language: go +go: +- 1.8.1 -services: - - docker - -language: generic - -# on branches: ignore multiple commits that will queue build jobs, just run latest commit -git: - depth: 1 - -# establish environment variables +# add TF_CONSUL_TEST=1 to run consul tests +# they were causing timouts in travis env: - - TEST_DIR=examples/azure-sql-database - # - TEST_DIR=examples/azure-servicebus-create-topic-and-subscription - # - TEST_DIR=examples/azure-search-create - # - TEST_DIR=examples/azure-vnet-to-vnet-peering - # - TEST_DIR=examples/azure-traffic-manager-vm - # - TEST_DIR=examples/azure-vm-from-user-image - # - TEST_DIR=examples/azure-cdn-with-storage-account - # - TEST_DIR=examples/azure-vm-simple-linux-managed-disk - # - TEST_DIR=examples/azure-vnet-two-subnets + - CONSUL_VERSION=0.7.5 GOMAXPROCS=4 +# Fetch consul for the backend and provider tests +before_install: + - curl -sLo consul.zip https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip + - unzip consul.zip + - mkdir ~/bin + - mv consul ~/bin + - export PATH="~/bin:$PATH" + +install: +# This script is used by the Travis build to install a cookie for +# go.googlesource.com so rate limits are higher when using `go get` to fetch +# packages that live there. +# See: https://github.com/golang/go/issues/12933 +- bash scripts/gogetcookie.sh +- go get github.com/kardianos/govendor +script: +- make vet vendor-status test +- GOOS=windows go build branches: only: - - master - - /^(?i:topic)-.*$/ - -# install terraform -before_deploy: - - export KEY=$(cat /dev/urandom | tr -cd 'a-z' | head -c 12) - - export PASSWORD=$KEY$(cat /dev/urandom | tr -cd 'A-Z' | head -c 2)$(cat /dev/urandom | tr -cd '0-9' | head -c 2) - - export EXISTING_IMAGE_URI=https://permanentstor.blob.core.windows.net/permanent-vhds/permanent-osdisk1.vhd - - export EXISTING_STORAGE_ACCOUNT_NAME=permanentstor - - export EXISTING_RESOURCE_GROUP=permanent - -# terraform deploy + script -deploy: - - provider: script - skip_cleanup: true - script: cd $TRAVIS_BUILD_DIR/$TEST_DIR && ./deploy.ci.sh - on: - repo: harijayms/terraform - branch: topic-201-sql-database \ No newline at end of file + - master +notifications: + irc: + channels: + - irc.freenode.org#terraform-tool + skip_join: true + use_notice: true +matrix: + fast_finish: true + allow_failures: + - go: tip \ No newline at end of file From 2394ff7f592983702a78f7b68b9a5f6b8e7deccd Mon Sep 17 00:00:00 2001 From: anniehedgpeth Date: Thu, 18 May 2017 19:13:22 -0500 Subject: [PATCH 68/68] added graph to README --- examples/azure-sql-database/README.md | 4 +++- examples/azure-sql-database/graph.png | Bin 0 -> 102287 bytes 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 examples/azure-sql-database/graph.png diff --git a/examples/azure-sql-database/README.md b/examples/azure-sql-database/README.md index a390fd5c5937..dd0890061dde 100644 --- a/examples/azure-sql-database/README.md +++ b/examples/azure-sql-database/README.md @@ -17,4 +17,6 @@ Azure requires that an application is added to Azure Active Directory to generat If a `terraform.tfvars` file is present in the current directory, Terraform automatically loads it to populate variables. We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use `-var-file` to load it. ## variables.tf -The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. \ No newline at end of file +The `variables.tf` file contains all of the input parameters that the user can specify when deploying this Terraform template. + +![graph](/examples/azure-sql-database/graph.png) \ No newline at end of file diff --git a/examples/azure-sql-database/graph.png b/examples/azure-sql-database/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..bf5ee196b0571392c2e48d523f73d45ec840dd7e GIT binary patch literal 102287 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%0Ai7pMd`Vu^ zU)OeB6(*9d!Lj{Tr*cw0G5Dw3R0>6TzC5+|?d4N*Tdv*z7qYHEi3_O9I=?Zl8L0SMw+F;KQ-q znuS(iuASpHwb6&Zf7U^vX}ZuOfaP=e%Y2)s^~dfAJI-x0v6^n3u1dX?GmZHdJK%hFuU~Mr0J2 z=^VWGZvCeBS(_}Og5J6FT<`op;4^Cf`E1FCP5I8Br?x{OL=x+W zOC5jy{JXdD^&t%d@oVh3P24X>G=eb$j?l=FohyYNeG%QH;;RfHvt*eVBI?;b)yzza zeFFS#=-`8vt?^EWr$Nw28pD~#t0KTRMsG{uAvs!U*O)|~lpx5s_4(Dvqz;$Rc5w?M z)#9KnhP=pl5U}f>U)!LO-}ebmS7?TLjloUM-aOq-H}O(<-GcPNu#+S`765baziE-Q#!Pr^#>D_J68+DqSq^I+X;hAh|6%deN`{fJPZSzU(FG|%B{Z){`|RtYQgb8I1& z=gWejbWL@GA2&R%#^i#ooN~k|PYQoDJ)}H=_Pimc|9VZcPv3nSce%VT`RE1|aD`P4 zHj_0IEtmr4eGbJs8t;Tn0`YDlIytf8vIhHCwVE71y40V*g>QLBAoowT^K1epJk)+- z+Q~msnF(pUd!<%H)McorEMzJH(p!%&bY3reoy+=!s&@+G2iYAa-%gzRp1MhKthjv- zlz??s0A;8PkO#G>Y15ESn0a9E1R-+4cau%Wx;a}{^?^Zqq=YU8gtWZ|m*r}bKG|xg zL@YJO7A&{Z3eu5N5ubLfI8{y;w)tOPEjV$$rkcB`c{P5jIR8yj@hjHBP!j~6p_w|X zn!@0_(l}Smo}BMNGurobXzYN82(3P$KD-~(;uwoH$IMb<+0P`oQKO3WP;%>fg!e!) zgE$j?yJ3gy*nNf38bSO7s&gK?p+=NI3{a^5g6`%)uJgru8R)_-t+C#AwJb{hb~lG;Kj2 zghS-0=7o6YK)hv8S$EXtDC$P|;85SPJ)RT~f=b)r5mw#V$$h%KNN$sxOUMD**PTCn zxkJH1E0WtIx~D)S$F^j5Zu{f@=#0#bW1YTh-at7?h2^!HR3=(}5OZJI+>w}xgLg2= zP)$rczw(y3CN5)K_Y;E)I+Kxx?j#0dhC1;a!CGupw$+VpHXgS=I6az$Q4t=w9O3IZ zj03|+1@YIk@&Z6`@XfMX))JllJ@m2 z>+-E**vu9QrPV9UKaz|Is>JvcGn!X%BSN~x;EvK(g$zrOW&hZzMau7TCfX8xZS`lF z&dajW?boT1C{I;R7l}l!^IxEx~!omiPshoKec3G1UIG~P^ zW%eR0Q^#YC%)rPh%}Z-qG(ju^OHB-}M$Hhh!MwQwPcCGX>E>+tmD2XgLim!N+c#QF z#vf7rVY7$bph{b~bbzYUj}&4Q57QSN3~p5SgLMQ;C0YhrbxnffE% zXr^ZfWlRq7+v!tT4CPyF(m^i&cQLm=hIpNNV!3mpy1IOz&5u1eWvcrLWj1X{C3pYY z3B`q!)+!azyXa9*$#OHYMXfIG)+t|jCrOZYma7Df?p2NQE<1RTJ1dlAzr$q+RtSx~ zNr~mO`uW~pC-})HjF$tbJhLUO2d!pQj92c*{uTu6VXVUOr?c};5+Qoq>y5NrN8R}1 z18Zd?p`YOWxulC!gM}7feB2f#71z@8^7&2&mZDty3JGv(|I=8dMT54?;(YiaDkQ2p zYB=g4E<%M2_l<@44=VFT8$pa-!mw^d5xq=qv=9`Ij-S7K z2=)+AIjvRd%86o)BCV=FAB%JMXUUnr<@M1F>_^I%X$2EpItD$WfAge{QZAXlGxmE7 z9+5!LDAG)=!z)$IHoiE`*k$KYy*x;Ka1$%Ldr$hzVg{D`B>M&S3R{*IFGY^sH<=Cv zn>R|8&%P?>%2w(KkBJhUZ&3LsPUj5Q-et7SKLfagO7<_aN)0ADWQjA!@(-c1w%^_G z&`1Yf#@;DAkVpKWg;xFEJ6V`#eJzm^wI_Xvaov!0o6pLw}EO#av9&k;fZvty7KE+ z+#eO6(6#S@R1Bx1^-P7-YuD(+u0RANzU0BX%3js>h+`H7%O~S?)y*TDCWO&B6Ox7kEkGBDD4B$s18T(J7SvUIIzAM+!M~@aGa)%0^?%T@kt%a#2dUiA>2Z?|3$n zs8kA3%vMY8N6W38$E6fA&7{n_FPFC{-e<_dO?v&yzA7U7`?rV0EV#EKZq*C5tQ2Zv zTGdypwfhimPHGH(cg(lme94VS=dOLCttFJhcz4>*sWhld1LS9%K1>)p z7>PLaa?Q9NbBtd|Vk-8A*_K$F*SvMO2oU29(z?y<3N77p5l(k))s>D{D38g9qteGT&8#o=nM943I_@q*cOGn| z(_YMg)*bWJD2h}p?IH%ze4buyq273vlG)m?XWc%e^@d!BX2d1me5`&`Ym1L<2`4XO zCApL*j?o^ilWpE)oL;}d7av4z(p-6v_qj38R_8df3D(X0K(V*cdErF!e3?17H{5yQ z=63DFrD+?-$iTuyeei>6<&-7FhSOZ{xw8e9=*A25Q{qg+=LQ$Ov;3?pE9o%JR+kdTpqNn3ED3;$3%PIEaKR5e+m?U$95o_NoB zMnt^Auj2CfB3;e9B}-`dOnt+KaKu3l%Cvx}-c9#;SQQPMhte^z;O`K={`>~dv*kha z`UeP+=jz^)vKid4**!SlJM_wL%To>|iKITXQtIli=UlkySf$GSro}L(tW0KYdG_cw zZDXf=RU%8BF&WioJ*ALNb`7?%`k#u2)b)AE1Z}lyL<~iKD(GPo*4^Aw4N&8P3-aZ!f#W*)pf0nPI2(l~sCq`GM zOwv0+hHK4b(Plm3VU_~fY)9koym^I`x$tnZ2Tq&Vw5R-J@(I9Zpzah)AEtg1ML}Rh z-yywFZPD`x$nI}!{ox~%$8xb_^CW(z@5`K9Ck|h_lo#N8CAaG?OyxGN=Lo)dl2lVf zgnyl7SaLKrWD)go;~P&js=GJIeCoV*Y`_?(&GgPvBG#qT=oN( zw$7&{OBo-#NdU-_0ismp;#lyt+<O8MGq{ysAB%xTVQw6I}xzVppt%6&DmGeWT7b+c$+sU0Y3J z^CZv*)k%a7{(HxsVJT<{myxX)I;K2Ypy zj1HI;kHcKy*qePgyPeL{{yCVU?amvoBB#v-Grk>>qM=6d`+VudpUoMLzIyp)_cyCd zWuQM(AL%3}GVuN?k+i<`pGIq*APBqi&lQpgRV+*8^!=y`rI&EAGsmUyShMcP+-!VaA=w!ruY-F+umZlh$U{+B=(e4g%??;vFYVG7I`~8)cXb^X< z{w(6$xqS#@{J*x&JFJOqUE?8!ZXkdl7)nBm2q;K|&^$mw(?}8Npdg4rdJ!RnCZV^4 zfJTZ`5d}nw1r$VTK-h$$0=h+tG>x!n8HNT1stZ;f+t@W|BJvD;ZsuB4DW*TSxQVI+gOTKc!m*{}jgY31P~f zre%DEm65Q?IY-WEus)oBH|BIN;>u{a0LeL7-h3f^JA719>TlUA&xp+Hzo+;D6sTgs zTx6l%zJgz^$Bdlge?!oC9M4GvE+2$x@NmD%-Lr=U;vKViX_@ z-ZcazZBQtf`Kv*)+lMt!GrJMQ{i2&T>x4(%nSUS)gN$UN=oyjL<@?&BA_)dpA#}M_ zD3U0$n-$@{eow4arfHbLIM%N$#1Tl!#I6RAX5ddh_ZoHO0~wV}>UrI=sw(z6mjkH= zf{3BBpZ6X}O*Zu|$@8!ifq{{3JZJMotMxmzgm_3-I*YPWeI2V#?pd&svOs=uVKl$9 z)t{(V>Vr?q4!5o(i1`t=ngZ+u5FSF|mVl*zfoF+amfo-(@4dRwYNG!&@8ssKUd!lV zv?J3cE>_;i&Gr1cpm1r~xWPi0tV(I_fw&`u)6Zmu-riH`n_rM^(~1&L3+%|VH+uIG zaDzs2y?e|kU3YCwV^@6XIS&Y+YgPcBNgig#sRAK1(ww$9T+I;G(#+Y>`wr28HzDUbC zo=}rmP7tKxMD$;2Vv2VG1jsH1$jQC?ktEuhiU3xcJ65jYQwba_EIJ7h7&aMoLxZ~} za5MK5k{J#urTq*9{5kU_6f5W?4Ub~Mk({*5ee8sw<;-g2Rbwq8#jd!Q^KV%3ayD|q#mWKap^rvM09eN{kKaIM+!hus5# zlN)`!8_C)p2VIY_QCbw9$e%x`1o04mL1mLw;Q={`ONG(-YG@CR35^W0=g;U359SS z(Ik{Gxsbw0KY&U{Gv3?Jjni#}sELdVpW{MewkHL2zqy5fUWX4D-;uJf=*yuVku@OO zN*>4NMFZ4~Rw>s$vHxn=gg0u01aPjba@C6+&9=9GJ@@@AHu-|)ykOOU17$8tN3C1u zrxOYDXo)uMcGqK20gfewujP5fRigJ{BX)G(y5-=bGl{F7`1@?|T`rJqy)GA&Je%O% z2iRp@Q~LQU9n)XIjDbs#obokvZBIyy_G$AJ~Xh zJTz93qOo^d@xrph``yEY0acghYNUDHNnTv{>s~ag4b}8bYl0w0y>Y#EA$v7TNx?}T zz>d^{DMy0|EEW*ZaL>};RHH%eEPS!&n$ZBy1FpSS+ffx#TLm6?ZY^26DUUy%0VXkL zHBd4ZuHFc+3R?ZyYpV9#2ST>dgdQMZ(7Z&RC9ikhKQ!S(DgI|o&NKu1kmFjj^_g)k zZbc~U(y?kr1us`7ubk?oWBWBqB*80K|M>eqr2+X}pZLx@mym(_D#zt2UN9w+U{Xwt zpD`)Dp#IktaQcjiVg~>`G?}&Ljm{T0@EVeKH{QdCK;t0m_>{qJcz~}bG}=YYv@NJ< zcncQ(t*!@8`waLfXd*=oMgOHud885!lLXa(HO2k~kUOsm@HO2@&!TOi5O$$lpZRnp z-+rGlj|u4O-csqAgZ%vYzV+q?G)tV`BWQKz05A8d8OXCgUMGCLBz1Xxg-2^p){ zSM7f?qJpI~yY>02Cp{o`)FT%T<_H07Lc;o&m=NTVL#KVl&e{Y&KE%@Wx!uT0~+Hg#Nxb1Kcv68W)ncSUrAw^#m6mw-08Hc z@YVjZU)-nqOgrKQfKLoe$yvy#&$w;KyuHqlYKL-zT;r_Wp{_#W}V}D%K~`XDgG)%ik*Wyr(DpAa*~aw=1zW{skj)2 zb4IhT(Q(B7ok4>?m|RgI^@+>8c^>kNi>*i?Ve`nZKLq3Tk~;WAv5_m+kUb}uH-J8@ zOAQN4n}ueFmGsp`beE^T%~KgN#C&x}$x3>r9PNvX;Nvag8YgK`hvdD+PTl`o7mV+B zRO)(tti8nt^bufu!}!aUXhGWuzuUPniqqA5%Igoy9QN+k4JDv1Et)V*88JXW%o`@i z8RXy0iCB5f?F`4^iC8R+6D2%*n#G+>flgDFLGVeQiNgQLh2x|F?rP+KLvCxXtt6RJ z?JY#(6Ry&AJP(0#NO}v%A{kz5!97wp#;(!$&Bk}C8;8%tGg1M8Dpw}R2~No#e;Y$K z9i1`97;ff9+x?8{l0j1aa&7H+f&a^B+uB6u;bP8&2OMw@>E|=>oBHiKU{Qep^K^~Y zVOG`0Z}(K+cHSCl#jA)hHMcB&n7o*xYm)7%d`wm#tu&q~O6|JMW^{V*$vFr5a{aus za*Qr3sCL3pj7H#BNvvc0Q3PDK+-)!%1(5U8iB_3FE;j+7OInOKr>^o&XX)p;_`XqT zz`sqc-uWlv8O7FdPBtsw3K`vPfbh+MFzp`3Jnjl-ixDnjh2izVy=(Q$1{4KkfmhLB zDh)DvdE@?zr3_HJ3sA&9Lne(UCq zADChbjaO~O-8BL_cCvk{HRYIIT6mt}`J*C3YcRsvCamYUCz5bQ>rqpd@Cgl^=&UGC z%qU01S+cAS;@ELFGF5nR&zF_Z7A|D4b)yD~68|xo0&dNZ?!WsKIz)f>$?R2r^ts86 zjAeEBF5PEQzh}$&Ou+i}z5ADbnoOF@U<1M|A%L7l!3l7ce(f`F35%vz+ei(QI(38pq{RfS@W}?iCcJinhP>0%?ioc zDt~oisEQAUdn^c7{-&V4RV$h~y(^ttlwSQ_5?kp2Z90?mGVw&`_o7PWYKxMHj$=ja zsk&hlE4qxP#;^43J7!4O^?oRfCk3(Ki<6?-rpPC{}dKz3xqi!PK0-GTnrFpqp`n-+W!{)k`3&E?_+3!nb!Yv?$?EG7~m!n l0^f;Mzv-g?dtI~aN=)gCXs)A&)nOpuFgLcqJu-5;`ETV6hcW;F literal 0 HcmV?d00001