diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index d3de0a3..41e505d 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -16,4 +16,4 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: - version: v1.41 + version: v1.42 diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..db67a81 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,66 @@ +--- + +run: + tests: false + +linters: + enable: + - asciicheck + - bodyclose + - cyclop + - whitespace + - wastedassign + - unparam + - tparallel + - thelper + - tagliatelle + - exportloopref + - dupl + - goconst + - ifshort + - importas + - goimports + - gofumpt + - gocritic + - revive + - depguard + - dogsled + - durationcheck + - errname + - errorlint + - exhaustive + - forcetypeassert + - funlen + - gochecknoglobals + - gochecknoinits + - gocognit + - gocyclo + - godox + - gofmt + - goheader + - gomoddirectives + - gomodguard + - goprintffuncname + - makezero + - misspell + - nakedret + - nilerr + - nolintlint + - prealloc + - predeclared + - promlinter + - rowserrcheck + - sqlclosecheck + - stylecheck + - testpackage + - unconvert + disable: + - forbidigo # need to wait for log rework + - paralleltest # need to wait for tests rework + + # these ones should be enabled later with dedicated PR to fix them + - gosec + - gomnd + - noctx + - goerr113 + - nestif diff --git a/Makefile b/Makefile index 9bebc0d..086cf21 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ EXE := simple-tfswitch -PKG := github.com/jb-abbadie/simple-tfswitch +PKG := github.com/terraform-tools/simple-tfswitch VER := $(shell cat version) PATH := build:$(PATH) GOOS ?= $(shell go env GOOS) diff --git a/go.mod b/go.mod index ff3929d..448841f 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,20 @@ -module github.com/jb-abbadie/simple-tfswitch +module github.com/terraform-tools/simple-tfswitch -go 1.16 +go 1.17 require ( github.com/Masterminds/semver v1.5.0 - github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/terraform-config-inspect v0.0.0-20210625153042-09f34846faab github.com/rogpeppe/go-internal v1.8.0 - github.com/zclconf/go-cty v1.8.0 // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect +) + +require ( + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/google/go-cmp v0.5.6 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/hcl/v2 v2.10.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/zclconf/go-cty v1.9.1 // indirect + golang.org/x/text v0.3.7 // indirect ) diff --git a/go.sum b/go.sum index 3f1c9ae..52fe4de 100644 --- a/go.sum +++ b/go.sum @@ -1,42 +1,52 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/protobuf v1.1.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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 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/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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.0.0 h1:efQznTz+ydmQXq3BOnRa3AXzvCeTq1P4dKj/z5GLlY8= github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= +github.com/hashicorp/hcl/v2 v2.10.1 h1:h4Xx4fsrRE26ohAk/1iGF/JBqRQbyUqu5Lvj60U54ys= +github.com/hashicorp/hcl/v2 v2.10.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/terraform-config-inspect v0.0.0-20210625153042-09f34846faab h1:P08dNG+lM+gjaaMk8SsMi/mIPs8z7jrkEmnpcCwy/U0= github.com/hashicorp/terraform-config-inspect v0.0.0-20210625153042-09f34846faab/go.mod h1:Z0Nnk4+3Cy89smEbrq+sl1bxc9198gIP4I7wcQF6Kqs= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -47,8 +57,11 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac 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/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.9.1 h1:viqrgQwFl5UpSxc046qblj78wZXVDFnSOufaOTER+cc= +github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -59,12 +72,14 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/lib/common_test.go b/lib/common_test.go index b35e82b..f9c6442 100644 --- a/lib/common_test.go +++ b/lib/common_test.go @@ -14,7 +14,7 @@ func checkFileExist(file string) bool { func createFile(path string) { // detect if file exists - var _, err = os.Stat(path) + _, err := os.Stat(path) // create file if not exists if os.IsNotExist(err) { @@ -32,7 +32,7 @@ func createFile(path string) { func createDirIfNotExist(dir string) { if _, err := os.Stat(dir); os.IsNotExist(err) { log.Printf("Creating directory for terraform: %v", dir) - err = os.MkdirAll(dir, 0755) + err = os.MkdirAll(dir, 0o755) if err != nil { fmt.Printf("Unable to create directory for terraform: %v", dir) panic(err) diff --git a/lib/download.go b/lib/download.go index 348373f..c87e265 100644 --- a/lib/download.go +++ b/lib/download.go @@ -23,8 +23,8 @@ func DownloadFromURL(installLocation string, url string) (string, error) { defer response.Body.Close() if response.StatusCode != 200 { - //Sometimes hashicorp terraform file names are not consistent - //For example 0.12.0-alpha4 naming convention in the release repo is not consistent + // Sometimes hashicorp terraform file names are not consistent + // For example 0.12.0-alpha4 naming convention in the release repo is not consistent return "", fmt.Errorf("[Error] : Unable to download from %s", url) } diff --git a/lib/download_test.go b/lib/download_test.go index fbc620d..57f0dd5 100644 --- a/lib/download_test.go +++ b/lib/download_test.go @@ -9,12 +9,11 @@ import ( "path/filepath" "testing" - lib "github.com/jb-abbadie/simple-tfswitch/lib" + lib "github.com/terraform-tools/simple-tfswitch/lib" ) // TestDownloadFromURL_FileNameMatch : Check expected filename exist when downloaded func TestDownloadFromURL_FileNameMatch(t *testing.T) { - hashiURL := "https://releases.hashicorp.com/terraform/" installVersion := "terraform_" installPath := getInstallLocation(".terraform.versions_test") @@ -32,7 +31,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { // create /.terraform.versions_test/ directory to store code if _, err := os.Stat(installLocation); os.IsNotExist(err) { log.Printf("Creating directory for terraform: %v", installLocation) - err = os.MkdirAll(installLocation, 0755) + err = os.MkdirAll(installLocation, 0o755) if err != nil { fmt.Printf("Unable to create directory for terraform: %v", installLocation) panic(err) @@ -88,7 +87,6 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { // TestDownloadFromURL_FileExist : Check expected file exist when downloaded func TestDownloadFromURL_FileExist(t *testing.T) { - hashiURL := "https://releases.hashicorp.com/terraform/" installVersion := "terraform_" installPath := getInstallLocation(".terraform.versions_test") @@ -106,7 +104,7 @@ func TestDownloadFromURL_FileExist(t *testing.T) { // create /.terraform.versions_test/ directory to store code if _, err := os.Stat(installLocation); os.IsNotExist(err) { log.Printf("Creating directory for terraform: %v", installLocation) - err = os.MkdirAll(installLocation, 0755) + err = os.MkdirAll(installLocation, 0o755) if err != nil { fmt.Printf("Unable to create directory for terraform: %v", installLocation) panic(err) @@ -162,7 +160,6 @@ func TestDownloadFromURL_FileExist(t *testing.T) { // TestInvalidURL : Invalid url should throw an error func TestInvalidURL(t *testing.T) { - hashiURL := "https://releases.hashicorp.com/terraform/" installVersion := "terraform_" installPath := getInstallLocation(".terraform.versions_test") @@ -181,7 +178,7 @@ func TestInvalidURL(t *testing.T) { // create /.terraform.versions_test/ directory to store code if _, err := os.Stat(installLocation); os.IsNotExist(err) { log.Printf("Creating directory for terraform: %v\n", installLocation) - err = os.MkdirAll(installLocation, 0755) + err = os.MkdirAll(installLocation, 0o755) if err != nil { fmt.Printf("Unable to create directory for terraform: %v\n", installLocation) panic(err) @@ -189,7 +186,7 @@ func TestInvalidURL(t *testing.T) { } url := hashiURL + invalidVersion + "/" + installVersion + invalidVersion + macOS - //expectedFile :=filepath.Join(usr.HomeDir, installPath, installVersion + invalidVersion + macOS) + // expectedFile :=filepath.Join(usr.HomeDir, installPath, installVersion + invalidVersion + macOS) _, errDownload := lib.DownloadFromURL(installLocation, url) if errDownload != nil { @@ -202,7 +199,6 @@ func TestInvalidURL(t *testing.T) { // TestDownloadFromURL_Valid : Test if https://releases.hashicorp.com/terraform/ is still valid func TestDownloadFromURL_Valid(t *testing.T) { - hashiURL := "https://releases.hashicorp.com/terraform/" url, err := url.ParseRequestURI(hashiURL) diff --git a/lib/files.go b/lib/files.go index 020dc42..948b931 100644 --- a/lib/files.go +++ b/lib/files.go @@ -10,8 +10,7 @@ import ( // RenameFile : rename file name func RenameFile(src string, dest string) { - err := os.Rename(src, dest) - if err != nil { + if err := os.Rename(src, dest); err != nil { fmt.Println(err) return } @@ -21,7 +20,6 @@ func RenameFile(src string, dest string) { func RemoveFiles(src string) { files, err := filepath.Glob(src) if err != nil { - panic(err) } for _, f := range files { @@ -40,17 +38,15 @@ func CheckFileExist(file string) bool { // Unzip will decompress a zip archive, moving all files and folders // within the zip file (parameter 1) to an output directory (parameter 2). func Unzip(src string, dest string) ([]string, error) { - - var filenames []string - r, err := zip.OpenReader(src) if err != nil { - return filenames, err + return []string{}, err } defer r.Close() - for _, f := range r.File { + filenames := make([]string, 0, len(r.File)) + for _, f := range r.File { rc, err := f.Open() if err != nil { return filenames, err @@ -62,15 +58,12 @@ func Unzip(src string, dest string) ([]string, error) { filenames = append(filenames, fpath) if f.FileInfo().IsDir() { - // Make Folder err := os.MkdirAll(fpath, os.ModePerm) if err != nil { return []string{}, err } - } else { - // Make File if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { return filenames, err @@ -89,17 +82,16 @@ func Unzip(src string, dest string) ([]string, error) { if err != nil { return filenames, err } - } } return filenames, nil } -//CreateDirIfNotExist : create directory if directory does not exist +// CreateDirIfNotExist : create directory if directory does not exist func CreateDirIfNotExist(dir string) { if _, err := os.Stat(dir); os.IsNotExist(err) { fmt.Printf("Creating directory for terraform binary at: %v\n", dir) - err = os.MkdirAll(dir, 0755) + err = os.MkdirAll(dir, 0o755) if err != nil { fmt.Printf("Unable to create directory for terraform binary at: %v", dir) panic(err) @@ -107,9 +99,9 @@ func CreateDirIfNotExist(dir string) { } } -//CheckDirExist : check if directory exist -//dir=path to file -//return bool +// CheckDirExist : check if directory exist +// dir=path to file +// return bool func CheckDirExist(dir string) bool { if _, err := os.Stat(dir); os.IsNotExist(err) { return false diff --git a/lib/files_test.go b/lib/files_test.go index 8db7f00..3fc7915 100644 --- a/lib/files_test.go +++ b/lib/files_test.go @@ -10,7 +10,7 @@ import ( "strings" "testing" - "github.com/jb-abbadie/simple-tfswitch/lib" + "github.com/terraform-tools/simple-tfswitch/lib" ) // TestRenameFile : Create a file, check filename exist, diff --git a/lib/install.go b/lib/install.go index fbfa365..57e9e47 100644 --- a/lib/install.go +++ b/lib/install.go @@ -19,10 +19,6 @@ const ( lockFilePath = "/tmp/simple-tfswitch.lock" ) -var ( - installLocation = "/tmp" -) - // getInstallLocation : get location where the terraform binary will be installed, // will create a directory in the home location if it does not exist func getInstallLocation() string { @@ -42,28 +38,26 @@ func getInstallLocation() string { } /* set installation location */ - installLocation = filepath.Join(userCommon, installPath) + installLocation := filepath.Join(userCommon, installPath) /* Create local installation directory if it does not exist */ CreateDirIfNotExist(installLocation) return installLocation - } func WaitForLockFile() (unlock func()) { m := lockedfile.MutexAt(lockFilePath) unlock, err := m.Lock() if err != nil { - fmt.Printf("there was a problem while trying to aquire lockfile %v", lockFilePath) + fmt.Printf("there was a problem while trying to acquire lockfile %v", lockFilePath) os.Exit(1) } return unlock } -//Install : Install the provided version in the argument -func Install(tfversion string, mirrorURL string) string { - +// Install : Install the provided version in the argument +func Install(tfversion string, mirrorURL string) (string, error) { if !ValidVersionFormat(tfversion) { fmt.Printf("The provided terraform version format does not exist - %s. Try `tfswitch -l` to see all available versions.\n", tfversion) os.Exit(1) @@ -73,26 +67,21 @@ func Install(tfversion string, mirrorURL string) string { unlock := WaitForLockFile() defer unlock() - installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file + installLocation := getInstallLocation() // get installation location - this is where we will put our terraform binary file 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 */ installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, installVersion+tfversion)) fileExist := CheckFileExist(installFileVersionPath) /* if selected version already exist, */ if fileExist { - return installFileVersionPath + return installFileVersionPath, nil } - //if does not have slash - append slash + // if does not have slash - append slash hasSlash := strings.HasSuffix(mirrorURL, "/") if !hasSlash { mirrorURL = fmt.Sprintf("%s/", mirrorURL) @@ -105,16 +94,14 @@ func Install(tfversion string, mirrorURL string) string { /* If unable to download file from url, exit(1) immediately */ if errDownload != nil { - fmt.Println(errDownload) - os.Exit(1) + return "", errDownload } /* unzip the downloaded zipfile */ _, errUnzip := Unzip(zipFile, installLocation) if errUnzip != nil { fmt.Println("[Error] : Unable to unzip downloaded zip file") - log.Fatal(errUnzip) - os.Exit(1) + return "", errUnzip } /* rename unzipped file to terraform version name - terraform_x.x.x */ @@ -124,10 +111,10 @@ func Install(tfversion string, mirrorURL string) string { /* remove zipped file to clear clutter */ RemoveFiles(zipFile) - return installFileVersionPath + return installFileVersionPath, nil } -//ConvertExecutableExt : convert excutable with local OS extension +// ConvertExecutableExt : convert excutable with local OS extension func ConvertExecutableExt(fpath string) string { switch runtime.GOOS { case "windows": diff --git a/lib/install_test.go b/lib/install_test.go index 8b0ab2e..559e33b 100644 --- a/lib/install_test.go +++ b/lib/install_test.go @@ -13,7 +13,6 @@ func getInstallLocation(installPath string) string { } func TestInstall(t *testing.T) { - t.Run("User should exist", func(t *testing.T) { usr, errCurr := user.Current() diff --git a/lib/list_versions.go b/lib/list_versions.go index 35bf5a1..f9a4f7d 100644 --- a/lib/list_versions.go +++ b/lib/list_versions.go @@ -14,12 +14,11 @@ type tfVersionList struct { tflist []string } -//GetTFList : Get the list of available terraform version given the hashicorp url +// GetTFList : Get the list of available terraform version given the hashicorp url func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { - - result, error := GetTFURLBody(mirrorURL) - if error != nil { - return nil, error + result, err := GetTFURLBody(mirrorURL) + if err != nil { + return nil, err } var tfVersionList tfVersionList @@ -35,7 +34,7 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { for i := range result { if r.MatchString(result[i]) { str := r.FindString(result[i]) - trimstr := strings.Trim(str, "/") //remove "/" from /X.X.X/ + trimstr := strings.Trim(str, "/") // remove "/" from /X.X.X/ tfVersionList.tflist = append(tfVersionList.tflist, trimstr) } } @@ -45,14 +44,12 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { } return tfVersionList.tflist, nil - } -//GetTFURLBody : Get list of terraform versions from hashicorp releases +// GetTFURLBody : Get list of terraform versions from hashicorp releases func GetTFURLBody(mirrorURL string) ([]string, error) { - hasSlash := strings.HasSuffix(mirrorURL, "/") - if !hasSlash { //if does not have slash - append slash + if !hasSlash { // if does not have slash - append slash mirrorURL = fmt.Sprintf("%s/", mirrorURL) } resp, errURL := http.Get(mirrorURL) @@ -65,13 +62,12 @@ func GetTFURLBody(mirrorURL string) ([]string, error) { if resp.StatusCode != 200 { log.Printf("[Error] : Retrieving contents from url: %s", mirrorURL) - os.Exit(1) + return nil, fmt.Errorf("[Error] : Retrieving contents from url: %s", mirrorURL) } body, errBody := ioutil.ReadAll(resp.Body) if errBody != nil { log.Printf("[Error] : reading body: %v", errBody) - os.Exit(1) return nil, errBody } @@ -89,7 +85,6 @@ func GetTFURLBody(mirrorURL string) ([]string, error) { // For example: 0.1. 2 = invalid */ func ValidVersionFormat(version string) bool { - // Getting versions from body; should return match /X.X.X-@/ where X is a number,@ is a word character between a-z or A-Z // Follow https://semver.org/spec/v1.0.0-beta.html // Check regular expression at https://rubular.com/r/ju3PxbaSBALpJB diff --git a/lib/list_versions_test.go b/lib/list_versions_test.go index d3a49b2..36f41b3 100644 --- a/lib/list_versions_test.go +++ b/lib/list_versions_test.go @@ -5,7 +5,7 @@ import ( "reflect" "testing" - "github.com/jb-abbadie/simple-tfswitch/lib" + "github.com/terraform-tools/simple-tfswitch/lib" ) const ( @@ -14,7 +14,6 @@ const ( // TestGetTFList : Get list from hashicorp func TestGetTFList(t *testing.T) { - listAll := true list, _ := lib.GetTFList(hashiURL, listAll) @@ -37,13 +36,11 @@ func TestGetTFList(t *testing.T) { } else { t.Log("Write versions exist (expected)") } - } -//TestValidVersionFormat : test if func returns valid version format +// TestValidVersionFormat : test if func returns valid version format // more regex testing at https://rubular.com/r/UvWXui7EU2icSb func TestValidVersionFormat(t *testing.T) { - var version string version = "0.11.8" @@ -134,5 +131,4 @@ func TestValidVersionFormat(t *testing.T) { } else { log.Fatalf("Failed to verify version format: %s\n", version) } - } diff --git a/main.go b/main.go index 83f61ee..299fd6b 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "log" "os" @@ -10,7 +11,7 @@ import ( "github.com/Masterminds/semver" "github.com/hashicorp/terraform-config-inspect/tfconfig" - lib "github.com/jb-abbadie/simple-tfswitch/lib" + lib "github.com/terraform-tools/simple-tfswitch/lib" ) const ( @@ -26,9 +27,8 @@ func main() { } tfBinaryPath, err := installTFProvidedModule(dir, mirrorURL) - if err != nil { - fmt.Println("Error occured:", err) + fmt.Println("Error occurred:", err) } exitCode := runTerraform(tfBinaryPath, args[1:]...) @@ -47,20 +47,19 @@ func installTFProvidedModule(dir string, mirrorURL string) (string, error) { module, _ := tfconfig.LoadModule(dir) if len(module.RequiredCore) == 0 { - return "", fmt.Errorf("No required_versions found") + return "", fmt.Errorf("no required_versions found") } - 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 return installFromConstraint(&tfconstraint, mirrorURL), nil } // install using a version constraint func installFromConstraint(tfconstraint *string, mirrorURL string) string { - tfversion := "" - listAll := true //set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(mirrorURL, listAll) //get list of versions + listAll := true // set list all true - all versions including beta and rc will be displayed + tflist, _ := lib.GetTFList(mirrorURL, listAll) // get list of versions - 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() @@ -68,7 +67,7 @@ func installFromConstraint(tfconstraint *string, mirrorURL string) string { } versions := make([]*semver.Version, len(tflist)) for i, tfvals := range tflist { - version, err := semver.NewVersion(tfvals) //NewVersion parses a given version and returns an instance of Version or an error if unable to parse the version. + version, err := semver.NewVersion(tfvals) // NewVersion parses a given version and returns an instance of Version or an error if unable to parse the version. if err != nil { fmt.Printf("Error parsing version: %s", err) os.Exit(1) @@ -81,25 +80,25 @@ func installFromConstraint(tfconstraint *string, mirrorURL string) string { for _, element := range versions { if constrains.Check(element) { // Validate a version against a constraint - tfversion = element.String() - if lib.ValidVersionFormat(tfversion) { //check if version format is correct - return Install(tfversion, mirrorURL) - } else { - printInvalidTFVersion() - os.Exit(1) + tfversion := element.String() + if lib.ValidVersionFormat(tfversion) { // check if version format is correct + out, err := lib.Install(tfversion, mirrorURL) + if err != nil { + log.Printf("Error during install %v", err) + os.Exit(1) + } + return out } + printInvalidTFVersion() + os.Exit(1) } } - fmt.Println("No version found to match constraint. Follow the README.md instructions for setup. https://github.com/jb-abbadie/simple-tfswitch/blob/main/README.md") + fmt.Println("No version found to match constraint. Follow the README.md instructions for setup. https://github.com/terraform-tools/simple-tfswitch/blob/main/README.md") os.Exit(1) return "" } -func Install(tfversion string, mirrorURL string) string { - return lib.Install(tfversion, mirrorURL) -} - func runTerraform(tfBinaryPath string, args ...string) int { cmd := exec.Command(tfBinaryPath, args...) cmd.Env = os.Environ() @@ -108,8 +107,9 @@ func runTerraform(tfBinaryPath string, args ...string) int { cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { - if exitError, ok := err.(*exec.ExitError); ok { - return exitError.ExitCode() + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + return exitErr.ExitCode() } } return 0 diff --git a/main_test.go b/main_test.go index eb0d284..f2f8df5 100644 --- a/main_test.go +++ b/main_test.go @@ -7,7 +7,6 @@ import ( // TestMain : check to see if user exist func TestMain(t *testing.T) { - t.Run("User should exist", func(t *testing.T) { usr, errCurr := user.Current()