Skip to content

Commit

Permalink
Allows setting terraform_binary in terragrunt.hcl
Browse files Browse the repository at this point in the history
Related to gruntwork-io#743
  • Loading branch information
Eugene Dementiev committed Aug 7, 2019
1 parent b398b48 commit ccc111f
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 39 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2152,6 +2152,12 @@ If you run `terragrunt hclfmt` at the `root`, this will update:
Additionally, there's a flag `--terragrunt-check`. It allows to validating if files are properly formatted. It does not
rewrite files and in case of invalid format, it will return an error with exit status 0.
#### terraform_binary
The terragrunt `terraform_binary` string option can be used to override the default terraform binary path (which is `terraform`).
The precedence is as follows: `--terragrunt-tfpath` command line option -> `TERRAGRUNT_TFPATH` env variable -> `terragrunt.hcl` in the module directory -> included `terragrunt.hcl`
### Clearing the Terragrunt cache
Terragrunt creates a `.terragrunt-cache` folder in the current working directory as its scratch directory. It downloads
Expand Down
13 changes: 13 additions & 0 deletions _docs/migration_guides/upgrading_to_terragrunt_0.19.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ to Terragrunt 0.19.x and newer:
1. [Use first-class expressions](#use-first-class-expressions)
1. [Check attributes vs blocks usage](#check-attributes-vs-blocks-usage)
1. [Rename a few built-in functions ](#rename-a-few-built-in-functions)
1. [Use terraform \<0.12](#use-older-terraform)

Check out [this PR in the terragrunt-infrastructure-live-example
repo](https://github.com/gruntwork-io/terragrunt-infrastructure-live-example/pull/17) for an example of what the code
Expand Down Expand Up @@ -272,3 +273,15 @@ Two built-in functions were renamed:
1. `get_parent_tfvars_dir()` is now called `get_parent_terragrunt_dir()`.

Make sure to make the corresponding updates in your `terragrunt.hcl` file!

### Use older Terraform

Although it is not officiall supported and not tested, it is still possible to use terraform<0.12 with terragrunt >=0.19.

Just install a different version of terraform into a directory of your choice outside of `PATH` and specify path to the binary in `terragrunt.hcl` as `terraform_binary`:

```hcl
terraform_binary = "~/bin/terraform-v11/terraform"
```
2 changes: 1 addition & 1 deletion cli/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func parseTerragruntOptionsFromArgs(args []string, writer, errWriter io.Writer)
return nil, err
}
if terraformPath == "" {
terraformPath = "terraform"
terraformPath = options.TERRAFORM_DEFAULT_PATH
}

terraformSource, err := parseStringArg(args, OPT_TERRAGRUNT_SOURCE, os.Getenv("TERRAGRUNT_SOURCE"))
Expand Down
9 changes: 8 additions & 1 deletion cli/cli_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ AUTHOR(S):
var MODULE_REGEX = regexp.MustCompile(`module[[:blank:]]+".+"`)

// This uses the constraint syntax from https://github.com/hashicorp/go-version
// This version of Terragrunt only works with Terraform 0.12.0 and above
// This version of Terragrunt was tested to work with Terraform 0.12.0 and above only
const DEFAULT_TERRAFORM_VERSION_CONSTRAINT = ">= v0.12.0"

const TERRAFORM_EXTENSION_GLOB = "*.tf"
Expand Down Expand Up @@ -241,10 +241,17 @@ func runTerragrunt(terragruntOptions *options.TerragruntOptions) error {
}

terragruntConfig, err := config.ReadTerragruntConfig(terragruntOptions)

if err != nil {
return err
}

if terragruntOptions.TerraformPath == options.TERRAFORM_DEFAULT_PATH { // not changed from default
if terragruntConfig.TerraformBinary != "" {
terragruntOptions.TerraformPath = terragruntConfig.TerraformBinary
}
}

if terragruntConfig.Skip {
terragruntOptions.Logger.Printf("Skipping terragrunt module %s due to skip = true.",
terragruntOptions.TerragruntConfigPath)
Expand Down
42 changes: 26 additions & 16 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ const DefaultTerragruntConfigPath = "terragrunt.hcl"

// TerragruntConfig represents a parsed and expanded configuration
type TerragruntConfig struct {
Terraform *TerraformConfig
RemoteState *remote.RemoteState
Dependencies *ModuleDependencies
PreventDestroy bool
Skip bool
IamRole string
Inputs map[string]interface{}
Locals map[string]interface{}
Terraform *TerraformConfig
TerraformBinary string
RemoteState *remote.RemoteState
Dependencies *ModuleDependencies
PreventDestroy bool
Skip bool
IamRole string
Inputs map[string]interface{}
Locals map[string]interface{}
}

func (conf *TerragruntConfig) String() string {
Expand All @@ -39,14 +40,15 @@ func (conf *TerragruntConfig) String() string {
// terragruntConfigFile represents the configuration supported in a Terragrunt configuration file (i.e.
// terragrunt.hcl)
type terragruntConfigFile struct {
Terraform *TerraformConfig `hcl:"terraform,block"`
Inputs *cty.Value `hcl:"inputs,attr"`
Include *IncludeConfig `hcl:"include,block"`
RemoteState *remoteStateConfigFile `hcl:"remote_state,block"`
Dependencies *ModuleDependencies `hcl:"dependencies,block"`
PreventDestroy *bool `hcl:"prevent_destroy,attr"`
Skip *bool `hcl:"skip,attr"`
IamRole *string `hcl:"iam_role,attr"`
Terraform *TerraformConfig `hcl:"terraform,block"`
TerraformBinary *string `hcl:"terraform_binary,attr"`
Inputs *cty.Value `hcl:"inputs,attr"`
Include *IncludeConfig `hcl:"include,block"`
RemoteState *remoteStateConfigFile `hcl:"remote_state,block"`
Dependencies *ModuleDependencies `hcl:"dependencies,block"`
PreventDestroy *bool `hcl:"prevent_destroy,attr"`
Skip *bool `hcl:"skip,attr"`
IamRole *string `hcl:"iam_role,attr"`

// This struct is used for validating and parsing the entire terragrunt config. Since locals are evaluated in a
// completely separate cycle, it should not be evaluated here. Otherwise, we can't support self referencing other
Expand Down Expand Up @@ -433,6 +435,10 @@ func mergeConfigWithIncludedConfig(config *TerragruntConfig, includedConfig *Ter
includedConfig.IamRole = config.IamRole
}

if config.TerraformBinary != "" {
includedConfig.TerraformBinary = config.TerraformBinary
}

if config.Inputs != nil {
includedConfig.Inputs = mergeInputs(config.Inputs, includedConfig.Inputs)
}
Expand Down Expand Up @@ -586,6 +592,10 @@ func convertToTerragruntConfig(terragruntConfigFromFile *terragruntConfigFile, c
terragruntConfig.Terraform = terragruntConfigFromFile.Terraform
terragruntConfig.Dependencies = terragruntConfigFromFile.Dependencies

if terragruntConfigFromFile.TerraformBinary != nil {
terragruntConfig.TerraformBinary = *terragruntConfigFromFile.TerraformBinary
}

if terragruntConfigFromFile.PreventDestroy != nil {
terragruntConfig.PreventDestroy = *terragruntConfigFromFile.PreventDestroy
}
Expand Down
45 changes: 24 additions & 21 deletions options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ var TERRAFORM_COMMANDS_WITH_SUBCOMMAND = []string{

const DEFAULT_MAX_FOLDERS_TO_CHECK = 100

// TERRAFORM_DEFAULT_PATH just takes terraform from the path
const TERRAFORM_DEFAULT_PATH = "terraform"

const TerragruntCacheDir = ".terragrunt-cache"

// TerragruntOptions represents options that configure the behavior of the Terragrunt program
Expand Down Expand Up @@ -124,7 +127,7 @@ func NewTerragruntOptions(terragruntConfigPath string) (*TerragruntOptions, erro

return &TerragruntOptions{
TerragruntConfigPath: terragruntConfigPath,
TerraformPath: "terraform",
TerraformPath: TERRAFORM_DEFAULT_PATH,
TerraformCommand: "",
AutoInit: true,
NonInteractive: false,
Expand All @@ -137,16 +140,16 @@ func NewTerragruntOptions(terragruntConfigPath string) (*TerragruntOptions, erro
DownloadDir: downloadDir,
IgnoreDependencyErrors: false,
IgnoreExternalDependencies: false,
Writer: os.Stdout,
ErrWriter: os.Stderr,
MaxFoldersToCheck: DEFAULT_MAX_FOLDERS_TO_CHECK,
AutoRetry: true,
MaxRetryAttempts: DEFAULT_MAX_RETRY_ATTEMPTS,
Sleep: DEFAULT_SLEEP,
RetryableErrors: util.CloneStringList(RETRYABLE_ERRORS),
ExcludeDirs: []string{},
IncludeDirs: []string{},
Check: false,
Writer: os.Stdout,
ErrWriter: os.Stderr,
MaxFoldersToCheck: DEFAULT_MAX_FOLDERS_TO_CHECK,
AutoRetry: true,
MaxRetryAttempts: DEFAULT_MAX_RETRY_ATTEMPTS,
Sleep: DEFAULT_SLEEP,
RetryableErrors: util.CloneStringList(RETRYABLE_ERRORS),
ExcludeDirs: []string{},
IncludeDirs: []string{},
Check: false,
RunTerragrunt: func(terragruntOptions *TerragruntOptions) error {
return errors.WithStackTrace(RunTerragruntCommandNotSet)
},
Expand Down Expand Up @@ -205,16 +208,16 @@ func (terragruntOptions *TerragruntOptions) Clone(terragruntConfigPath string) *
IamRole: terragruntOptions.IamRole,
IgnoreDependencyErrors: terragruntOptions.IgnoreDependencyErrors,
IgnoreExternalDependencies: terragruntOptions.IgnoreExternalDependencies,
Writer: terragruntOptions.Writer,
ErrWriter: terragruntOptions.ErrWriter,
MaxFoldersToCheck: terragruntOptions.MaxFoldersToCheck,
AutoRetry: terragruntOptions.AutoRetry,
MaxRetryAttempts: terragruntOptions.MaxRetryAttempts,
Sleep: terragruntOptions.Sleep,
RetryableErrors: util.CloneStringList(terragruntOptions.RetryableErrors),
ExcludeDirs: terragruntOptions.ExcludeDirs,
IncludeDirs: terragruntOptions.IncludeDirs,
RunTerragrunt: terragruntOptions.RunTerragrunt,
Writer: terragruntOptions.Writer,
ErrWriter: terragruntOptions.ErrWriter,
MaxFoldersToCheck: terragruntOptions.MaxFoldersToCheck,
AutoRetry: terragruntOptions.AutoRetry,
MaxRetryAttempts: terragruntOptions.MaxRetryAttempts,
Sleep: terragruntOptions.Sleep,
RetryableErrors: util.CloneStringList(terragruntOptions.RetryableErrors),
ExcludeDirs: terragruntOptions.ExcludeDirs,
IncludeDirs: terragruntOptions.IncludeDirs,
RunTerragrunt: terragruntOptions.RunTerragrunt,
}
}

Expand Down

0 comments on commit ccc111f

Please sign in to comment.