Terranova is a thin wrapper for Terraform that provides extra tools and logic to handle Terraform configurations at scale.
- Python 3.12+ for development.
- uv for build system.
- Podman for container packaging.
- pre-commit for git management.
- Ability to share terraform configuration without modules.
- Ability to define arbitrary resource layout.
- Ability to auto-generate documentation using metadata attached to resource definition.
- Ability to execute runbooks to interact with resources.
- Ability to import variables between resource group.
- We needed a way to manage resources as code at scale.
- The solution should leverage terraform to avoid re-implementing the wheel.
- The solution shouldn't leverage the terraform configuration DSL to add features since it can change.
The following steps will ensure your project is cloned properly.
- Clone repository:
git clone https://github.com/elastic/terranova cd terranova - Install dependencies and setup environment:
uv sync uv run poe env:configure
- To lint you have to use the workflow.
uv run poe lint- It will lint the project code using
pylint.
- To format you have to use the workflow.
uv run poe fmt- It will format the project code using
blackandisort.
# Install custom terranova tap
brew tap elastic/terranova
# Install terranova
brew install terranovacurl -sSL https://raw.githubusercontent.com/elastic/terranova/0.6.5/install.sh | sh -sIf you use wget instead:
wget -qO- https://raw.githubusercontent.com/elastic/terranova/0.6.5/install.sh | sh -sThat will download terranova, put it inside /usr/local/bin/ and give it execution rights with chmod.
# For MacOSX Apple Silicon
gh release download 0.6.5 -p '*-darwin-arm64' -O /usr/local/bin/terranova --clobber --repo elastic/terranova
# For MacOSX Intel
gh release download 0.6.5 -p '*-darwin-amd64' -O /usr/local/bin/terranova --clobber --repo elastic/terranova
# For Linux arm64
gh release download 0.6.5 -p '*-linux-arm64' -O /usr/local/bin/terranova --clobber --repo elastic/terranova
# For Linux amd64
gh release download 0.6.5 -p '*-linux-amd64' -O /usr/local/bin/terranova --clobber --repo elastic/terranova
# Make it executable
chmod +x /usr/local/bin/terranovaterranovarely on the concept of resource groups.- You can define as many resource groups as you want.
- The base layout should contain the directory
resourcesandshared. - The
resourcesdirectory contains resource groups. - The
shareddirectory contains any sharable resource that will be symlink if defined as dependency. - A resource group is defined when a
manifest.ymlis present. - By default,
terranovawill look for aconfdirectory in the working directory that contain both above directories.
conf
βββ resources
β βββ resource_group_1
β β βββ runbooks
β β β βββ pyinfra.py
β β βββ main.tf
β β βββ manifest.yml
β βββ resource_group_2
β βββ main.tf
β βββ manifest.yml
βββ shared
βββ providers
β βββ github.tf
βββ config.tf
terranovawill rely on the layout to apply change using terraform.- In the above case, running
terranova apply resource_group_1will runterraformon resources present in that directory. terranovasupports any depth within the layout.- This allows you to reflect any structure.
- Create a new directory in
conf/resources. - Create a new
manifest.ymlfile with the following content.
version: "1.2"
metadata:
name: Terranova Hello World
description: Hello World
url: https://github.com/elastic/terranova
contact: mailto:[email protected]- Define any resource using standard
terraformconfiguration. - Add metadata on each resource to allow auto-generate documentation.
/*
@attr-name attr-value
*/
data "null_data_source" "values" {
inputs = {}
}
/*
@attr-name attr-value
*/
resource "null_resource" "foobar" {}- You can now run
terranova init <resource_group_name>andterranova apply <resource_group_name>.
- In some case, we need to share common terraform configuration or scripts across many resource group.
- It's possible to define dependencies in the manifest and symlink them in any resource group.
- Those common resources should be defined in the
shareddirectory. - All symlink are maintained by
terranovaand are updated when theterranova initcommand is run.
# Supported since 1.0 manifest version.
---
dependencies:
- source: providers/github.tf # Which file or directory to symlink.
target: 00-github-provider.tf # Where to symlink the file or directory.- In some case, we need to interact with terraform resources using specific tooling.
- It's possible to define a runbook in the manifest and invoke arbitrary tools.
- It's also possible to interact with
terranovato extract information usingoutputs.
# Supported since 1.1 manifest version.
---
runbooks:
- name: "<runbook_name>" # Used as argument in the command
entrypoint: "<tool_entrypoint>" # Tool to invoke
workdir: "<working_directory>" # Optional: Used to navigate in sub-directories.
args:
- <arguments> # List of arguments to pass
env:
- name: PATH # Inherit environment value
- name: FOO # Override or define environment value
value: bar- In some case, we need to interact across many resource groups and need to import variables from a resource group to another one.
- It's possible to define imports in the manifest.
# Supported since 1.2 manifest version.
---
imports:
- from: "<resource_group_path>" # Relative resource group path
import: "<output_variable>" # Name of the output variable to import
as: "<working_directory>" # Optional: Name of the input variable to map to.- Run the following command
terranova docs.
- Run the following command
terranova apply <path>.
- Run the following command
terranova import <path> <resource_address> <identifier>. - The
importterraform command is used under the hood.
If you find this project useful here's how you can help, please click the ποΈ Watch button to avoid missing notifications about new versions, and give it a π GitHub Star!
You can also contribute by:
- Sending a Pull Request with your awesome new features and bug fixed.
- Be part of the community and help resolve Issues.
The terranova project is free and open-source software licensed under the Apache-2.0 license.