Skip to content
Terraform Maven Plugin
Java Groovy HCL
Branch: develop
Clone or download

README.md

terraform-maven


License Build Status Coverage Status Maven Central

Terraform Maven Plugin

The Terraform Maven Plugin brings Maven to Terraform, which greatly enhances Terraform’s project lifecycle and dependency management capability. Maven in some form has been the standard for Java project management for over a decade. Now, all of that Maven goodness can be used with Terraform!


Contents

Not finding what you are looking for? Try the Wiki!


Artifacts in This Repository

Artifact Name Version Latest Snapshot Security Scan Results Description
tf-maven-plugin Maven Central Maven Snapshot tf-maven-plugin vulnerabilities Terraform Maven Plugin
tf-cmd-api Maven Central Maven Snapshot tf-cmd-api vulnerabilities Terraform Command API
tf-s3-archetype Maven Central Maven Snapshot N/A Maven Terraform S3 Archetype

Repository Directory Structure

  • examples - Terraform Maven example projects
    • tf-s3 - A Terraform Maven s3 example project
    • tf-s3-consumer - An example project that consumes the tf-s3 project as a dependency
  • tf-build-tools - The parent project of the tf-maven-plugin and tf-cmd-api projects
    • tf-maven-plugin - The Terraform Maven Plugin project
    • tf-cmd-api - A Java API for Terraform project
    • tf-s3-archetype - An Archetype for a S3 Terraform Project

Benefits of the Terraform Maven Plugin

  • Dependency Management
    • Terraform really has no dependency management to speak of. Even when you use Terraform Enterprise or some other private Terraform module registry, a version update to a module means editing the Terraform code in each and every place that module is sourced. The Terraform Maven Plugin allows you to specify your dependencies for Terraform the same way you specify your dependencies with Java: in an external Maven POM file. And because it's Maven, Terraform modules sourced from Maven repos can also take advantage of version ranges and Maven's SNAPSHOT functionality. It also resoolves transitive dependencies. No more modifying code for version updates! No more sourcing obscure URLs! Hooray, Maven!
  • Packaging as Part of the Build Lifecycle
    • The package goal can package a Terraform root module for deployment into a Maven repo or it can package that same Terraform root module with its dependencies for deployment into an isolated environment or Terraform Enterprise. It's all part of a single Maven goal/command.
  • Deploying Terraform Artifacts to a Maven Repo with an Attached POM is a Snap
    • By default the deploy goal deploys a zip artifact packaged by the package goal to a Maven repo along with the POM of the current Maven Terraform project. But if you want to point to a differnt POM or a different artifact for deployment, it can do that too. Easy peasy.
  • Terraform support for Java testing frameworks
    • The tf-cmd-api artifact provides Java support for Terraform, which can be used to easily integrate mature Java testing frameworks, like Spock or JUnit. One example of this is the [tf-s3 example in this repo].
  • Simple Integration with CI Tools
    • Get rid of hundreds of lines of untested code in your CI tool and replace it with tested build lifecycle management using Maven! Most CI tools either have Maven included or have a Maven plugin available. Less Terraform build logic in your CI tool means more reliable builds and less CI code to maintain.
  • Build Terraform Maven Projects or Standalone Terraform Configurations and Anything In Between
    • You can use the Terraform Maven plugin for building any Terraform, not just Terraform Maven projects! The default configuration is opinionated around the Maven project structure. But that's available to override. Do you have a different folder containing Terraform modules that you want packaged into a Fat Zip? No problem. What about just running a Terraform configuration in some directory that you specify? That works too. You don't lose anything with the Terraform Maven plugin. You just gain a whole lot of packaged functionality and the build lifecycle power of Maven with Terraform!

Maven Goals

tf:get

Description:

Downloads Maven artifacts into a common modules directory and extracts each artifacts contents into a folder named for the artifact (version agnostic).

Optional Parameters:

Name Type Description
tfModulesDir String The directory location where Terraform modules will be expanded; defaults to src/main/.tfmodules

tf:init

Description:

Executes the terraform init command. See https://www.terraform.io/docs/commands/init.html.

Note: tf:init depends on tf:get; so tf:get is always executed when tf:init is specified.

Optional Parameters:

Name Type Description
tfRootDir String The root module directory location where terraform will be initialized; defaults to src/main/tf/{first dir found}
pluginDir String Skips plugin installation and loads plugins only from the specified directory
getPlugins Boolean Skips plugin installation
backendConfig String A comma delimited string of optional backend config (e.g. backendConfig="region=us-east-1,bucket=mybucket,key=/some/path")
verifyPlugins Boolean Skips release signature validation when installing downloaded plugins (not recommended)
skipTfGet Boolean If set to true, tf:init is done without running tf:get

tf:plan

Description:

Executes the terraform plan command. See https://www.terraform.io/docs/commands/plan.html.

Optional Parameters:

Name Type Description
tfVarFiles String A comma delimited string of tfvars files (e.g. -var-file=foo)
tfVars String A comma delimited string of tfvars (e.g. -var 'name=value')
lockTimeout Number Duration to retry a state lock
target Number A resource address to target
planInput Boolean If set to "true", input variables not directly set will be requested; otherwise, the plan will fail
noColor Any If this property exists, the -no-color flag is set
destroyPlan Any If this property exists, a destroy plan is outputted
planOutputFile String The path to save the generated execution plan
tfRootDir String A terraform config directory to apply; defaults to src/main/tf/{first dir found}, then current directory
timeout Number The maximum time in milliseconds that the terraform apply command can run; defaults to 10min
refreshState Boolean If set to "true" then Terraform will refresh the state before generating the plan
tfState String The path to the state file; defaults to terraform.tfstate

tf:apply

Description:

Executes the terraform apply command. See https://www.terraform.io/docs/commands/apply.html.

Optional Parameters:

Name Type Description
tfVarFiles String A comma delimited string of tfvars files (e.g. -var-file=foo)
tfVars String A comma delimited string of tfvars (e.g. -var 'name=value')
lockTimeout Number Duration to retry a state lock
target Number A resource address to target
noColor Any If this property exists, the -no-color flag is set
plan String A terraform plan to apply; if both plan and tfRootDir are specified, only plan is used
tfRootDir String A terraform config directory to apply; defaults to src/main/tf/{first dir found}, then current directory
timeout Number The maximum time in milliseconds that the terraform apply command can run; defaults to 10min

tf:destroy

Description:

Executes the terraform destroy command. See https://www.terraform.io/docs/commands/destroy.html.

Optional Parameters:

Name Type Description
lockTimeout Number Duration to retry a state lock
tfVars String A comma delimited string of tfvars (e.g. -var 'name=value')
target Number A resource address to target
noColor Any If this property exists, the -no-color flag is set
tfRootDir String A terraform config directory to destroy; defaults to current directory
timeout Number The maximum time in milliseconds that the terraform destroy command can run; defaults to 10min

tf:package

Description:

Recursively packages the Terraform files from the root module directory as target/{artifact-id}-{version}.zip. Optionally, a fat compressed package can be created instead, which also includes the Terraform module dependencies if available; see the tf:get goal above.

Note: Within the fat compressed package, module source paths are updated accordingly so that the pacakge is a wholly contained working module that can be consumed as a module, extracted, initialized and applied as-is or submitted to Terraform Enterprise.

Name Type Description
tfRootDir String The terraform root module directory location; defaults to src/main/tf/{first directory found} or src/main/tf if there are multiple source modules
tfModulesDir String The directory that contains the Terraform module depenencies; defaults to src/main/.tfmodules
fatTar Boolean Set to true if a fat compressed tar.gz package should be created, otherwise false; defaults to false

tf:deploy

Description:

Deploys a packaged Terraform zip artifact (see tf:package) with a POM to the specified Maven repo.

Name Type Description
file String The name of the Terraform zip file to deploy; defaults to target/{artifactId}-{version}.zip
url String The url of the Maven repo to which the zip file artifact will be deployed; defaults to {HOME}/.m2/repository
pomFile String The path to the pom.xml file to attach to the artifact; defaults to .flattened-pom.xml in the root of the project
generatePom String If set to "true" then a POM will be generated and attached to the deployment
groupId String The groupId for the generated POM (only used if generatePom=true
artifactId String The artifactId for the generated POM (only used if generatePom=true
version String The version for the generated POM (only used if generatePom=true
repositoryId String The server id to map on the under section of settings.xml; typically for authentication

tf:clean

Description:

Deletes all 'terraform' files from terraform configurations along with the Terraform modules directory.

Name Type Description
tfRootDir String The terraform root module directory location; defaults to src/main/tf/{first directory found}
tfModulesDir String The directory that contains the Terraform module depenencies; defaults to src/main/.tfmodules

How Commands Are Delegated to Terraform

Terraform commands are executed in a forked shell that is joined to the Maven process. This has important implications based on the operating system being used.

*nix-based Operating Systems

Terraform commands executed on *nix-based systems are forked into a bash shell that is joined to the Maven process.

Windows Operating Systems

Terraform commands executed on Windows operating systems by default use the Windows default command line (cmd.exe), which is not strictly compatible with Terraform as of Terraform v0.12 (e.g. -var parameters fail).

However, Git Bash can be used in place of the default Windows command line to improve compatibility with Terraform commands. To enable Git Bash, either set a Java system property shellPath or an environment variable SHELL_PATH to the absolute path of the Git Bash executable.

Setting Up a Terraform Maven Project

  1. Create a generic Maven project. see Maven Getting Started Guide
  2. Add a src/main/tf directory, under which one or more Terraform root module will reside.
  3. Add a paramater to the POM that specifies the version of the Terraform Maven Plugin
<properties>
  <tf-maven-version>0.7.3</tf-maven-version>
</properties>
  1. Configure the build plugins for the Terraform Maven Plugin (see the tf-s3 example for reference).
  <build>
    <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-install-plugin</artifactId>
          <executions>
            <execution>
              <id>default-install</id>
              <phase>never</phase>
            </execution>
          </executions>
        </plugin>
        <plugin>
          <!-- disables default jar packaging: https://stackoverflow.com/questions/2188746/what-is-the-best-way-to-avoid-maven-jar -->
          <artifactId>maven-jar-plugin</artifactId>
          <executions>
            <execution>
              <id>default-jar</id>
              <phase>never</phase>
              <configuration>
                <finalName>unwanted</finalName>
                <classifier>unwanted</classifier>
              </configuration>
            </execution>
          </executions>
        </plugin>
        <plugin>
          <groupId>com.deliveredtechnologies</groupId>
          <artifactId>tf-maven-plugin</artifactId>
          <version>${tf-maven-version}</version>
          <executions>
            <execution>
              <id>terraform-clean</id>
              <phase>clean</phase>
              <goals>
                <goal>clean</goal>
              </goals>
            </execution>
            <execution>
              <id>terraform-install</id>
              <phase>install</phase>
              <goals>
                <goal>deploy</goal>
              </goals>
            </execution>
            <execution>
              <id>terraform-package</id>
              <phase>package</phase>
              <goals>
                <goal>package</goal>
              </goals>
            </execution>
            <execution>
              <id>terraform-deploy</id>
              <phase>deploy</phase>
              <goals>
                <goal>deploy</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-deploy-plugin</artifactId>
          <configuration>
            <skip>true</skip>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>flatten-maven-plugin</artifactId>
          <version>1.1.0</version>
          <configuration>
          </configuration>
          <executions>
            <!-- enable flattening -->
            <execution>
              <id>flatten</id>
              <phase>process-resources</phase>
              <goals>
                <goal>flatten</goal>
              </goals>
            </execution>
            <!-- ensure proper cleanup -->
            <execution>
              <id>flatten.clean</id>
              <phase>clean</phase>
              <goals>
                <goal>clean</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
    </plugins>
  </build>

Setting Up a Terraform Maven Project Using an ArcheType

Instead of doing all the above steps you can simply build the module/project by running the Maven Archetype Plugin which creates project from an archetype.

An example on how to generate the project using an archetype is shown below.

mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.7.3 -DgroupId=<custom_group_name> -DartifactId=<custom-artifact_name>

Maven Non-Interactive mode creates a project with the name that you passed in <custom_articatId_name> under <custom_groupId_name>.

or

mvn archetype:generate -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.7.3

After running the above command mvn interactive console prompts for the required arguments (ex: groupId and artifactId) and creates the project accordingly.

How to Use Terraform Maven Projects

If you used the above configuration, the following Terraform Maven goals are mapped to the project's Maven phases.

Maven Phase Terraform Maven Goals
install deploy
clean clean
package package
deploy deploy

Articles

You can’t perform that action at this time.