From 0cf5b1c3ad3e79214907ea0f457d70b75fc2bdae Mon Sep 17 00:00:00 2001 From: "Fabiano V. Santos" Date: Wed, 31 Mar 2021 07:37:06 -0300 Subject: [PATCH 1/8] [tg-hcl] Support for terragrunt files --- README.md | 9 +++++++++ main.go | 44 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f04e5c6b..7912228c 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: +```ruby +terragrunt_version_constraint = ">= 0.26, < 0.27" +terraform_version_constraint = ">= 0.13, < 0.14" +... +``` + ## Automation **Automatically switch with bash** diff --git a/main.go b/main.go index 739e77ba..c807a265 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ import ( "io/ioutil" "log" "os" + "regexp" "sort" "strings" @@ -47,6 +48,7 @@ const ( tfvFilename = ".terraform-version" rcFilename = ".tfswitchrc" tomlFilename = ".tfswitch.toml" + tgHclFilename = "terragrunt.hcl" ) var version = "0.11.0\n" @@ -80,6 +82,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 +146,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 +195,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") @@ -373,14 +383,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 +431,23 @@ 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) + content := retrieveFileContents(*tgFile) + var constraint = "" + + for _, line := range strings.Split(content, "\n") { + regex, _ := regexp.Compile(`^terraform_version_constraint\s+=\s+"(?P.*)".*`) + + if regex.MatchString(line) { + res := regex.FindStringSubmatch(line) + constraint = res[1] + installFromConstraint(&constraint, custBinPath) + } + } + + 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) +} From 15eac767608b6a2f56fd5fafee2e633636cf29c5 Mon Sep 17 00:00:00 2001 From: "Fabiano V. Santos" Date: Fri, 23 Apr 2021 07:53:08 -0300 Subject: [PATCH 2/8] [tg-hcl] Fix regex compile moved out from loop --- main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.go b/main.go index c807a265..5b872c83 100644 --- a/main.go +++ b/main.go @@ -436,11 +436,10 @@ func installFromConstraint(tfconstraint *string, custBinPath *string) { func installTGHclFile(tgFile *string, custBinPath *string) { fmt.Printf("Terragrunt file found: %s\n", *tgFile) content := retrieveFileContents(*tgFile) + regex, _ := regexp.Compile(`^terraform_version_constraint\s+=\s+"(?P.*)".*`) var constraint = "" for _, line := range strings.Split(content, "\n") { - regex, _ := regexp.Compile(`^terraform_version_constraint\s+=\s+"(?P.*)".*`) - if regex.MatchString(line) { res := regex.FindStringSubmatch(line) constraint = res[1] From 84800493f924c0bd73a89ca537adc6f0205f4d45 Mon Sep 17 00:00:00 2001 From: chrispruitt Date: Thu, 29 Apr 2021 16:01:50 -0500 Subject: [PATCH 3/8] temp fix for macos on arm64 due to M1 chip --- lib/install.go | 5 +++++ vendor/golang.org/x/sys/unix/mkall.sh | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) 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/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) From 6bc7a1d186114edf197df6ef44a36e3a89f5ac19 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Tue, 4 May 2021 21:24:21 -0500 Subject: [PATCH 4/8] added exit code 1 when version format is invalid --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 5b872c83..74913ff4 100644 --- a/main.go +++ b/main.go @@ -254,6 +254,7 @@ func installVersion(arg string, custBinPath *string) { printInvalidTFVersion() fmt.Println("Args must be a valid terraform version") usageMessage() + os.Exit(1) } } From 9329114fa8c2a9221700d1f631ed6827e18e2c9a Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 5 May 2021 16:35:28 -0500 Subject: [PATCH 5/8] Use HCL parser to parse terragrunt hcl --- go.mod | 2 ++ go.sum | 20 +++++++++++++++ main.go | 26 ++++++++++---------- test-data/test_terragrunt_hcl/terragrunt.hcl | 16 ++++++++++++ 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 test-data/test_terragrunt_hcl/terragrunt.hcl 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/main.go b/main.go index 74913ff4..8b631df8 100644 --- a/main.go +++ b/main.go @@ -22,13 +22,14 @@ import ( "io/ioutil" "log" "os" - "regexp" "sort" "strings" // 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" @@ -436,18 +437,17 @@ func installFromConstraint(tfconstraint *string, custBinPath *string) { // Install using version constraint from terragrunt file func installTGHclFile(tgFile *string, custBinPath *string) { fmt.Printf("Terragrunt file found: %s\n", *tgFile) - content := retrieveFileContents(*tgFile) - regex, _ := regexp.Compile(`^terraform_version_constraint\s+=\s+"(?P.*)".*`) - var constraint = "" - - for _, line := range strings.Split(content, "\n") { - if regex.MatchString(line) { - res := regex.FindStringSubmatch(line) - constraint = res[1] - installFromConstraint(&constraint, custBinPath) - } + 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) +} - 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) +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 From aa84338230801bf0a16d776f4fa5197d1cd1a7de Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 5 May 2021 16:36:40 -0500 Subject: [PATCH 6/8] bumping version to 12 --- main.go | 4 ++-- version | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 8b631df8..b4f6c78a 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 */ @@ -52,7 +52,7 @@ const ( 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") 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 From 24db808b7156548296bef74fcd2905fd6b275777 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 5 May 2021 19:17:39 -0500 Subject: [PATCH 7/8] fix error code --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index b4f6c78a..1ce7f77f 100644 --- a/main.go +++ b/main.go @@ -249,6 +249,7 @@ 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 { From 6b674f8fae1e8e16509e3b56c1342efd10d1a6d4 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 5 May 2021 19:25:56 -0500 Subject: [PATCH 8/8] Added documentation on how to use terragrunt hcl --- README.md | 2 +- main.go | 2 +- www/docs/Quick-Start.md | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7912228c..e5b5475f 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ 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: +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" diff --git a/main.go b/main.go index 1ce7f77f..2842bbaa 100644 --- a/main.go +++ b/main.go @@ -58,7 +58,7 @@ 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") 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: