Update: The Openstack provider has been merged into terraform. It comes with the terraform default download as of 0.4.0.

Get it HERE: https://terraform.io/downloads.html

Then proceed directly to the second part of this series to get up and running with Terraform on Openstack quickly!

Or.. read more below for the original post.

TL;DR: Two post series for automating the configuration and VM deployment of a brand new tenant / project in OpenStack with Terraform, using the new Terraform OpenStack Provider.

With the OpenStack provider for Terraform nearly accepted into the Terraform release, I thought it was time to demonstrate the power of this currently beta provider.

In this blog post we will:

  • Compile the openstack terraform provider from the github pull request.

In the followup post, we will:

  • Write a terraform ‘.TF’ file to describe our desired deployment state including;
    • Neutron networks/subnets
    • Neutron gateways
    • Keypairs and Security Groups
    • Virtual machines and Volumes
    • Virtual IP’s
    • Load balancers (LBaaS).
  • Have terraform deploy, modify and rip down our infrastructure.

1. Compile the Terraform Openstack Provider

Terraform is written in Golang, all terraform plugins are standalone golang binaries that terraform will check for in it’s local dir and gopath.

As Openstack support isn’t yet shipped with terraform, lets compile the provider based on the open github pull request.


Clone the Terraform Github repo:

TrX-MBP-13:demo matt$ git clone https://github.com/hashicorp/terraform.git
Cloning into 'terraform'...
remote: Counting objects: 24528, done.
remote: Compressing objects: 100% (85/85), done.
remote: Total 24528 (delta 55), reused 0 (delta 0), pack-reused 24443
Receiving objects: 100% (24528/24528), 19.53 MiB | 1.83 MiB/s, done.
Resolving deltas: 100% (16660/16660), done.
Checking connectivity... done.
TrX-MBP-13:demo matt$ cat terraform/.git/config
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
[remote "origin"]
	url = https://github.com/hashicorp/terraform.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

Modify the git config so we can see PR’s locally: 

TrX-MBP-13:demo matt$ vi terraform/.git/config
TrX-MBP-13:demo matt$ cat terraform/.git/config
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
[remote "origin"]
	url = https://github.com/hashicorp/terraform.git
	fetch = +refs/heads/*:refs/remotes/origin/*
	fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
TrX-MBP-13:demo matt$ cd terraform/
TrX-MBP-13:terraform matt$ git fetch
remote: Counting objects: 5259, done.
remote: Compressing objects: 100% (857/857), done.
remote: Total 5259 (delta 2381), reused 1759 (delta 1759), pack-reused 2643
Receiving objects: 100% (5259/5259), 1.14 MiB | 1.56 MiB/s, done.
Resolving deltas: 100% (3087/3087), done.
From https://github.com/hashicorp/terraform
 * [new ref]         refs/pull/980/head -> origin/pr/980
 * [new ref]         refs/pull/983/head -> origin/pr/983
 * [new ref]         refs/pull/984/head -> origin/pr/984
 [ ... Lines Removed ... ]
 * [new ref]         refs/pull/986/head -> origin/pr/986
 * [new ref]         refs/pull/987/head -> origin/pr/987
 * [new ref]         refs/pull/988/head -> origin/pr/988
 * [new ref]         refs/pull/989/head -> origin/pr/989
 * [new ref]         refs/pull/990/head -> origin/pr/990
 * [new ref]         refs/pull/991/head -> origin/pr/991
 * [new ref]         refs/pull/993/head -> origin/pr/993
 * [new ref]         refs/pull/997/head -> origin/pr/997
 * [new ref]         refs/pull/998/head -> origin/pr/998
 * [new ref]         refs/pull/999/head -> origin/pr/999

 We can now create local branches which track Pull Requests
thanks to https://gist.github.com/piscisaureus/3342247 for this tip!

TrX-MBP-13:terraform matt$ git checkout pr/924
Branch pr/924 set up to track remote branch pr/924 from origin.
Switched to a new branch 'pr/924'
TrX-MBP-13:terraform matt$ git status
On branch pr/924
Your branch is up-to-date with 'origin/pr/924'.
nothing to commit, working directory clean

 Check Dependancies! 

I am assuming you have a working golang environment installed on your system this point; The topic has been covered many times in far nicer ways than I could cover here. For example: http://skife.org/golang/2013/03/24/go_dev_env.html

I’m also assuming you have downloaded the terraform binary for your system from HERE and it’s in your $PATH  so that you can run terraform as follows.

TrX-MBP-13:terraform matt$ terraform
usage: terraform [--version] [--help] <command> [<args>]

Available commands are:
    apply      Builds or changes infrastructure
    destroy    Destroy Terraform-managed infrastructure
    get        Download and install modules for the configuration
    graph      Create a visual graph of Terraform resources
    init       Initializes Terraform configuration from a module
    output     Read an output from a state file
    plan       Generate and show an execution plan
    pull       Refreshes the local state copy from the remote server
    push       Uploads the the local state to the remote server
    refresh    Update local state file against real resources
    remote     Configures remote state management
    show       Inspect Terraform state or plan
    version    Prints the Terraform version

Compile Terraform Openstack plugin!

We move the terraform git repo we cloned into our $GOPATH/src directory, check we have the required dependancies to compile a terraform plugin, then compile the plugin.

Finally we place the resulting plugin into our $PATH along with the binary installation of Terraform we already have installed.

[email protected] demo $ mv terraform $GOPATH/src/github.com/hashicorp/.
[email protected] demo $ cd $GOPATH/src/github.com/hashicorp/terraform
[email protected] terraform (pr/924) $ make updatedeps
go get -u github.com/mitchellh/gox
go get -u golang.org/x/tools/cmd/stringer
go list ./... \
		| xargs go list -f '{{join .Deps "\n"}}' \
		| grep -v github.com/hashicorp/terraform \
		| sort -u \
		| xargs go get -f -u -v
code.google.com/p/go-uuid (download)
code.google.com/p/go.crypto (download)
code.google.com/p/goauth2 (download)
code.google.com/p/google-api-go-client (download)
github.com/MSOpenTech/azure-sdk-for-go (download)
github.com/armon/circbuf (download)
github.com/cyberdelia/heroku-go (download)
github.com/hashicorp/atlas-go (download)
github.com/hashicorp/consul (download)
[... Output Shortened ...]
github.com/mitchellh/prefixedio (download)
github.com/pearkes/cloudflare (download)
[email protected] terraform (pr/924) $ cd builtin/bins/provider-openstack/
[email protected] provider-openstack (pr/924) $ go build
[email protected] provider-openstack (pr/924) $ ls
main.go            provider-openstack
[email protected] provider-openstack (pr/924) $ mv provider-openstack terraform-provider-openstack

Notice, once built, we rename the binary to ‘terraform-provider-openstack’. This is due to Terraform plugin naming convention. Allowing terraform to discover plugins in it’s directory/path.

You will see this if you look at your Terraform install location with the existing bundled providers:

[email protected] provider-openstack (pr/924) $ ls -la /Users/matt/bin/terraform 
[email protected] 1 matt  staff  12135908 19 Feb 11:29 /Users/matt/bin/terraform

[email protected] provider-openstack (pr/924) $ ls -la /Users/matt/bin | grep terraform-provider
[email protected]   1 matt  staff  11402340 19 Feb 11:29 terraform-provider-atlas
[email protected]   1 matt  staff  13235540 19 Feb 11:29 terraform-provider-aws
[email protected]   1 matt  staff  11319092 19 Feb 11:29 terraform-provider-cloudflare
[email protected]   1 matt  staff  21043012 19 Feb 11:29 terraform-provider-cloudstack
[email protected]   1 matt  staff  11587332 19 Feb 11:29 terraform-provider-consul
[email protected]   1 matt  staff  11638484 19 Feb 11:29 terraform-provider-digitalocean
[email protected]   1 matt  staff  11327572 19 Feb 11:29 terraform-provider-dnsimple
[email protected]   1 matt  staff  13705116 19 Feb 11:29 terraform-provider-google
[email protected]   1 matt  staff  11881860 19 Feb 11:29 terraform-provider-heroku
[email protected]   1 matt  staff  11293396 19 Feb 11:29 terraform-provider-mailgun
[email protected]   1 matt  staff  11238020 19 Feb 11:29 terraform-provider-null

Add the new provider to your $PATH location:

[email protected] provider-openstack (pr/924) $ cp terraform-provider-openstack ~/bin/.

Finally, check the binary is correct and Terraform accepts the provider.

[email protected] demo $ terraform-provider-openstack
This binary is a Terraform plugin. These are not meant to be
executed directly. Please execute `terraform`, which will load
any plugins automatically.

Terraform would error on this simple manifest if it could not find a provider named ‘openstack’:

[email protected] demo $ wget https://gist.githubusercontent.com/matjohn2/250cbed0feaf74d44463/raw/549708e628ed1efdbf95f7e0dfd800c664de872c/gistfile1.txt -O testopenstack.tf
--2015-03-27 10:40:45--  https://gist.githubusercontent.com/matjohn2/250cbed0feaf74d44463/raw/549708e628ed1efdbf95f7e0dfd800c664de872c/gistfile1.txt
Resolving gist.githubusercontent.com...
Connecting to gist.githubusercontent.com||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 305 [text/plain]
Saving to: 'testopenstack.tf'

testopenstack.tf              100%[=================================================>]     305  --.-KB/s   in 0s     

2015-03-27 10:40:45 (9.09 MB/s) - 'testopenstack.tf' saved [305/305]

[email protected] demo $ ls
[email protected] demo $ cat testopenstack.tf 
# Testing the OpenStack provider from merge of 
# https://github.com/hashicorp/terraform/pull/924

provider "openstack" {
     user_name = "Openstack User"
     tenant_name = "OPENSTACK TENANT NAME"
     auth_url = "https://openstack-keystone-auth-uri:5000/v2.0"
     password = "YourOpenstackPassword"
}[email protected] demo $ terraform apply

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

That’s It! Terraform is ready to rock your Openstack deployment!

In the next blog post, we’ll take it for a spin and automate some infrastructure.




Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.