Terranova is a Go package that allow you to use the Terraform Go Packages instead of using the binary. It works with the Terraform version 0.12.9
.
For more information about Terranova and how to use use it, refer to the blog post Terranova: Using Terraform from Go
Terranova works better as a Go module, if you don't have a go.mod
file in your project, create it with go mod init [package full name]
. Import Terranova in the Go code:
import (
"github.com/johandry/terranova"
)
As soon as you execute a Go command such as go build
or go test
it will be included in your go.mod
file and downloaded.
If you are not using modules yet, using vendors or having the packages in $GOPATH
, please, git clone
the repository and create the vendor directory:
mkdir -p $GOPATH/src/github.com/johandry/
cd $GOPATH/src/github.com/johandry/
git clone --depth=1 https://github.com/johandry/terranova.git
GO111MODULE=on go mod vendor
After having the package, the high level use of Terranova is like follows:
- Create a Platform instance with the Terraform code to apply
- Get (
go get
), import and add (AddProvider()
) the Terraform Provider(s) used in the code - Get (
go get
), import and add (AddProvisioner()
) the the Terraform Provisioner (if any) used in the Terraform code - Add (
Var()
) the variables used in the Terraform code - Load the previous state of the infrastructure using
ReadStateFromFile()
orReadState()
methods. - Apply the changes using the method
Apply()
- Save the final state of the infrastructure using
WriteStateToFile()
orWriteState()
methods.
The following example shows how to create, scale or terminate AWS EC2 instances:
package main
import (
"log"
"os"
"github.com/johandry/terranova"
"github.com/terraform-providers/terraform-provider-aws/aws"
)
var code string
const stateFilename = "simple.tfstate"
func main() {
count := 1
keyName := "demo"
platform, err := terranova.NewPlatform(code).
AddProvider("aws", aws.Provider()).
Var("c", count).
Var("key_name", keyName).
ReadStateFromFile(stateFilename)
if err != nil {
if os.IsNotExist(err) {
log.Printf("[DEBUG] state file %s does not exists", stateFilename)
} else {
log.Fatalf("Fail to load the initial state of the platform from file %s. %s", stateFilename, err)
}
}
terminate := (count == 0)
if err := platform.Apply(terminate); err != nil {
log.Fatalf("Fail to apply the changes to the platform. %s", err)
}
if _, err := platform.WriteStateToFile(stateFilename); err != nil {
log.Fatalf("Fail to save the final state of the platform to file %s. %s", stateFilename, err)
}
}
func init() {
code = `
variable "c" { default = 2 }
variable "key_name" {}
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "server" {
instance_type = "t2.micro"
ami = "ami-6e1a0117"
count = "${var.c}"
key_name = "${var.key_name}"
}
`
}
Read the same example at terranova-examples/aws/simple/main.go and the blog post Terranova: Using Terraform from Go for a detail explanation of the code.
The git repository terranova-examples contain more examples of how to use Terranova with different clouds or providers.
All this research was done reading the Terraform documentation and source code.
Please, feel free to comment, open Issues and Pull Requests, help us to improve Terranova.