diff --git a/README.md b/README.md index f04e5c6b..e5b5475f 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,15 @@ version = "0.11.3" 3. Run the command `tfswitch` in the same directory as your `.tfswitchrc` #### *Instead of a `.tfswitchrc` file, a `.terraform-version` file may be used for compatibility with [`tfenv`](https://github.com/tfutils/tfenv#terraform-version-file) and other tools which use it* + +### Use terragrunt.hcl file +If a terragrunt.hcl file with the terraform constrain is included in the current directory, it should automatically download or switch to that terraform version. For example, the following should automatically switch terraform to the lastest version 0.13: +```ruby +terragrunt_version_constraint = ">= 0.26, < 0.27" +terraform_version_constraint = ">= 0.13, < 0.14" +... +``` + ## Automation **Automatically switch with bash** diff --git a/go.mod b/go.mod index 99932fc4..4f92aa29 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ require ( github.com/chzyer/logex v1.1.10 // indirect github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3 // indirect github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect + github.com/hashicorp/hcl/v2 v2.10.0 // indirect + github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 // indirect github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/kiranjthomas/terraform-config-inspect v0.0.0-20191120205521-a1d709eb2824 github.com/lunixbochs/vtclean v0.0.0-20170504063817-d14193dfc626 // indirect diff --git a/go.sum b/go.sum index 99faf702..c00e4382 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -53,10 +55,13 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -66,8 +71,12 @@ github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1: github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl/v2 v2.10.0 h1:1S1UnuhDGlv3gRFV4+0EdwB+znNP5HmcGbIqwnSCByg= +github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/hcl2 v0.0.0-20190821123243-0c888d1241f6 h1:JImQpEeUQ+0DPFMaWzLA0GdUNPaUlCXLpfiqkSZBUfc= github.com/hashicorp/hcl2 v0.0.0-20190821123243-0c888d1241f6/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= +github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 h1:PFfGModn55JA0oBsvFghhj0v93me+Ctr3uHC/UmFAls= +github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -158,10 +167,16 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/zclconf/go-cty v1.0.0 h1:EWtv3gKe2wPLIB9hQRQJa7k/059oIfAqcEkCNnaVckk= github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -180,6 +195,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -199,12 +216,15 @@ golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/lib/install.go b/lib/install.go index c3794d29..dde1e5b3 100644 --- a/lib/install.go +++ b/lib/install.go @@ -91,6 +91,11 @@ func Install(tfversion string, binPath string) { goarch := runtime.GOARCH goos := runtime.GOOS + // TODO: Workaround for macos arm64 since terraform doesn't have a binary for it yet + if goos == "darwin" && goarch == "arm64" { + goarch = "amd64" + } + /* check if selected version already downloaded */ fileExist := CheckFileExist(installLocation + installVersion + tfversion) diff --git a/main.go b/main.go index 739e77ba..2842bbaa 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ package main /* -* Version 0.6.0 +* Version 0.12.0 * Compatible with Mac OS X AND other LINUX OS ONLY */ @@ -28,6 +28,8 @@ import ( // original hashicorp upstream have broken dependencies, so using fork as workaround // TODO: move back to upstream "github.com/Masterminds/semver" + "github.com/hashicorp/hcl2/gohcl" + "github.com/hashicorp/hcl2/hclparse" "github.com/kiranjthomas/terraform-config-inspect/tfconfig" "github.com/mitchellh/go-homedir" @@ -47,15 +49,16 @@ const ( tfvFilename = ".terraform-version" rcFilename = ".tfswitchrc" tomlFilename = ".tfswitch.toml" + tgHclFilename = "terragrunt.hcl" ) -var version = "0.11.0\n" +var version = "0.12.0\n" func main() { custBinPath := getopt.StringLong("bin", 'b', defaultBin, "Custom binary path. Ex: /Users/username/bin/terraform") listAllFlag := getopt.BoolLong("list-all", 'l', "List all versions of terraform - including beta and rc") latestPre := getopt.StringLong("latest-pre", 'p', defaultLatest, "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") - latestStable := getopt.StringLong("latest-stable", 's', defaultLatest, "Latest implicit version. Ex: tfswitch --latest 0.13 downloads 0.13.5 (latest)") + latestStable := getopt.StringLong("latest-stable", 's', defaultLatest, "Latest implicit version. Ex: tfswitch --latest-stable 0.13 downloads 0.13.7 (latest)") latestFlag := getopt.BoolLong("latest", 'u', "Get latest stable version") versionFlag := getopt.BoolLong("version", 'v', "Displays the version of tfswitch") helpFlag := getopt.BoolLong("help", 'h', "Displays help message") @@ -80,6 +83,7 @@ func main() { RCFile := dir + fmt.Sprintf("/%s", rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose) TOMLConfigFile := dir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) HomeTOMLConfigFile := homedir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in home directory (option to specify bin directory) + TGHACLFile := dir + fmt.Sprintf("/%s", tgHclFilename) //settings for terragrunt.hcl file in current directory (option to specify bin directory) switch { case *versionFlag: @@ -143,6 +147,9 @@ func main() { tfversion := os.Getenv("TF_VERSION") fmt.Printf("Terraform version environment variable: %s\n", tfversion) installVersion(tfversion, custBinPath) + /* if terragrunt.hcl file found (IN ADDITION TO A TOML FILE) */ + case fileExists(TGHACLFile) && len(args) == 0: + installTGHclFile(&TGHACLFile, &binPath) // if no arg is provided - but toml file is provided case version != "": installVersion(version, &binPath) @@ -189,6 +196,10 @@ func main() { case checkTFModuleFileExist(dir) && len(args) == 0: installTFProvidedModule(dir, custBinPath) + /* if terragrunt.hcl file found */ + case fileExists(TGHACLFile) && len(args) == 0: + installTGHclFile(&TGHACLFile, custBinPath) + /* if Terraform Version environment variable is set */ case checkTFEnvExist() && len(args) == 0: tfversion := os.Getenv("TF_VERSION") @@ -238,12 +249,14 @@ func installVersion(arg string, custBinPath *string) { lib.Install(requestedVersion, *custBinPath) } else { fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") + os.Exit(1) } } else { printInvalidTFVersion() fmt.Println("Args must be a valid terraform version") usageMessage() + os.Exit(1) } } @@ -373,14 +386,20 @@ func installOption(listAll bool, custBinPath *string) { // install when tf file is provided func installTFProvidedModule(dir string, custBinPath *string) { - tfversion := "" + fmt.Printf("Reading required version from terraform file") module, _ := tfconfig.LoadModule(dir) - tfconstraint := module.RequiredCore[0] //we skip duplicated definitions and use only first one + tfconstraint := module.RequiredCore[0] //we skip duplicated definitions and use only first one + installFromConstraint(&tfconstraint, custBinPath) +} + +// install using a version constraint +func installFromConstraint(tfconstraint *string, custBinPath *string) { + tfversion := "" listAll := true //set list all true - all versions including beta and rc will be displayed tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions - fmt.Printf("Reading required version from terraform file, constraint: %s\n", tfconstraint) + fmt.Printf("Reading required version from constraint: %s\n", *tfconstraint) - constrains, err := semver.NewConstraint(tfconstraint) //NewConstraint returns a Constraints instance that a Version instance can be checked against + constrains, err := semver.NewConstraint(*tfconstraint) //NewConstraint returns a Constraints instance that a Version instance can be checked against if err != nil { fmt.Printf("Error parsing constraint: %s\nPlease check constrain syntax on terraform file.\n", err) fmt.Println() @@ -415,3 +434,21 @@ func installTFProvidedModule(dir string, custBinPath *string) { fmt.Println("No version found to match constraint. Follow the README.md instructions for setup. https://github.com/warrensbox/terraform-switcher/blob/master/README.md") os.Exit(1) } + +// Install using version constraint from terragrunt file +func installTGHclFile(tgFile *string, custBinPath *string) { + fmt.Printf("Terragrunt file found: %s\n", *tgFile) + parser := hclparse.NewParser() + file, diags := parser.ParseHCLFile(*tgFile) //use hcl parser to parse HCL file + if diags.HasErrors() { + fmt.Println("Unable to parse HCL file") + os.Exit(1) + } + var version terragruntVersionConstraints + gohcl.DecodeBody(file.Body, nil, &version) + installFromConstraint(&version.TerraformVersionConstraint, custBinPath) +} + +type terragruntVersionConstraints struct { + TerraformVersionConstraint string `hcl:"terraform_version_constraint"` +} diff --git a/test-data/test_terragrunt_hcl/terragrunt.hcl b/test-data/test_terragrunt_hcl/terragrunt.hcl new file mode 100644 index 00000000..7fb80f2f --- /dev/null +++ b/test-data/test_terragrunt_hcl/terragrunt.hcl @@ -0,0 +1,16 @@ +include { + path = "${find_in_parent_folders()}" +} + +terraform { + source = "..." + + extra_arguments "variables" { + commands = get_terraform_commands_that_need_vars() + } +} + inputs = merge( + jsondecode(file("${find_in_parent_folders("general.tfvars")}")) +) + +terraform_versin_constraint=">= 0.13, < 0.14" \ No newline at end of file diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh index 1715122b..7559892d 100755 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -72,12 +72,12 @@ darwin_amd64) ;; darwin_arm) mkerrors="$mkerrors" - mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" + mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; darwin_arm64) mkerrors="$mkerrors -m64" - mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" + mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; dragonfly_amd64) diff --git a/version b/version index 8cbd132a..94d73482 100644 --- a/version +++ b/version @@ -1 +1 @@ -RELEASE_VERSION=0.11 \ No newline at end of file +RELEASE_VERSION=0.12 \ No newline at end of file diff --git a/www/docs/Quick-Start.md b/www/docs/Quick-Start.md index 0ca136e3..8d08cf07 100644 --- a/www/docs/Quick-Start.md +++ b/www/docs/Quick-Start.md @@ -81,6 +81,14 @@ version = "0.11.3" *Instead of a `.tfswitchrc` file, a `.terraform-version` file may be used for compatibility with [`tfenv`](https://github.com/tfutils/tfenv#terraform-version-file) and other tools which use it* +### Use terragrunt.hcl file +If a terragrunt.hcl file with the terraform constrain is included in the current directory, it should automatically download or switch to that terraform version. For example, the following should automatically switch terraform to the lastest version 0.13: +```ruby +terragrunt_version_constraint = ">= 0.26, < 0.27" +terraform_version_constraint = ">= 0.13, < 0.14" +... +``` + **Automatically switch with bash** Add the following to the end of your `~/.bashrc` file: