As regular readers will know I really like the tools provided by Hashicorpβ†— and today I found an excuse to use one. I needed to bring up a Virtual Machine in Microsoft Azureβ†— . I hadn’t logged into Azure for quite a while so imagine my shock when I opened the dashboard, it’s not that great and the beta of the new one isn’t that brilliant either. It was so bad I tweeted about it ….

I had recently looked at Terraform↗ for another project and I worked through the excellent getting started guide which covers how to launch AWS Instances↗ .

I decided that it maybe more straight forward to launch my test Virtual Machines using Terraform rather than going through the dashboard, apart from the storage container which I created ahead of launching my configuration.

Terraform is straight forward to install if you have Homebrew↗ installed, none Mac users can follow the install guide↗ .

Terraform & Azure 1/6
 brew install terraform
 brew cask install graphviz

There is a Cask version of terraform, this does not ship with the Azure provider so use the main brew package instead. Graphviz↗ is installed so that the graph functionality can be used.

I downloaded a copy of my Publish Settings from https://manage.windowsazure.com/publishsettings↗ and renamed the file to settings.publishsettings. I then created terraform configuration (which can be found in the following repo https://github.com/russmckendrick/terraform-examples/tree/master/azure↗ ).

First off I checked everything was OK with the configuration using terraform plan;

Terraform & Azure 2/6
 ⚑ terraform plan
 var.azure_settings_file
 Default: settings.publishsettings
 Enter a value:

Refreshing Terraform state prior to plan…

The Terraform execution plan has been generated and is shown below.
 Resources are shown in alphabetical order for quick scanning. Green resources
 will be created (or destroyed and then created if an existing resource
 exists), yellow resources are being changed in-place, and red resources
 will be destroyed.

Note: You didn’t specify an β€œ-out” parameter to save this plan, so when
 β€œapply” is called, Terraform can’t guarantee this is what will execute.

+ azure_hosted_service.terraform-service
 default_certificate_thumbprint: β€œβ€ => β€œ<computed>”
 description: β€œβ€ => β€œHosted service created by Terraform.”
 ephemeral_contents: β€œβ€ => β€œ0”
 label: β€œβ€ => β€œruss-tf-hs-01”
 location: β€œβ€ => β€œWest Europe”
 name: β€œβ€ => β€œruss-terraform-service”
 status: β€œβ€ => β€œ<computed>”
 url: β€œβ€ => β€œ<computed>”

+ azure_instance.basic-server
 automatic_updates: β€œβ€ => β€œ0”
 description: β€œβ€ => β€œ<computed>”
 endpoint.#: β€œβ€ => β€œ1”
 endpoint.2462817782.name: β€œβ€ => β€œSSH”
 endpoint.2462817782.private_port: β€œβ€ => β€œ22”
 endpoint.2462817782.protocol: β€œβ€ => β€œtcp”
 endpoint.2462817782.public_port: β€œβ€ => β€œ22”
 hosted_service_name: β€œβ€ => β€œruss-terraform-service”
 cover:
    image: β€œβ€ => β€œOpenLogic 7.1”
 ip_address: β€œβ€ => β€œ<computed>”
 location: β€œβ€ => β€œWest Europe”
 name: β€œβ€ => β€œruss-terraform-test”
 password: β€œβ€ => β€œz69rVZfH”
 security_group: β€œβ€ => β€œ<computed>”
 size: β€œβ€ => β€œBasic_A1”
 storage_service_name: β€œβ€ => β€œrussstoreage”
 subnet: β€œβ€ => β€œ<computed>”
 username: β€œβ€ => β€œazureuser”
 vip_address: β€œβ€ => β€œ<computed>”

Plan: 2 to add, 0 to change, 0 to destroy.

As you can see everything is good to go, I also generated graphical overview using terraform graph which shows how it looks;

Terraform & Azure 3/6
terraform graph | dot -Tpng > graph.png

graph

As everything looked good it was time to apply the configuration and launch the Virtual Machine using terraform apply;

Terraform & Azure 4/6
 ⚑ terraform apply
 var.azure_settings_file
 Default: settings.publishsettings
 Enter a value:

azure_hosted_service.terraform-service: Creating…
 default_certificate_thumbprint: β€œβ€ => β€œ<computed>”
 description: β€œβ€ => β€œHosted service created by Terraform.”
 ephemeral_contents: β€œβ€ => β€œ0”
 label: β€œβ€ => β€œruss-tf-hs-01”
 location: β€œβ€ => β€œWest Europe”
 name: β€œβ€ => β€œruss-terraform-service”
 status: β€œβ€ => β€œ<computed>”
 url: β€œβ€ => β€œ<computed>”
 azure_hosted_service.terraform-service: Creation complete
 azure_instance.basic-server: Creating…
 automatic_updates: β€œβ€ => β€œ0”
 description: β€œβ€ => β€œ<computed>”
 endpoint.#: β€œβ€ => β€œ1”
 endpoint.2462817782.name: β€œβ€ => β€œSSH”
 endpoint.2462817782.private_port: β€œβ€ => β€œ22”
 endpoint.2462817782.protocol: β€œβ€ => β€œtcp”
 endpoint.2462817782.public_port: β€œβ€ => β€œ22”
 hosted_service_name: β€œβ€ => β€œruss-terraform-service”
 cover:
    image: β€œβ€ => β€œOpenLogic 7.1”
 ip_address: β€œβ€ => β€œ<computed>”
 location: β€œβ€ => β€œWest Europe”
 name: β€œβ€ => β€œruss-terraform-test”
 password: β€œβ€ => β€œz69rVZfH”
 security_group: β€œβ€ => β€œ<computed>”
 size: β€œβ€ => β€œBasic_A1”
 storage_service_name: β€œβ€ => β€œrussstoreage”
 subnet: β€œβ€ => β€œ<computed>”
 username: β€œβ€ => β€œazureuser”
 vip_address: β€œβ€ => β€œ<computed>”
 azure_instance.basic-server: Creation complete

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
 below. This state is required to modify and destroy your
 infrastructure, so keep it safe. To inspect the complete state
 use the `terraform show` command.

State path: terraform.tfstate

As you can see from the GUI below it launched the Cloud Service and Virtual Machine as defined.

microsoft-azure

I then used terraform show to query my instance to get the computed elements of the configuration;

Terraform & Azure 5/6
 ⚑ terraform show
 azure_hosted_service.terraform-service:
 id = russ-terraform-service
 description = Hosted service created by Terraform.
 ephemeral_contents = false
 label = russ-tf-hs-01
 location = West Europe
 name = russ-terraform-service
 azure_instance.basic-server:
 id = russ-terraform-test
 automatic_updates = false
 endpoint.# = 1
 endpoint.2462817782.name = SSH
 endpoint.2462817782.private_port = 22
 endpoint.2462817782.protocol = tcp
 endpoint.2462817782.public_port = 22
 hosted_service_name = russ-terraform-service
 image = OpenLogic 7.1
 ip_address = 100.112.32.27
 location = West Europe
 name = russ-terraform-test
 password = z69rVZfH
 reverse_dns = 
 security_group = 
 size = Basic_A1
 storage_service_name = russstoreage
 subnet = 
 username = azureuser
 vip_address = 104.40.211.127

I connected to the Virtual Machine, did what I had to do (thats a whole other blog post) and then finally tore down the Virtual Machine and Cloud Service using terraform destroy;

Terraform & Azure 6/6
 ⚑ terraform destroy
 Do you really want to destroy?
 Terraform will delete all your managed infrastructure.
 There is no undo. Only β€˜yes’ will be accepted to confirm.

Enter a value: yes

var.azure_settings_file
 Default: settings.publishsettings
 Enter a value:

azure_hosted_service.terraform-service: Refreshing state… (ID: russ-terraform-service)
 azure_instance.basic-server: Refreshing state… (ID: russ-terraform-test)
 azure_instance.basic-server: Destroying…
 azure_instance.basic-server: Destruction complete
 azure_hosted_service.terraform-service: Destroying…
 azure_hosted_service.terraform-service: Destruction complete

Apply complete! Resources: 0 added, 0 changed, 2 destroyed.

As a Mac / Linux user I found the whole experience to be a lot more what I am used to with other cloud services and a lot less β€œMicrosoft” than I feared.