Skip to content

yzhivkov/gradle-plugin-terraform

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status master branch Latest version

What is this repository for

This plugin provides a workflow, when using Hashicorps terraform When we started using terraform, we just used the cli. However, soon we found that there is a workflow when we use terraform.

We are using it at Danske Spil and Lund&Bendsen, perhaps you can also benefit from it.

One usecase is, that we save the textual output from terraform plan in a file, and commit it to git before we do an apply (NB: git committing is not part of this plugin). This is done for auditing reasons. To do that, you have to do something like (the real flow is more complex, and the example below is pseudo-code)

// run plan and save the output in a file
terraform plan > plan-output
// inspect output visually
// commit the file
git commit -m "plan-output" plan-output
// Perform the change
terraform apply

Even if you remember to do the above steps every time,

  • Every now and then, we have to do a terraform get to get terraform plan to run.
  • After a fresh clone, you have to do a terraform init to get stuff initialized.
  • ...

So, to make sure we follow the workflow we have defined to be the best, and to make sure we remember to do the auditing we want, we codified it in this gradle plugin.

This plugin is written for terraform 0.10.4. It will most likely work with 0.10.x versions, but no guarantees are given.

How do you set up gradle with the plugin

Well. There are a number of tests in the repo you can read. Here is a brief overview, but remember that the source code is always the truth. These words are merely shadows on the wall.

This is how you include and apply the plugin in a non multi project

plugins {
  id "dk.danskespil.gradle.plugins.terraform" version "0.0.8"
}

This is how you can do it in a multi project, where your terraform files are in a terraform subproject build.gradle

plugins {
    id "dk.danskespil.gradle.plugins.terraform" version "0.0.8" apply false
}

configure(project(':terraform')) {
    apply plugin: 'dk.danskespil.gradle.plugins.terraform'
}

settings.gradle

include 'terraform'

This is how you can do it in a multi project, where your terraform files are in a multiple subprojects build.gradle

plugins {
    id "dk.danskespil.gradle.plugins.terraform" version "0.0.8" apply false
}

configure(project(':terraforming').subprojects) {
    apply plugin: 'dk.danskespil.gradle.plugins.terraform'
}

settings.gradle

include 'terraforming:env-test'
include 'terraforming:env-production'

How do you use it

this gives you a number of tasks, that represent a subset of terraforms cli commands, e.g.

  • plan (called tfPlan)
  • validate (called tfValidate)
  • apply (called tfApply)
  • init (called tfInit)
  • get (called tfGet)

and some tasks that are not terraform tasks

  • tfClean (tfClean task is executed with you execute clean task. It cleans the output files created by tfPlan. If you do not want it, disable it with tfClean.enabled=false)

you call them like this

./gradlew tfPlan
./gradlew tfApply
...

The tasks have inter-dependencies, e.g. tfApply uses the plan-output.bin from tfPlan to make its apply, so it will call tfPlan for you if its not present. Likewise tfPlan will call terraform plan for you and produce plan-output.bin and plan-output. If you call it again, it will only actually execute terraform plan if your *.tf or *.tpl files has changed since last time it was called. This can save considerable amounts of time if you are building even mid-sized infrastructures.

When applying the plugin itself, you get a configured version of the tasks that works in a reasonable way. e.g. tfPlan writes textual output to plan-output by default, and the binary plan to plan-output.bin by default.

However, since the plugin can not know where you have put your modules, you have to tell it. You do that as done in the example below, assuming your module files are at the gradle root dir in directory modules

// apply plugin
tfGet {
  inputs.files fileTree("$rootDir/modules")
  // the output is configured by default in the plugin, so you do not have to do that 
  // outputs.files fileTree("$projectDir/.terraform/modules")
}

You can create custom version of the tasks like so

task myPlan(type: dk.danskespil.gradle.plugins.terraform.tasks.Plan) {
    out=file('my-better-bin-name.bin'
    outAsText=file('my-better-text-name.text'
}

if you want to, but if you just want a workflow that works as our default, use the tasks provided by the plugin. They have been configured for you. If you create custom tasks you have to configure them yourself. Remember you can consult the tests in the code, to see how stuff works

Examples

After applying the plugin, you can call tfPlan and expect that plan is called after all required initialization has been performed. This requires that you have a working terraform setup, e.g. that you are able to perform the terraform cli steps manually.

How do I contribute

Join the party - write a test, code the functionality.

How do I get set up?

  • Build the code : ./gradlew clean build
  • How to run tests
    • ./gradlew test # Simple version
    • ./gradlew --continuous --info test # Keep testing
    • ./gradlew --continuous --info --tests dk.danskespil.gradle.plugins.terraform.tasks.PlanTest test # Keep testing a single test
  • Release, following ajoberstar plugin https://github.com/ajoberstar/gradle-git/wiki/Release%20Plugins
    • ./gradlew clean release -Prelease.scope=major_minor_OR_patch -Prelease.stage=final_OR_rc_OR_milestone_OR_dev
    • ./gradlew clean release # snapshot version
    • ./gradlew clean release -Prelease.scope=patch -Prelease.stage=dev # e.g. fiddling with readme
  • Deployment
    • ./gradlew clean publishPlugins
    • or
    • ./gradlew clean build release publishPlugins -Prelease.scope=patch -Prelease.stage=milestone

Contribution guidelines

  • This is a TDD project. Respect that by writing your test before your code, reuse the existing test classes and helpers and you will be fine

Who do I talk to?

Versions

Next release

0.1.0

  • Handles var files and vars

0.0.9

  • added test with multi project usage example
  • updated to latest deps
  • added dependencies so build, clean, ... behaves like you would expect
  • added auto-apply feature by Joe Bradish

0.0.6-0.0.8

No comments provided.

0.0.5

  • Internal refactoring

0.0.4-SNAPSHOT

  • documentation on tfGet

0.0.3-SNAPSHOT

  • Validate
  • terraform arguments, such as -out, are called 'out' when they are implemented in tasks, e.g. Plan. This undo'es what was done in 0.0.2-SNAPSHOT

0.0.2

  • Has apply

0.0.2-SNAPSHOT

  • make it easy to distinguish between flags and options provided by terraform and those provided by the plugin. Example --out is provided by terraform, and it saves the output of plan to a binary file for later use. However we want to keep the textual output in a file as well, so a plugin-specific flag --outAsText is provided. To make it easy to distinguish, terraform args (such as --out=aFileName.bin) are prefixed with tfNativeArg and becomes --tfNativeArgOut. Yes, its verbose. Yes its easier to figure out what it means without having to read documentation.

0.0.1

  • With focus on "terraform plan" and the corresponding custom task Plan a test environment is set up

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Groovy 100.0%