A couple of posts ago I talked about how you could achieve full stack testing in Go using Docker containers. I have just finished the first version of terraform provider kong, a terraform provider for Kong that is built on top of gokong.
At the moment at Form3 we configure Kong using a custom Ruby script that runs on our Kong container and configures Kong upon boot up. Whilst this works there are a number of problems with this approach:
- It is hard to know what the end state of Kong is as you end up with a whole bunch of Ruby code that is hard to follow
- If you want to migrate the container over time it can be quite tricky as its hard to clean up APIs, consumers and other Kong resources as you delete them (the database Kong uses is long lasting)
By writing a custom terraform provider for Kong all of these problems go away. As terraform uses a declarative language you simply declare the state that you want the thing you are configuring to be in (in this case Kong) and terraform looks at the current state and automatically works out how to get there. This makes everything so much simpler. A good example is if you remove an API in our current world you have to remember to write a line of Ruby to delete the old API. When using terraform you simply remove the API from your configuration and terraform deletes it for you.
Building upon the way that I wrote gokong I wrote terraform provider kong in the same vein, ie full stack testing using real components and no mocks! This means that the acceptance tests in terraform provider kong spin up a real Kong container and apply terraform plans to it, check it is in the expected state and then destroy it again. Testing in this way gives you ultimate confidence that the code works!
To automate releases of new versions of terraform provider kong I have used the excellent goreleaser. Goreleaser automates building your code for multiple platforms, zipping/tar balling it up and uploading it to github. It is so easy to use, kudos to the authors. To setup you simply need to create a
|– binary: terraform-provider-kong|
My file specifies the binary and builds for mac (Darwin), Linux and Windows. The last part is to define a task to run
goreleaser as part of your build. Goreleaser will only run when the build is running as a tag build, therefore you can create a task and run it on every build and
goreleaser will only build a release for a tagged build, pretty smart. My build task to create a release looks like:
|go get github.com/goreleaser/goreleaser; \|
I run the release task as part of every travis build. You also need to create a github token which is used by
goreleaser to upload the release to your github account. To generate a github token go to https://github.com/settings/tokens/new. Then simply set it as a secure environment variable in your
goreleaser will pick it up for you.
Then when you want to create a release you can simply do:
|git tag -a v0.1.0 -m "My release"|
|git push origin v0.1.0|
Which will build a new
v0.1.0 release and automatically create the binaries and upload the release to Github. Pretty smart!
The last thing I wanted to go through was that I’m taking advantage of the build matrix feature of travis to run the tests against multiple versions of kong. The following section of my
|– KONG_VERSION=0.11 TF_ACC=1|
|– KONG_VERSION=0.11.1 TF_ACC=1|
|– KONG_VERSION=0.11.2 TF_ACC=1|
Travis will automatically run a build for each line under the matrix definition. Each with the values on the line. I pass the
KONG_VERSION parameter all of the way through to the code that pulls the Kong container for Docker so it will pull the version that is specified here. Hence I can easily update this build to run against many versions of Kong. As new versions are released I can simply add a line to the build matrix and it will automatically be tested on travis. This is a really powerful feature, being able to run your tests against multiple versions of a target piece of software is immense!