Skip to content
/ tenv Public
forked from tofuutils/tenv

OpenTofu / Terraform / Terragrunt version manager

License

Notifications You must be signed in to change notification settings

fox-forks/tenv

 
 

Repository files navigation

Github release Contributors maintenance status Go report codecov


Logo

tenv

OpenTofu, Terraform and Terragrunt version manager, written in Go.
· Report Bug · Request Feature

About The Project

Welcome to tenv, a versatile version manager for OpenTofu, Terraform and Terragrunt, written in Go. Our tool simplifies the complexity of handling different versions of these powerful tools, ensuring developers and DevOps professionals can focus on what matters most - building and deploying efficiently.

tenv is a successor of tofuenv and tfenv.

Key Features

  • Versatile version management: Easily switch between different versions of OpenTofu, Terraform and Terragrunt.
  • Semver 2.0.0 Compatibility: Utilizes go-version for semantic versioning and use the HCL parser to extract required version constraint from OpenTofu/Terraform/Terragrunt files.
  • Signature verification: Supports cosign (if present on your machine) and PGP (via gopenpgp), see signature support.
  • Intuitive installation: Simple installation process with Homebrew and manual options.

Table of Contents

Table of Contents
  1. About The Project
  2. Table of contents
  3. Getting Started
  4. Usage
  5. Environment variables
  6. Version files
  7. Technical details
  8. Contributing
  9. Community
  10. Authors
  11. Licence

Getting Started

Prerequisites

If you need to enable cosign checks, install cosign tool via one of the following commands:

MacOS (Homebrew)
brew install cosign
Alpine Linux
apk add cosign
Linux: RPM
LATEST_VERSION=$(curl https://api.github.com/repos/sigstore/cosign/releases/latest | jq -r .tag_name | tr -d "v\", ")
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-${LATEST_VERSION}-1.x86_64.rpm"
sudo rpm -ivh cosign-${LATEST_VERSION}.x86_64.rpm
Linux: dkpg
LATEST_VERSION=$(curl https://api.github.com/repos/sigstore/cosign/releases/latest | jq -r .tag_name | tr -d "v\", ")
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign_${LATEST_VERSION}_amd64.deb"
sudo dpkg -i cosign_${LATEST_VERSION}_amd64.deb

Installation

Automatic Installation

MacOS (Homebrew)
brew tap tofuutils/tap
brew install tenv
Ubuntu
LATEST_VERSION=$(curl --silent https://api.github.com/repos/tofuutils/tenv/releases/latest|jq -r .tag_name)
curl -O -L "https://github.com/tofuutils/tenv/releases/latest/download/tenv_${LATEST_VERSION}_amd64.deb"
sudo dpkg -i "tenv_${LATEST_VERSION}_amd64.deb"

Manual Installation

Get the most recent packaged binaries (.deb, .rpm, .apk, pkg.tar.zst , .zip or .tar.gz format) by visiting the release page. After downloading, unzip the folder and seamlessly integrate it into your system's PATH.

Docker Installation

You can use dockerized version of tenv via the following command:

docker run --rm --it ghcr.io/tofuutils/tenv:latest help

The docker container is not meant as a way to run tenv for CI pipelines, for local use, you should use one of the packaged binaries.

Usage

tenv supports OpenTofu, Terragrunt and Terraform. To manage each binary you can use tenv <tool> <command>. Below is a list of tools and commands that use actual subcommands:

tool env vars description
tofu TOFUENV_ OpenTofu
tf TFENV_ Terraform
tg TG_ Terragrunt
tenv <tool> install [version]

Install a requested version of <tool> (into TENV_ROOT directory from <TOOL>_REMOTE url).

Without a parameter, the version to use is resolved automatically via the relevant <TOOL>_VERSION environment variable or version file (searched in the working directory, its parent, user home directory, and TFENV_ROOT directory).

Will default to "latest" when no specified version is found.

If a parameter is passed, available options include:

  • an exact Semver 2.0.0 version string to install
  • a version constraint string (checked against versions available at <TOOL>_REMOTE url)
  • latest, latest-stable (old name of latest) or latest-pre (include unstable version), which are checked against versions available at <TOOL>_REMOTE url)
  • latest-allowed or min-required to scan your IAC files to detect which version is maximally allowed or minimally required. See required_version docs.
tenv tofu install
tenv tofu install 1.6.0-beta5
tenv tf install "~> 1.6.0"
tenv tf install latest-pre
tenv tg install latest
tenv tg install latest-stable
tenv <tool> install latest-allowed
tenv <tool> install min-required

A complete display :

$ tenv tofu install 1.6.0
Installing OpenTofu 1.6.0
Fetching release information from https://api.github.com/repos/opentofu/opentofu/releases/tags/v1.6.0
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.sig
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.pem
Installation of OpenTofu 1.6.0 successful
tenv <tool> use [version]

Switch the default tool version to use (set in TENV_ROOT/<TOOL>/version file).

tenv <tool> use has a --working-dir, -w flag to write a version file in working directory.

Available parameter options:

  • an exact Semver 2.0.0 version string to use
  • a version constraint string (checked against versions available in TENV_ROOT directory)
  • latest, latest-stable (old name of latest) or latest-pre (include unstable version), which are checked against versions available in TENV_ROOT directory
  • latest-allowed or min-required to scan your IAC files to detect which version is maximally allowed or minimally required.

See required_version docs.

tenv tofu use v1.6.0-beta5
tenv tf use min-required
tenv tg use latest
tenv tofu use latest-allowed
tenv <tool> detect

Detect the used version of tool for the working directory.

$ tenv tofu detect
No version files found for OpenTofu, fallback to latest-allowed strategy
Scan project to find .tf files
No OpenTofu version requirement found in project files, fallback to latest strategy
Found compatible version installed locally : 1.6.1
OpenTofu 1.6.1 will be run from this directory.
$ tenv tg detect -q
Terragrunt 0.55.1 will be run from this directory.
tenv <tool> reset

Reset used version of tool (remove TENV_ROOT/<TOOL>/version file).

$ tenv tofu reset
Removed /home/dvaumoron/.tenv/OpenTofu/version
tenv <tool> uninstall [version]

Uninstall a specific version of OpenTofu (remove it from TENV_ROOT directory without interpretation).

$ tenv tofu uninstall v1.6.0-alpha4
Uninstallation of OpenTofu 1.6.0-alpha4 successful (directory /home/dvaumoron/.tenv/OpenTofu/1.6.0-alpha4 removed)
tenv <tool> list

List installed tool versions (located in TENV_ROOT directory), sorted in ascending version order.

tenv <tool> list has a --descending, -d flag to sort in descending order.

$ tenv tofu list -v
* 1.6.0 (set by /home/dvaumoron/.tenv/OpenTofu/version)
  1.6.1
found 2 OpenTofu version(s) managed by tenv.
tenv <tool> list-remote

List installable tool versions (from <TOOL>_REMOTE url), sorted in ascending version order.

tenv <tool> list-remote has a --descending, -d flag to sort in descending order.

tenv <tool> list-remote has a --stable, -s flag to display only stable version.

$ tenv tofu list-remote
Fetching all releases information from https://api.github.com/repos/opentofu/opentofu/releases
1.6.0-alpha1
1.6.0-alpha2
1.6.0-alpha3
1.6.0-alpha4
1.6.0-alpha5
1.6.0-beta1
1.6.0-beta2
1.6.0-beta3
1.6.0-beta4
1.6.0-beta5
1.6.0-rc1
1.6.0 (installed)
1.6.1 (installed)
tenv help [command]

Help about any command.

You can use --help -h flag instead.

$ tenv help tf detect
Display Terraform current version.

Usage:
  tenv tf detect [flags]

Flags:
  -f, --force-remote         force search on versions available at TFENV_REMOTE url
  -h, --help                 help for detect
  -k, --key-file string      local path to PGP public key file (replace check against remote one)
  -n, --no-install           disable installation of missing version
  -c, --remote-conf string   path to remote configuration file (advanced settings)
  -u, --remote-url string    remote url to install from

Global Flags:
  -q, --quiet              no output (and no log)
  -r, --root-path string   local path to install versions of OpenTofu, Terraform and Terragrunt (default "/home/dvaumoron/.tenv")
  -v, --verbose            verbose output
$ tenv tofu use -h
Switch the default OpenTofu version to use (set in TENV_ROOT/OpenTofu/version file)

Available parameter options:
- an exact Semver 2.0.0 version string to use
- a version constraint string (checked against version available in TENV_ROOT directory)
- latest, latest-stable or latest-pre (checked against version available in TENV_ROOT directory)
- latest-allowed or min-required to scan your OpenTofu files to detect which version is maximally allowed or minimally required.

Usage:
  tenv tofu use version [flags]

Flags:
  -f, --force-remote          force search on versions available at TOFUENV_REMOTE url
  -t, --github-token string   GitHub token (increases GitHub REST API rate limits)
  -h, --help                  help for use
  -k, --key-file string       local path to PGP public key file (replace check against remote one)
  -n, --no-install            disable installation of missing version
  -c, --remote-conf string    path to remote configuration file (advanced settings)
  -u, --remote-url string     remote url to install from
  -w, --working-dir           create .opentofu-version file in working directory

Global Flags:
  -q, --quiet              no unnecessary output (and no log)
  -r, --root-path string   local path to install versions of OpenTofu, Terraform and Terragrunt (default "/home/dvaumoron/.tenv")
  -v, --verbose            verbose output (and set log level to Trace)

Environment variables

tenv commands support global environment variables and variables by tool for : OpenTofu, Terraform and TerraGrunt.

Global tenv environment variables

TENV_AUTO_INSTALL

String (Default: true)

If set to true tenv will automatically install missing tool versions needed.

tenv <tool> subcommands detect and use support a --no-install, -n disabling flag version.

TENV_FORCE_REMOTE

String (Default: false)

If set to true tenv detection of needed version will skip local check and verify compatibility on remote list.

tenv <tool> subcommands detect and use support a --force-remote, -f flag version.

TENV_GITHUB_TOKEN

String (Default: "")

Allow to specify a GitHub token to increase GitHub Rate limits for the REST API. Useful because OpenTofu and Terragrunt binaries are downloaded from GitHub repository.

tenv tofu and tenv tg subcommands detect, install, list-remote and use support a --github-token, -t flag version.

TENV_QUIET

String (Default: false)

If set to true tenv disable unnecessary output (including log level forced to off).

tenv subcommands support a --quiet, -q flag version.

TENV_LOG

String (Default: "warn")

Set tenv log level (possibilities sorted by decreasing verbosity : "trace", "debug", "info", "warn", "error", "off").

tenv support a --verbose, -v flag which set log level to "trace".

TENV_REMOTE_CONF

String (Default: ${TENV_ROOT}/remote.yaml)

The path to a yaml file for advanced remote configuration (can be used to call artifact mirror).

tenv <tool> subcommands detect, install, list-remote and use support a --remote-conf, -c flag version.

TENV_ROOT

String (Default: ${HOME}/.tenv)

The path to a directory where the local OpenTofu versions, Terraform versions, Terragrunt versions and tenv configuration files exist.

tenv support a --root-path, -r flag version.

OpenTofu environment variables

TOFUENV_AUTO_INSTALL

Same as TENV_AUTO_INSTALL (compatibility with tofuenv).

Example 1

Use OpenTofu version 1.6.1 that is not installed, and auto installation is disabled :

$ TOFUENV_AUTO_INSTALL=false tenv use 1.6.1
Written 1.6.1 in /home/dvaumoron/.tenv/OpenTofu/version

Example 2

Use OpenTofu version 1.6.0 that is not installed, and auto installation stay enabled.

$ tenv tofu use 1.6.0
Installing OpenTofu 1.6.0
Fetching release information from https://api.github.com/repos/opentofu/opentofu/releases/tags/v1.6.0
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.sig
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.pem
Installation of OpenTofu 1.6.0 successful
Written 1.6.0 in /home/dvaumoron/.tenv/OpenTofu/version
TOFUENV_FORCE_REMOTE

Same as TENV_FORCE_REMOTE.

TOFUENV_INSTALL_MODE

String (Default: "")

See advanced remote configuration.

TOFUENV_LIST_MODE

String (Default: "")

See advanced remote configuration.

TOFUENV_LIST_URL

String (Default: "")

See advanced remote configuration.

TOFUENV_OPENTOFU_PGP_KEY

String (Default: "")

Allow to specify a local file path to OpenTofu PGP public key, if not present download https://get.opentofu.org/opentofu.asc.

tenv tofu subcommands detect, ìnstall and use support a --key-file, -k flag version.

TOFUENV_REMOTE

String (Default: https://api.github.com/repos/opentofu/opentofu/releases)

To install OpenTofu from a remote other than the default (must comply with Github REST API).

tenv tofu subcommands detect, install, list-remote and use support a --remote-url, -u flag version.

TOFUENV_ROOT

Same as TENV_ROOT (compatibility with tofuenv).

TOFUENV_GITHUB_TOKEN

Same as TENV_GITHUB_TOKEN (compatibility with tofuenv).

TOFUENV_TOFU_VERSION

String (Default: "")

If not empty string, this variable overrides OpenTofu version, specified in .opentofu-version files.

tenv tofu subcommands install and detect also respects this variable.

e.g. with :

TENV_QUIET=t dist/tofu_linux_amd64_v1/tofu version
OpenTofu v1.6.1
on linux_amd64

then :

$ TENV_QUIET=t TOFUENV_TOFU_VERSION=1.6.0 dist/tofu_linux_amd64_v1/tofu version
OpenTofu v1.6.0
on linux_amd64

Terraform environment variables

TFENV_AUTO_INSTALL

Same as TENV_AUTO_INSTALL (compatibility with tfenv).

TFENV_FORCE_REMOTE

Same as TENV_FORCE_REMOTE.

TFENV_HASHICORP_PGP_KEY

String (Default: "")

Allow to specify a local file path to Hashicorp PGP public key, if not present download https://www.hashicorp.com/.well-known/pgp-key.txt.

tenv tf subcommands detect, ìnstall and use support a --key-file, -k flag version.

TFENV_INSTALL_MODE

String (Default: "")

See advanced remote configuration.

TFENV_LIST_MODE

String (Default: "")

See advanced remote configuration.

TFENV_LIST_URL

String (Default: "")

See advanced remote configuration.

TFENV_REMOTE

String (Default: https://releases.hashicorp.com)

To install Terraform from a remote other than the default (must comply with Hashicorp Release API)

tenv tf subcommands detect, install, list-remote and use support a --remote-url, -u flag version.

TFENV_ROOT

Same as TENV_ROOT (compatibility with tfenv).

TFENV_TERRAFORM_VERSION

String (Default: "")

If not empty string, this variable overrides Terraform version, specified in .terraform-version files.

tenv tf subcommands install and detect also respects this variable.

e.g. with :

$ TENV_QUIET=t dist/terraform_linux_amd64_v1/terraform version
Terraform v1.7.2
on linux_amd64

then :

$ TENV_QUIET=t TFENV_TERRAFORM_VERSION=1.7.0 dist/terraform_linux_amd64_v1/terraform version
Terraform v1.7.0
on linux_amd64

Your version of Terraform is out of date! The latest version
is 1.7.2. You can update by downloading from https://www.terraform.io/downloads.html

Terragrunt environment variables

TG_INSTALL_MODE

String (Default: "")

See advanced remote configuration.

TG_LIST_MODE

String (Default: "")

See advanced remote configuration.

TG_LIST_URL

String (Default: "")

See advanced remote configuration.

TG_REMOTE

String (Default: https://api.github.com/repos/gruntwork-io/terragrunt/releases)

To install Terragrunt from a remote other than the default (must comply with Github REST API)

tenv tg subcommands detect, install, list-remote and use support a --remote-url, -u flag version.

TG_VERSION

String (Default: "")

If not empty string, this variable overrides Terragrunt version, specified in .terragrunt-version files.

tenv tg subcommands install and detect also respects this variable.

e.g. with :

$ TENV_QUIET=t terragrunt -v
terragrunt version v0.55.1

then :

$ TENV_QUIET=t TG_VERSION=0.54.1 terragrunt -v
terragrunt version v0.54.1

version files

default version file

The TENV_ROOT/<TOOL>/version file is the tool default version used when no project specific or user specific are found. It can be written with tenv <tool> use.

opentofu version files

If you put a .opentofu-version file in the working directory, one of its parent directory, or user home directory, tenv detects it and uses the version written in it. Note, that TOFUENV_TOFU_VERSION can be used to override version specified by .opentofu-version file.

Recognize same values as tenv tofu use command.

See required_version docs.

terraform version files

If you put a .terraform-version or .tfswitchrc file in the working directory, one of its parent directory, or user home directory, tenv detects it and uses the version written in it. Note, that TFENV_TERRAFORM_VERSION can be used to override version specified by those files.

Recognize same values as tenv tf use command.

See required_version docs.

terragrunt version files

If you put a .terragrunt-version or a .tgswitchrc file in the working directory, one of its parent directory, or user home directory, tenv detects it and uses the version written in it. tenv also detect a version field in a .tgswitch.toml in same places. Note, that TG_VERSION can be used to override version specified by those files.

Recognize same values as tenv tg use command.

terragrunt.hcl file

If you have a terragrunt.hcl or terragrunt.hcl.json in the working directory, tenv will read constraint from terraform_version_constraint or terragrunt_version_constraint field in it (depending on proxy or subcommand used).

required_version

the latest-allowed or min-required strategies scan through your IAC files (.tf or .tf.json) and identify a version conforming to the constraint in the relevant files.

Currently the format for Terraform required_version and OpenTofu required_version are very similar, however this may change over time, always refer to docs for the latest format specification.

example:

version = ">= 1.2.0, < 2.0.0"

This would identify the latest version at or above 1.2.0 and below 2.0.0

Technical details

Project binaries

tofu

The tofu command in this project is a proxy to OpenTofu's tofu command managed by tenv. The default resolution strategy is latest-allowed relying on terraform_version_constraint from terragunt.hcl file or required_version from .tf files (without TOFUENV_TOFU_VERSION environment variable or .opentofu-version file).

terraform

The terraform command in this project is a proxy to HashiCorp's terraform command managed by tenv. The default resolution strategy is latest-allowed relying on terraform_version_constraint from terragunt.hcl file or required_version from .tf files (without TFENV_TERRAFORM_VERSION environment variable or .terraform-version file).

terragrunt

The terragrunt command in this project is a proxy to Gruntwork's terragrunt command managed by tenv. The default resolution strategy is latest-allowed relying on terragrunt_version_constraint from terragunt.hcl file (without TG_VERSION environment variable or .terragrunt-version file).

Advanced remote configuration

This advanced configuration is meant to call artifact mirror (like JFrog Artifactory).

The yaml file from TENV_REMOTE_CONF path can have one part for each supported proxy : tofu, terraform and terragrunt.

yaml fields description

Each part can have the following string field : install_mode, list_mode, list_url, url, new_base_url, old_base_url, selector and part

With install_mode set to "direct", tenv skip the release information fetching and build download url directly (overridden by <TOOL>_INSTALL_MODE env var).

With list_mode set to "html", tenv change the fetching of all releases information from API to parse the parent html page of artifact location, see selector and part (overridden by <TOOL>_LIST_MODE env var).

url allows to override the default remote url (overridden by flag or <TOOL>_REMOTE env var).

list_url allows to override the remote url only for the releases listing (overridden by <TOOL>_LIST_URL env var).

old_base_url and new_base_url are used as url rewrite rule (if an url start with the prefix, it will be changed to use the new base url).

If old_base_url and new_base_url are empty, tenv try to guess right behaviour depending previous field.

selector is used to gather in a list all matching html node and part choose on which node part (attribute name or "#text" for inner text) a version will be extracted (selector default to "a" (html link) and part default to "href" (link target))

Examples

Those examples assume that a GitHub proxy at https://artifactory.example.com/artifactory/github have the same behavior than JFrog Artifactory :

Example 1 : Retrieve Terraform binaries and list available releases from the mirror.

TFENV_REMOTE=https://artifactory.example.com/artifactory/hashicorp
TFENV_LIST_MODE=html

Example 2 : Retrieve Terraform binaries from the mirror and list available releases from the Hashicorp releases API.

TFENV_REMOTE=https://artifactory.example.com/artifactory/hashicorp
TFENV_LIST_URL=https://releases.hashicorp.com

Example 1 & 2, does not need install mode (by release index.json is figed in mirror without problem), however create a rewrite rule from "https://releases.hashicorp.com" to "https://artifactory.example.com/artifactory/hashicorp" to obtains correct download URLs.

Example 3 : Retrieve OpenTofu binaries and list available releases from the mirror.

TOFUENV_REMOTE=https://artifactory.example.com/artifactory/github
TOFUENV_INSTALL_MODE=direct
TOFUENV_LIST_MODE=html

Example 4 : Retrieve OpenTofu binaries from the mirror and list available releases from the GitHub API.

TOFUENV_REMOTE=https://artifactory.example.com/artifactory/github
TOFUENV_INSTALL_MODE=direct
TOFUENV_LIST_URL=https://api.github.com/repos/opentofu/opentofu/releases

Example 3 & 4, does not create a rewrite rule (the direct install mode build correct download URLs).

Example 1 & 4 can be merged in a remote.yaml :

tofu:
  url: "https://artifactory.example.com/artifactory/github"
  install_mode: "direct"
  list_url: "https://api.github.com/repos/opentofu/opentofu/releases"
terraform:
  url: "https://artifactory.example.com/artifactory/hashicorp"
  list_mode: "html"

Signature support

OpenTofu signature support

tenv checks the sha256 checksum and the signature of the checksum file with cosign (if present on your machine) or PGP (via gopenpgp). However, unstable OpenTofu versions are signed only with cosign (in this case, if cosign is not found tenv will display a warning).

Terraform signature support

tenv checks the sha256 checksum and the PGP signature of the checksum file (via gopenpgp, there is no cosign signature available).

Terragrunt signature support

tenv checks the sha256 checksum (there is no signature available).

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

Community

Have questions or suggestions? Reach out to us via:

  • GitHub Issues
  • User/Developer Group: Join github community to get update of Harbor's news, features, releases, or to provide suggestion and feedback.
  • Slack: Join tofuutils's community for discussion and ask questions: OpenTofu, channel: #tofuutils

Authors

tenv is based on tofuenv and gotofuenv projects and supported by tofuutils team with help from these awesome contributors:

Star History Chart

LICENSE

The tenv project is distributed under the Apache 2.0 license. See LICENSE.

About

OpenTofu / Terraform / Terragrunt version manager

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 97.5%
  • Dockerfile 1.4%
  • Makefile 1.1%