{"id":15155679,"url":"https://github.com/craftypath/gotf","last_synced_at":"2025-10-24T12:31:00.125Z","repository":{"id":38081979,"uuid":"236013123","full_name":"craftypath/gotf","owner":"craftypath","description":"Managing multiple environments with Terraform made easy","archived":false,"fork":false,"pushed_at":"2023-03-07T03:00:54.000Z","size":17332,"stargazers_count":25,"open_issues_count":10,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-31T01:14:42.383Z","etag":null,"topics":["devops","environments","go","golang","hashicorp","hashicorp-terraform","iac","infrastructure-as-code","terraform"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/craftypath.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-24T14:02:09.000Z","updated_at":"2022-02-09T17:57:59.000Z","dependencies_parsed_at":"2024-06-20T10:21:59.154Z","dependency_job_id":"01d22a06-8841-4476-84b4-7c65b2f83d8e","html_url":"https://github.com/craftypath/gotf","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/craftypath%2Fgotf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/craftypath%2Fgotf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/craftypath%2Fgotf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/craftypath%2Fgotf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/craftypath","download_url":"https://codeload.github.com/craftypath/gotf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237964492,"owners_count":19394410,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devops","environments","go","golang","hashicorp","hashicorp-terraform","iac","infrastructure-as-code","terraform"],"created_at":"2024-09-26T18:42:07.821Z","updated_at":"2025-10-24T12:30:54.800Z","avatar_url":"https://github.com/craftypath.png","language":"Go","readme":"# gotf\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![CI](https://github.com/craftypath/gotf/workflows/CI/badge.svg?branch=master\u0026event=push)\n\n`gotf` is a Terraform wrapper that makes it easy to support multiple configurations, e.g. for different environments.\n\n## Installation\n\n### GitHub Release\n\nDownload a release from GitHub:\n\nhttps://github.com/craftypath/gotf/releases\n\n### Homebrew\n\n```console\n$ brew tap craftypath/tap\n$ brew install gotf\n```\n\n## Usage\n\n```console\n$ gotf --help\n\n  ___   __  ____  ____\n / __) /  \\(_  _)(  __)\n( (_ \\(  O ) )(   ) _)\n \\___/ \\__/ (__) (__)   v0.16.0 (commit=00896ad, date=2021-12-10T18:21:54Z)\n\ngotf is a Terraform wrapper facilitating configurations for various environments\n\nUsage:\n  gotf [flags] [Terraform args]\n\nFlags:\n  -c, --config string        Config file to be used (default \"gotf.yaml\")\n  -d, --debug                Print additional debug output to stderr\n  -h, --help                 help for gotf\n  -m, --module-dir string    The module directory to run Terraform in (default \".\")\n  -n, --no-vars              Don't add any variables when running Terraform.\n                             This is necessary when running 'terraform apply' with a plan file.\n  -p, --params key=value     Params for templating in the config file. May be specified multiple times (default map[])\n  -s, --skip-backend-check   Skip checking for changed backend configuration\n  -v, --version              version for gotf\n```\n\n## Demo\n\nCheck out the [demo](demo) project which does not use cloud providers and keeps state locally.\nThis allows you to play with the tool on your local machine.\n\n## Talks\n\n\u003ca href=\"https://www.youtube.com/watch?v=Tel-9m5_MSc\u0026list=PLD9VybHH2wnYtuaiEcjMH5n2gTgNSDYAV\" target=\"_blank\"\u003e\u003cimg src=\"https://i.ytimg.com/vi/Tel-9m5_MSc/maxresdefault.jpg\"\nalt=\"🇩🇪 gotf – Umgebungen mit Terraform einfacher managen | Reinhard von codecentric auf der #SoftwerkerKonf\" width=\"240\" height=\"135\" border=\"10\" /\u003e\u003c/a\u003e\u003cbr\u003e\n**🇩🇪 gotf – Umgebungen mit Terraform einfacher managen | Reinhard von codecentric auf der #SoftwerkerKonf**\n\n## Configuration\n\n`gotf` is configured via config file.\nBy default, `gotf.yaml` is loaded from the current directory.\nConfig files support templating as specified below.\n\n### Parameters\n\n#### `terraformVersion`\n\nOptionally sets a specific Terraform version to use.\n`gotf` will download this version and cache it in `$XDG_CACHE_HOME/gotf/terraform/\u003cversion\u003e` verifying GPG signature and SHA256 sum.\n\n#### `params`\n\nConfig entries that can be used for templating. See section on templating below for details.\n\n#### `requiredParams`\n\nIn addition to specifying `params` in the config file, they may also be specified on the command-line using the `-p|--param` flag.\nParams that are required can be configured here.\nAllowed values for a `param` must be specified as list.\nIf no restrictions apply, no value or an empty list must be specified.\nValues must be strings.\n\n#### `globalVarFiles`\n\nA list of variables files which are added to the Terraform environment via `TF_CLI_ARGS_\u003ccommand\u003e=-var-file=\u003cfile\u003e` for commands that support them.\nThey are resolved relative to this config file.\n\n#### `moduleVarFiles.\u003cmoduleDir\u003e`\n\nA list of module-specific variables files which are added to the Terraform environment if the corresponding module is run via `TF_CLI_ARGS_\u003ccommand\u003e=-var-file=\u003cfile\u003e` for commands that support them.\nThey are resolved relative to this config file.\n\n#### `globalVars`\n\nVariables which are added to the Terraform environment via `TF_VAR_\u003cvar\u003e=value` for commands that support them.\n\n#### `moduleVars.\u003cmoduleDir\u003e`\n\nModule-specific variables which are added to the Terraform environment if the corresponding module is run via `TF_VAR_\u003cvar\u003e=value` for commands that support them.\nModule-specific variables override global ones.\n\n#### `varsFromEnvFiles`\n\nAllows variables to be configured as env files (`name=value` per line) which can also be sourced from a shell script.\n`gotf` interprets these files and passes each entry via `TF_VAR_` environment variable.\nNames are automatically lower-cased to match the common Terraform style.\nThis feature can be quite convenient if you create parts of your infrastructure via Terraform and other parts via shell scripts\nbut want to have a common source for shared variables.\nThis is also a workaround for getting rid of Terraform warnings in case a variable is not declared, which might happen if you use global var files for different modules.\nComments and variable expansion are supported.\n\n```shell\n# comment for FOO\nFOO=foo\n\n# comment for BAR\nBAR=\"bar is just a $FOO\"\n```\n\nThis would then be set as follows:\n\n```shell\nTF_VAR_foo=foo\nTV_VAR_bar=\"bar is just a foo\"\n```\n\n#### `envs`\n\nEnvironment variables to be added to the Terraform process.\n\n#### `backendConfigs`\n\nBackend configuration added as `-backend-config` CLI options when the Terraform `init` command is run.\n\n#### `ignoreMissingVarFiles`\n\nIf set to `true`, gotf checks whether configured variable files exist and does not pass them to Terraform if they don't.\n\n### Example\n\n```yaml\nterraformVersion:  1.1.5\n\nrequiredParams:\n  environment:\n    - dev\n    - prod\n\nparams:\n  param: myval\n\nglobalVarFiles:\n  - global-{{ .Params.environment }}.tfvars\n  - global.tfvars\n\nglobalVars:\n  foo: foovalue\n  templated_var: \"{{ .Params.param }}\"\n  mapvar: |-\n    {\n      entry1 = {\n        value1 = testvalue1\n        value2 = true\n      }\n      entry2 = {\n        value1 = testvalue2\n        value2 = false\n      }\n    }\n  module_dir: \"{{ .Params.moduleDir }}\"\n  state_key: '{{ (splitn \"_\" 2 .Params.moduleDir)._1 }}'\n\nmoduleVarFiles:\n  01_networking:\n    - 01_networking/{{ .Params.environment }}.tfvars\n  02_compute:\n    - 02_compute/{{ .Params.environment }}.tfvars\n\nmoduleVars:\n  01_networking:\n    myvar: value for networking\n  02_compute:\n    myvar: value for compute\n\nvarsFromEnvFiles:\n  - '{{ .Params.environment }}.env'\n\nenvs:\n  BAR: barvalue\n  TEMPLATED_ENV: \"{{ .Params.param }}\"\n\nbackendConfigs:\n  key: \"{{ .Vars.state_key }}\"\n  storage_account_name: mytfstateaccount{{ .Params.environment }}\n  resource_group_name: mytfstate-{{ .Params.environment }}\n  container_name: mytfstate-{{ .Params.environment }}\n```\n\n### Templating\n\nGo templating can be used in the config file as follows.\nHermetic, i.e. repeatable, functions from the [Sprig](https://masterminds.github.io/sprig/) function library are included.\n\n* In the first templating pass, `globalVarFiles`, `globalVars`, `moduleVarFiles`, `moduleVars`, and `envs` are processed.\n  All parameters specified under `params` and using the `-p|--param` flag are available in the `.Params` object.\n  CLI params override those specified in the config file.\n  The basename of the module directory passed with the `--module-dir|-m` parameter is available as `moduleDir` dir in the `.Params` object.\n* In the second templating pass, `backendConfigs` are processed.\n  `globalVars` and ` moduleVars` are available as `.Vars` and `envs` are available as `.Envs` with the results from the first templating pass.\n  Additionally, `.Params` is also available again.\n\nUsing the above config file, running `terraform init` could look like this:\n\n```console\n$ gotf -c example-config.yaml -p environment=dev -m 01_networking init\n```\n\nAfter processing, the config file would look like this:\n\n```yaml\nterraformVersion:  1.1.5\n\nrequiredParams:\n  environment:\n    - dev\n    - prod\n\nparams:\n  param: myval\n\nglobalVarFiles:\n  - global-dev.tfvars\n  - global.tfvars\n\nglobalVars:\n  foo: foovalue\n  templated_var: \"myval\"\n  mapvar: |-\n    {\n      entry1 = {\n        value1 = testvalue1\n        value2 = true\n      }\n      entry2 = {\n        value1 = testvalue2\n        value2 = false\n      }\n    }\n  module_dir: \"01_networking\"\n  state_key: 'networking'\n\nmoduleVarFiles:\n  01_networking:\n    - 01_networking/dev.tfvars\n  02_compute:\n    - 02_compute/dev.tfvars\n\nmoduleVars:\n  01_networking:\n    myvar: value for networking\n  02_compute:\n    myvar: value for compute\n\nenvs:\n  BAR: barvalue\n  TEMPLATED_ENV: \"myval\"\n\nbackendConfigs:\n  key: \"networking\"\n  storage_account_name: mytfstateaccountdev\n  resource_group_name: mytfstate-dev\n  container_name: mytfstate-dev\n```\n\n## Debug Output\n\nSpecifying the `--debug` flag produces debug output which is written to stderr.\nFor example, the integration test in [cmd/gotf/gotf_test.go](cmd/gotf/gotf_test.go) produces the following debug output before running Terraform:\n\n```console\ngotf\u003e Loading config file: testdata/test-config.yaml\ngotf\u003e Processing var files...\ngotf\u003e File testdata/global-does-not-exists.tfvars does not exist. Ignoring it.\ngotf\u003e Processing module var files...\ngotf\u003e Processing vars from env files...\ngotf\u003e Processing global vars...\ngotf\u003e Processing module vars...\ngotf\u003e Processing envs...\ngotf\u003e Processing backend configs...\ngotf\u003e Using Terraform version 1.1.5\ngotf\u003e Terraform version 1.1.5 already installed.\ngotf\u003e Terraform binary: /Users/myuser/Library/Caches/gotf/terraform/1.1.5/terraform\ngotf\u003e\ngotf\u003e Terraform command-line:\ngotf\u003e -----------------------\ngotf\u003e /Users/myuser/Library/Caches/gotf/terraform/1.1.5/terraform apply -auto-approve -no-color\ngotf\u003e\ngotf\u003e Terraform environment:\ngotf\u003e ----------------------\ngotf\u003e TF_CLI_ARGS_import=-var-file=\"../global-prod.tfvars\" -var-file=\"../global.tfvars\" -var-file=\"prod.tfvars\"\ngotf\u003e TF_CLI_ARGS_init=-backend-config=path=\".terraform/terraform-networking-prod.tfstate\"\ngotf\u003e TEMPLATED_ENV=myval\ngotf\u003e TF_CLI_ARGS_plan=-var-file=\"../global-prod.tfvars\" -var-file=\"../global.tfvars\" -var-file=\"prod.tfvars\"\ngotf\u003e TF_VAR_myvar=value for networking\ngotf\u003e TF_CLI_ARGS_apply=-var-file=\"../global-prod.tfvars\" -var-file=\"../global.tfvars\" -var-file=\"prod.tfvars\"\ngotf\u003e TF_CLI_ARGS_refresh=-var-file=\"../global-prod.tfvars\" -var-file=\"../global.tfvars\" -var-file=\"prod.tfvars\"\ngotf\u003e TF_VAR_foo=42\ngotf\u003e TF_VAR_var_from_env_file=prod-env\ngotf\u003e TF_VAR_mapvar={\n  entry1 = {\n    value1 = testvalue1\n    value2 = true\n  }\n  entry2 = {\n    value1 = testvalue2\n    value2 = false\n  }\n}\ngotf\u003e TF_VAR_state_key=networking\ngotf\u003e BAR=barvalue\ngotf\u003e TF_CLI_ARGS_destroy=-var-file=\"../global-prod.tfvars\" -var-file=\"../global.tfvars\" -var-file=\"prod.tfvars\"\ngotf\u003e TF_VAR_templated_var=myval\ngotf\u003e TF_VAR_module_dir=01_networking\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcraftypath%2Fgotf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcraftypath%2Fgotf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcraftypath%2Fgotf/lists"}