diff --git a/go.mod b/go.mod index f1832595..c6940e68 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/warrensbox/terraform-switcher go 1.22 require ( + github.com/gookit/slog v0.5.5 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72 @@ -19,6 +20,9 @@ require ( github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/gookit/color v1.5.4 // indirect + github.com/gookit/goutil v0.6.15 // indirect + github.com/gookit/gsr v0.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl/v2 v2.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -31,11 +35,15 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/zclconf/go-cty v1.1.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/sync v0.5.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 02ad8115..65454fd5 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,14 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo= +github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY= +github.com/gookit/gsr v0.1.0 h1:0gadWaYGU4phMs0bma38t+Do5OZowRMEVlHv31p0Zig= +github.com/gookit/gsr v0.1.0/go.mod h1:7wv4Y4WCnil8+DlDYHBjidzrEzfHhXEoFjEA0pPPWpI= +github.com/gookit/slog v0.5.5 h1:XoyK3NilKzuC/umvnqTQDHTOnpC8R6pvlr/ht9PyfgU= +github.com/gookit/slog v0.5.5/go.mod h1:RfIwzoaQ8wZbKdcqG7+3EzbkMqcp2TUn3mcaSZAw2EQ= github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= @@ -98,11 +106,16 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.1.0 h1:uJwc9HiBOCpoKIObTQaLR+tsEXx1HBHnOsOOpcdhZgw= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= @@ -112,14 +125,16 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= 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/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -127,6 +142,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/lib/common_test.go b/lib/common.go similarity index 82% rename from lib/common_test.go rename to lib/common.go index 12e3d3d2..b82a8f16 100644 --- a/lib/common_test.go +++ b/lib/common.go @@ -1,8 +1,6 @@ -package lib_test +package lib import ( - "fmt" - "log" "os" "path/filepath" ) @@ -23,22 +21,21 @@ func createFile(path string) { if os.IsNotExist(err) { file, err := os.Create(path) if err != nil { - fmt.Printf("%v", err) + logger.Error(err) return } defer file.Close() } - fmt.Println("==> done creating file", path) + logger.Infof("==> done creating %q file", path) } func createDirIfNotExist(dir string) { if _, err := os.Stat(dir); os.IsNotExist(err) { - log.Printf("Creating directory for terraform: %v", dir) + logger.Infof("Creating directory for terraform: %v", dir) err = os.MkdirAll(dir, 0755) if err != nil { - fmt.Printf("Unable to create directory for terraform: %v", dir) - panic(err) + logger.Panic("Unable to create %q directory for terraform: %v", dir, err) } } } diff --git a/lib/defaults.go b/lib/defaults.go index f8465487..2c076351 100644 --- a/lib/defaults.go +++ b/lib/defaults.go @@ -2,7 +2,6 @@ package lib import ( "github.com/mitchellh/go-homedir" - "log" "runtime" ) @@ -12,7 +11,7 @@ func GetDefaultBin() string { if runtime.GOOS == "windows" { home, err := homedir.Dir() if err != nil { - log.Fatalf("Could not detect home directory.") + logger.Fatal("Could not detect home directory.") } defaultBin = home + "/bin/terraform.exe" } diff --git a/lib/dir_perm_windows.go b/lib/dir_perm_windows.go index 56a6be27..6a03a1bc 100644 --- a/lib/dir_perm_windows.go +++ b/lib/dir_perm_windows.go @@ -1,7 +1,6 @@ package lib import ( - "fmt" "os" ) @@ -9,19 +8,19 @@ func CheckDirWritable(path string) bool { info, err := os.Stat(path) if err != nil { - fmt.Println("Path doesn't exist") + logger.Errorf("Path doesn't exist: %q", path) return false } err = nil if !info.IsDir() { - fmt.Println("Path isn't a directory") + logger.Errorf("Path isn't a directory: %q", path) return false } // Check if the user bit is enabled in file permission if info.Mode().Perm()&(1<<(uint(7))) == 0 { - fmt.Println("Write permission bit is not set on this file for user") + logger.Errorf("Path is not writable by the user: %q", path) return false } diff --git a/lib/download.go b/lib/download.go index 348373f1..2b1d99c9 100644 --- a/lib/download.go +++ b/lib/download.go @@ -1,7 +1,7 @@ package lib import ( - "fmt" + "errors" "io" "net/http" "os" @@ -13,11 +13,11 @@ import ( func DownloadFromURL(installLocation string, url string) (string, error) { tokens := strings.Split(url, "/") fileName := tokens[len(tokens)-1] - fmt.Printf("Downloading to: %s\n", installLocation) + logger.Infof("Downloading to %q", installLocation) response, err := http.Get(url) if err != nil { - fmt.Println("[Error] : Error while downloading", url, "-", err) + logger.Errorf("Error downloading %s: %v", url, err) return "", err } defer response.Body.Close() @@ -25,23 +25,23 @@ func DownloadFromURL(installLocation string, url string) (string, error) { 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 - return "", fmt.Errorf("[Error] : Unable to download from %s", url) + return "", errors.New("Unable to download from " + url) } zipFile := filepath.Join(installLocation, fileName) output, err := os.Create(zipFile) if err != nil { - fmt.Println("[Error] : Error while creating", zipFile, "-", err) + logger.Errorf("Error while creating %q: %v", zipFile, err) return "", err } defer output.Close() n, err := io.Copy(output, response.Body) if err != nil { - fmt.Println("[Error] : Error while downloading", url, "-", err) + logger.Errorf("Error while downloading %s: %v", url, err) return "", err } - fmt.Println(n, "bytes downloaded") + logger.Info(n, "bytes downloaded") return zipFile, nil } diff --git a/lib/download_test.go b/lib/download_test.go index 4f133eb2..4129fb64 100644 --- a/lib/download_test.go +++ b/lib/download_test.go @@ -1,16 +1,13 @@ -package lib_test +package lib import ( "fmt" "github.com/mitchellh/go-homedir" - "log" "net/url" "os" "path/filepath" "runtime" "testing" - - "github.com/warrensbox/terraform-switcher/lib" ) // TestDownloadFromURL_FileNameMatch : Check expected filename exist when downloaded @@ -24,17 +21,17 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { home, err := homedir.Dir() if err != nil { - log.Fatalf("Could not detect home directory.") + logger.Fatalf("Could not detect home directory") } - fmt.Printf("Current user homedir: %v \n", home) + logger.Infof("Current home directory: %q", home) var installLocation = "" if runtime.GOOS != "windows" { installLocation = filepath.Join(home, installPath) } else { installLocation = installPath } - fmt.Printf("Install Location: %v \n", installLocation) + logger.Infof("Install Location: %v", installLocation) // create /.terraform.versions_test/ directory to store code if _, err := os.Stat(installLocation); os.IsNotExist(err) { @@ -51,7 +48,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { url := hashiURL + lowestVersion + "/" + installVersion + lowestVersion + macOS expectedFile := filepath.Join(installLocation, installVersion+lowestVersion+macOS) - installedFile, errDownload := lib.DownloadFromURL(installLocation, url) + installedFile, errDownload := DownloadFromURL(installLocation, url) if errDownload != nil { t.Logf("Expected file name %v to be downloaded", expectedFile) @@ -76,7 +73,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { t.Cleanup(func() { defer os.Remove(tempDir) - fmt.Println("Cleanup temporary directory") + logger.Infof("Cleanup temporary directory %q", tempDir) }) } diff --git a/lib/files.go b/lib/files.go index 0f1dcfba..23e08d2a 100644 --- a/lib/files.go +++ b/lib/files.go @@ -4,10 +4,8 @@ import ( "archive/zip" "bufio" "bytes" - "fmt" "io" "io/ioutil" - "log" "os" "path/filepath" "strings" @@ -17,7 +15,7 @@ import ( func RenameFile(src string, dest string) { err := os.Rename(src, dest) if err != nil { - fmt.Println(err) + logger.Error(err) return } } @@ -103,11 +101,11 @@ func Unzip(src string, dest string) ([]string, error) { // 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) + logger.Infof("Creating directory for terraform binary at %q", dir) err = os.MkdirAll(dir, 0755) if err != nil { - fmt.Printf("Unable to create directory for terraform binary at: %v", dir) - panic(err) + logger.Error(err) + logger.Panicf("Unable to create directory for terraform binary at: %v", dir) } } } @@ -126,7 +124,7 @@ func WriteLines(lines []string, path string) (err error) { for _, item := range lines { _, err := file.WriteString(strings.TrimSpace(item) + "\n") if err != nil { - fmt.Println(err) + logger.Error(err) break } } @@ -171,7 +169,7 @@ func IsDirEmpty(name string) bool { f, err := os.Open(name) if err != nil { - log.Fatal(err) + logger.Fatal(err) } defer f.Close() @@ -189,8 +187,7 @@ func CheckDirHasTGBin(dir, prefix string) bool { files, err := ioutil.ReadDir(dir) if err != nil { - log.Fatal(err) - //return exist, err + logger.Fatal(err) } res := []string{} for _, f := range files { @@ -228,7 +225,7 @@ func GetCurrentDirectory() string { dir, err := os.Getwd() //get current directory if err != nil { - log.Printf("Failed to get current directory %v\n", err) + logger.Fatalf("Failed to get current directory %v", err) os.Exit(1) } return dir diff --git a/lib/files_test.go b/lib/files_test.go index c97eebf5..b1f7db65 100644 --- a/lib/files_test.go +++ b/lib/files_test.go @@ -1,11 +1,9 @@ -package lib_test +package lib import ( "bufio" "bytes" - "fmt" "io" - "log" "os" "path/filepath" "regexp" @@ -15,20 +13,19 @@ import ( "time" "github.com/mitchellh/go-homedir" - "github.com/warrensbox/terraform-switcher/lib" ) // TestRenameFile : Create a file, check filename exist, // rename file, check new filename exit func TestRenameFile(t *testing.T) { - installFile := lib.ConvertExecutableExt("terraform") + installFile := ConvertExecutableExt("terraform") installVersion := "terraform_" installPath := "/.terraform.versions_test/" version := "0.0.7" homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -45,9 +42,9 @@ func TestRenameFile(t *testing.T) { t.Error("Missing file") } - installVersionFilePath := lib.ConvertExecutableExt(filepath.Join(installLocation, installVersion+version)) + installVersionFilePath := ConvertExecutableExt(filepath.Join(installLocation, installVersion+version)) - lib.RenameFile(installFilePath, installVersionFilePath) + RenameFile(installFilePath, installVersionFilePath) if exist := checkFileExist(installVersionFilePath); exist { t.Logf("New file exist %v", installVersionFilePath) @@ -69,12 +66,12 @@ func TestRenameFile(t *testing.T) { // TestRemoveFiles : Create a file, check file exist, // remove file, check file does not exist func TestRemoveFiles(t *testing.T) { - installFile := lib.ConvertExecutableExt("terraform") + installFile := ConvertExecutableExt("terraform") installPath := "/.terraform.versions_test/" homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -91,7 +88,7 @@ func TestRemoveFiles(t *testing.T) { t.Error("Missing file") } - lib.RemoveFiles(installFilePath) + RemoveFiles(installFilePath) if exist := checkFileExist(installFilePath); exist { t.Logf("Old file should not exist %v", installFilePath) @@ -109,22 +106,20 @@ func TestUnzip(t *testing.T) { installPath := "/.terraform.versions_test/" absPath, _ := filepath.Abs("../test-data/test-data.zip") - fmt.Println(absPath) + logger.Infof("Absolute Path: %q", absPath) homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) createDirIfNotExist(installLocation) - files, errUnzip := lib.Unzip(absPath, installLocation) + files, errUnzip := Unzip(absPath, installLocation) if errUnzip != nil { - fmt.Println("Unable to unzip zip file") - log.Fatal(errUnzip) - os.Exit(1) + logger.Fatalf("Unable to unzip %q file: %v", absPath, errUnzip) } tst := strings.Join(files, "") @@ -145,7 +140,7 @@ func TestCreateDirIfNotExist(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -158,7 +153,7 @@ func TestCreateDirIfNotExist(t *testing.T) { t.Error("Directory should not exist") } - lib.CreateDirIfNotExist(installLocation) + CreateDirIfNotExist(installLocation) t.Logf("Creating directory %v", installLocation) if _, err := os.Stat(installLocation); err == nil { @@ -180,7 +175,7 @@ func TestWriteLines(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -189,11 +184,11 @@ func TestWriteLines(t *testing.T) { recentFilePath := filepath.Join(installLocation, recentFile) test_array := []string{"0.1.1", "0.0.2", "0.0.3", "0.12.0-rc1", "0.12.0-beta1"} - errWrite := lib.WriteLines(test_array, recentFilePath) + errWrite := WriteLines(test_array, recentFilePath) if errWrite != nil { t.Logf("Write should work %v (unexpected)", errWrite) - log.Fatal(errWrite) + logger.Fatal(errWrite) } else { var ( file *os.File @@ -203,7 +198,7 @@ func TestWriteLines(t *testing.T) { lines []string ) if file, errOpen = os.Open(recentFilePath); errOpen != nil { - log.Fatal(errOpen) + logger.Fatal(errOpen) } reader := bufio.NewReader(file) @@ -223,12 +218,12 @@ func TestWriteLines(t *testing.T) { } if errRead != nil { - log.Fatalf("Error: %s\n", errRead) + logger.Fatalf("Error: %s", errRead) } for _, line := range lines { if !semverRegex.MatchString(line) { - log.Fatalf("Write to file is not invalid: %s\n", line) + logger.Fatalf("Write to file is not invalid: %s", line) break } } @@ -248,7 +243,7 @@ func TestReadLines(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -263,26 +258,26 @@ func TestReadLines(t *testing.T) { ) if file, errCreate = os.Create(recentFilePath); errCreate != nil { - log.Fatalf("Error: %s\n", errCreate) + logger.Fatalf("Error: %s", errCreate) } for _, item := range test_array { _, err := file.WriteString(strings.TrimSpace(item) + "\n") if err != nil { - log.Fatalf("Error: %s\n", err) + logger.Fatalf("Error: %s", err) break } } - lines, errRead := lib.ReadLines(recentFilePath) + lines, errRead := ReadLines(recentFilePath) if errRead != nil { - log.Fatalf("Error: %s\n", errRead) + logger.Fatalf("Error: %s", errRead) } for _, line := range lines { if !semverRegex.MatchString(line) { - log.Fatalf("Write to file is not invalid: %s\n", line) + logger.Fatalf("Write to file is not invalid: %s", line) break } } @@ -301,7 +296,7 @@ func TestIsDirEmpty(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -313,7 +308,7 @@ func TestIsDirEmpty(t *testing.T) { createDirIfNotExist(test_dir_path) - empty := lib.IsDirEmpty(test_dir_path) + empty := IsDirEmpty(test_dir_path) t.Logf("Expected directory to be empty %v [expected]", test_dir_path) @@ -336,16 +331,16 @@ func TestCheckDirHasTFBin(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) createDirIfNotExist(installLocation) - installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(installLocation, installFilePrefix+"_"+goos+"_"+goarch)) + installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, installFilePrefix+"_"+goos+"_"+goarch)) createFile(installFileVersionPath) - empty := lib.CheckDirHasTGBin(installLocation, installFilePrefix) + empty := CheckDirHasTGBin(installLocation, installFilePrefix) t.Logf("Expected directory to have tf file %v [expected]", installFileVersionPath) @@ -361,11 +356,11 @@ func TestCheckDirHasTFBin(t *testing.T) { // TestPath : create file in directory, check if path exist func TestPath(t *testing.T) { installPath := "/.terraform.versions_test" - installFile := lib.ConvertExecutableExt("terraform") + installFile := ConvertExecutableExt("terraform") homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -374,7 +369,7 @@ func TestPath(t *testing.T) { installFilePath := filepath.Join(installLocation, installFile) createFile(installFilePath) - path := lib.Path(installFilePath) + path := Path(installFilePath) t.Logf("Path created %s\n", installFilePath) t.Logf("Path expected %s\n", installLocation) @@ -393,7 +388,7 @@ func TestGetFileName(t *testing.T) { fileNameWithExt := "file.toml" - fileName := lib.GetFileName(fileNameWithExt) + fileName := GetFileName(fileNameWithExt) if fileName == "file" { t.Logf("File removed extension (expected)") @@ -406,7 +401,7 @@ func TestGetFileName(t *testing.T) { func TestConvertExecutableExt(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } installPath := "/.terraform.versions_test/" @@ -418,7 +413,7 @@ func TestConvertExecutableExt(t *testing.T) { } for _, fpath := range test_array { - fpathExt := lib.ConvertExecutableExt((fpath)) + fpathExt := ConvertExecutableExt((fpath)) outputMsg := fpath + " converted to " + fpathExt + " on " + runtime.GOOS switch runtime.GOOS { diff --git a/lib/install.go b/lib/install.go index 1960339e..5bd17d76 100644 --- a/lib/install.go +++ b/lib/install.go @@ -2,7 +2,6 @@ package lib import ( "fmt" - "log" "os" "path/filepath" "runtime" @@ -54,7 +53,7 @@ func GetInstallLocation() string { /* get current user */ homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } userCommon := homedir @@ -71,12 +70,6 @@ func GetInstallLocation() string { // Install : Install the provided version in the argument func Install(tfversion string, binPath string, mirrorURL string) { - - // 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) - // } - /* Check to see if user has permission to the default bin location which is "/usr/local/bin/terraform" * If user does not have permission to default bin location, proceed to create $HOME/bin and install the tfswitch there * Inform user that they don't have permission to default location, therefore tfswitch was installed in $HOME/bin @@ -113,7 +106,7 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* set symlink to desired version */ CreateSymlink(installFileVersionPath, binPath) - fmt.Printf("Switched terraform to version %q \n", tfversion) + logger.Infof("Switched terraform to version %q", tfversion) AddRecent(tfversion) //add to recent file for faster lookup os.Exit(0) } @@ -131,16 +124,13 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* If unable to download file from url, exit(1) immediately */ if errDownload != nil { - fmt.Println(errDownload) - os.Exit(1) + logger.Fatalf("Error downloading %s: %v", url, 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) + logger.Fatalf("Unable to unzip %q file: %v", zipFile, errUnzip) } /* rename unzipped file to terraform version name - terraform_x.x.x */ @@ -159,7 +149,7 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* set symlink to desired version */ CreateSymlink(installFileVersionPath, binPath) - fmt.Printf("Switched terraform to version %q \n", tfversion) + logger.Infof("Switched terraform to version %q", tfversion) AddRecent(tfversion) //add to recent file for faster lookup os.Exit(0) } @@ -175,13 +165,13 @@ func AddRecent(requestedVersion string) { lines, errRead := ReadLines(versionFile) if errRead != nil { - fmt.Printf("[Error] : %s\n", errRead) + logger.Errorf("Error reading %q file: %v", versionFile, errRead) return } for _, line := range lines { if !ValidVersionFormat(line) { - fmt.Println("File dirty. Recreating cache file.") + logger.Infof("File %q is dirty (recreating cache file)", versionFile) RemoveFiles(versionFile) CreateRecentFile(requestedVersion) return @@ -220,7 +210,7 @@ func GetRecentVersions() ([]string, error) { outputRecent := []string{} if errRead != nil { - fmt.Printf("Error: %s\n", errRead) + logger.Errorf("Error reading %q file: %f", versionFile, errRead) return nil, errRead } @@ -273,7 +263,7 @@ func InstallableBinLocation(userBinPath string) string { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } binDir := Path(userBinPath) //get path directory from binary path @@ -291,21 +281,20 @@ func InstallableBinLocation(userBinPath string) string { homeBinExist := CheckDirExist(filepath.Join(homedir, "bin")) //check to see if ~/bin exist if homeBinExist { //if ~/bin exist, install at ~/bin/terraform - fmt.Printf("Installing terraform at %s\n", filepath.Join(homedir, "bin")) + logger.Infof("Installing terraform at %q", filepath.Join(homedir, "bin")) return filepath.Join(homedir, "bin", "terraform") } else { //if ~/bin directory does not exist, create ~/bin for terraform installation - fmt.Printf("Unable to write to: %s\n", userBinPath) - fmt.Printf("Creating bin directory at: %s\n", filepath.Join(homedir, "bin")) + logger.Noticef("Unable to write to %q", userBinPath) + logger.Infof("Creating bin directory at %q", filepath.Join(homedir, "bin")) CreateDirIfNotExist(filepath.Join(homedir, "bin")) //create ~/bin - fmt.Printf("RUN `export PATH=$PATH:%s` to append bin to $PATH\n", filepath.Join(homedir, "bin")) + logger.Warnf("Run `export PATH=\"$PATH:%s\"` to append bin to $PATH", filepath.Join(homedir, "bin")) return filepath.Join(homedir, "bin", "terraform") } } else { // ELSE: the "/usr/local/bin" or custom path provided by user is writable, we will return installable location return filepath.Join(userBinPath) } } - fmt.Printf("[Error] : Binary path does not exist: %s\n", userBinPath) - fmt.Printf("[Error] : Manually create bin directory at: %s and try again.\n", binDir) + logger.Fatalf("Binary path (%q) does not exist. Manually create bin directory %q and try again.", userBinPath, binDir) os.Exit(1) return "" } diff --git a/lib/list_versions.go b/lib/list_versions.go index d25e2164..a5c8759f 100644 --- a/lib/list_versions.go +++ b/lib/list_versions.go @@ -3,7 +3,6 @@ package lib import ( "fmt" "io/ioutil" - "log" "net/http" "os" "reflect" @@ -15,7 +14,7 @@ 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) @@ -43,14 +42,14 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { } if len(tfVersionList.tflist) == 0 { - fmt.Printf("Cannot get list from mirror: %s\n", mirrorURL) + logger.Infof("Cannot get version list from mirror: %s", mirrorURL) } return tfVersionList.tflist, nil } -//GetTFLatest : Get the latest terraform version given the hashicorp url +// GetTFLatest : Get the latest terraform version given the hashicorp url func GetTFLatest(mirrorURL string) (string, error) { result, error := GetTFURLBody(mirrorURL) @@ -71,7 +70,7 @@ func GetTFLatest(mirrorURL string) (string, error) { return "", nil } -//GetTFLatestImplicit : Get the latest implicit terraform version given the hashicorp url +// GetTFLatestImplicit : Get the latest implicit terraform version given the hashicorp url func GetTFLatestImplicit(mirrorURL string, preRelease bool, version string) (string, error) { if preRelease == true { //TODO: use GetTFList() instead of GetTFURLBody @@ -105,7 +104,7 @@ func GetTFLatestImplicit(mirrorURL string, preRelease bool, version string) (str return "", 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, "/") @@ -114,22 +113,20 @@ func GetTFURLBody(mirrorURL string) ([]string, error) { } resp, errURL := http.Get(mirrorURL) if errURL != nil { - log.Printf("[Error] : Getting url: %v", errURL) + logger.Fatalf("Error getting url: %v", errURL) os.Exit(1) - return nil, errURL } defer resp.Body.Close() if resp.StatusCode != 200 { - log.Printf("[Error] : Retrieving contents from url: %s", mirrorURL) + logger.Fatalf("Error retrieving contents from url: %s", mirrorURL) os.Exit(1) } body, errBody := ioutil.ReadAll(resp.Body) if errBody != nil { - log.Printf("[Error] : reading body: %v", errBody) + logger.Fatalf("Error reading body: %v", errBody) os.Exit(1) - return nil, errBody } bodyString := string(body) @@ -138,7 +135,7 @@ func GetTFURLBody(mirrorURL string) ([]string, error) { return result, nil } -//VersionExist : check if requested version exist +// VersionExist : check if requested version exist func VersionExist(val interface{}, array interface{}) (exists bool) { exists = false @@ -157,7 +154,7 @@ func VersionExist(val interface{}, array interface{}) (exists bool) { return exists } -//RemoveDuplicateVersions : remove duplicate version +// RemoveDuplicateVersions : remove duplicate version func RemoveDuplicateVersions(elements []string) []string { // Use map to record duplicates as we find them. encountered := map[string]bool{} diff --git a/lib/list_versions_test.go b/lib/list_versions_test.go index 0088f17a..6830cdb1 100644 --- a/lib/list_versions_test.go +++ b/lib/list_versions_test.go @@ -1,11 +1,8 @@ -package lib_test +package lib import ( - "log" "reflect" "testing" - - "github.com/warrensbox/terraform-switcher/lib" ) const ( @@ -16,7 +13,7 @@ const ( func TestGetTFList(t *testing.T) { listAll := true - list, _ := lib.GetTFList(hashiURL, listAll) + list, _ := GetTFList(hashiURL, listAll) val := "0.1.0" var exists bool @@ -33,120 +30,120 @@ func TestGetTFList(t *testing.T) { } if !exists { - log.Fatalf("Not able to find version: %s\n", val) + logger.Fatalf("Not able to find version: %s", val) } else { t.Log("Write versions exist (expected)") } } -//TestRemoveDuplicateVersions : test to removed duplicate +// TestRemoveDuplicateVersions : test to removed duplicate func TestRemoveDuplicateVersions(t *testing.T) { test_array := []string{"0.0.1", "0.0.2", "0.0.3", "0.0.1", "0.12.0-beta1", "0.12.0-beta1"} - list := lib.RemoveDuplicateVersions(test_array) + list := RemoveDuplicateVersions(test_array) if len(list) == len(test_array) { - log.Fatalf("Not able to remove duplicate: %s\n", test_array) + logger.Fatalf("Not able to remove duplicate: %s\n", test_array) } 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" - valid := lib.ValidVersionFormat(version) + valid := ValidVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "1.11.9" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "1.11.a" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "22323" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "@^&*!)!" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "1.11.9-beta1" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "0.12.0-rc2" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "1.11.4-boom" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } version = "1.11.4-1" - valid = lib.ValidVersionFormat(version) + valid = ValidVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - log.Fatalf("Failed to verify version format: %s\n", version) + logger.Fatalf("Failed to verify version format: %s\n", version) } } diff --git a/lib/logging.go b/lib/logging.go new file mode 100644 index 00000000..ec38d531 --- /dev/null +++ b/lib/logging.go @@ -0,0 +1,22 @@ +package lib + +import ( + "github.com/gookit/slog" + "github.com/gookit/slog/handler" +) + +const loggingTemplate = "{{datetime}} {{level}} [{{caller}}] {{message}} {{data}} {{extra}}\n" + +var logger = InitLogger() + +func InitLogger() *slog.Logger { + formatter := slog.NewTextFormatter() + formatter.EnableColor = true + formatter.ColorTheme = slog.ColorTheme + formatter.TimeFormat = "15:04:05.000" + formatter.SetTemplate(loggingTemplate) + h := handler.NewConsoleHandler(slog.AllLevels) + h.SetFormatter(formatter) + logger := slog.NewWithHandlers(h) + return logger +} diff --git a/lib/semver.go b/lib/semver.go index 366b92ee..38bbb90d 100644 --- a/lib/semver.go +++ b/lib/semver.go @@ -12,7 +12,7 @@ func GetSemver(tfconstraint *string, mirrorURL *string) (string, error) { listAll := true tflist, _ := GetTFList(*mirrorURL, listAll) //get list of versions - fmt.Printf("Reading required version from constraint: %s\n", *tfconstraint) + logger.Infof("Reading required version from constraint: %q", *tfconstraint) tfversion, err := SemVerParser(tfconstraint, tflist) return tfversion, err } @@ -39,7 +39,7 @@ func SemVerParser(tfconstraint *string, tflist []string) (string, error) { for _, element := range versions { if constraints.Check(element) { // Validate a version against a constraint tfversion = element.String() - fmt.Printf("Matched version: %s\n", tfversion) + logger.Infof("Matched version: %q", tfversion) if ValidVersionFormat(tfversion) { //check if version format is correct return tfversion, nil } @@ -52,10 +52,10 @@ func SemVerParser(tfconstraint *string, tflist []string) (string, error) { // Print invalid TF version func PrintInvalidTFVersion() { - fmt.Println("Version does not exist or invalid terraform version format.\n Format should be #.#.# or #.#.#-@# where # are numbers and @ are word characters.\n For example, 0.11.7 and 0.11.9-beta1 are valid versions") + logger.Info("Version does not exist or invalid terraform version format.\n Format should be #.#.# or #.#.#-@# where # are numbers and @ are word characters.\n For example, 0.11.7 and 0.11.9-beta1 are valid versions") } // Print invalid TF version func PrintInvalidMinorTFVersion() { - fmt.Println("Invalid minor terraform version format. Format should be #.# where # are numbers. For example, 0.11 is valid version") + logger.Info("Invalid minor terraform version format.\n Format should be #.# where # are numbers. For example, 0.11 is valid version") } diff --git a/lib/symlink.go b/lib/symlink.go index d5002682..19e48350 100644 --- a/lib/symlink.go +++ b/lib/symlink.go @@ -2,7 +2,6 @@ package lib import ( "io" - "log" "os" "runtime" ) @@ -14,14 +13,14 @@ func CreateSymlink(cwd string, dir string) { if runtime.GOOS == "windows" { r, err := os.Open(cwd) if err != nil { - log.Fatalf("Unable to open source binary: %s", cwd) + logger.Fatalf("Unable to open source binary: %s", cwd) os.Exit(1) } defer r.Close() w, err := os.Create(dir + ".exe") if err != nil { - log.Fatalf("Could not create target binary: %s", dir + ".exe") + logger.Fatalf("Could not create target binary: %s", dir+".exe") os.Exit(1) } defer func() { @@ -33,7 +32,7 @@ func CreateSymlink(cwd string, dir string) { } else { err := os.Symlink(cwd, dir) if err != nil { - log.Fatalf(` + logger.Fatalf(` Unable to create new symlink. Maybe symlink already exist. Try removing existing symlink manually. Try running "unlink %s" to remove existing symlink. @@ -50,7 +49,7 @@ func RemoveSymlink(symlinkPath string) { _, err := os.Lstat(symlinkPath) if err != nil { - log.Fatalf(` + logger.Fatalf(` Unable to stat symlink. Maybe symlink already exist. Try removing existing symlink manually. Try running "unlink %s" to remove existing symlink. @@ -62,7 +61,7 @@ func RemoveSymlink(symlinkPath string) { errRemove := os.Remove(symlinkPath) if errRemove != nil { - log.Fatalf(` + logger.Fatalf(` Unable to remove symlink. Maybe symlink already exist. Try removing existing symlink manually. Try running "unlink %s" to remove existing symlink. diff --git a/lib/symlink_test.go b/lib/symlink_test.go index 1abd0b2d..9430b8af 100644 --- a/lib/symlink_test.go +++ b/lib/symlink_test.go @@ -1,14 +1,11 @@ -package lib_test +package lib import ( "github.com/mitchellh/go-homedir" - "log" "os" "path/filepath" "runtime" "testing" - - "github.com/warrensbox/terraform-switcher/lib" ) // TestCreateSymlink : check if symlink exist-remove if exist, @@ -23,7 +20,7 @@ func TestCreateSymlink(t *testing.T) { home, err := homedir.Dir() if err != nil { - log.Fatalf("Could not detect home directory.") + logger.Fatalf("Could not detect home directory.") } symlinkPathSrc := filepath.Join(home, testSymlinkSrc) symlinkPathDest := filepath.Join(home, testSymlinkDest) @@ -31,7 +28,7 @@ func TestCreateSymlink(t *testing.T) { // Create file for test as windows does not like no source create, err := os.Create(symlinkPathDest) if err != nil { - log.Fatalf("Could not create test dest file for symlink at %v", symlinkPathDest) + logger.Fatalf("Could not create test dest file for symlink at %v", symlinkPathDest) } defer create.Close() @@ -47,7 +44,7 @@ func TestCreateSymlink(t *testing.T) { } } - lib.CreateSymlink(symlinkPathDest, symlinkPathSrc) + CreateSymlink(symlinkPathDest, symlinkPathSrc) if runtime.GOOS == "windows" { _, err := os.Stat(symlinkPathSrc + ".exe") @@ -81,7 +78,7 @@ func TestRemoveSymlink(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } symlinkPathSrc := filepath.Join(homedir, testSymlinkSrc) symlinkPathDest := filepath.Join(homedir, testSymlinkDest) @@ -96,7 +93,7 @@ func TestRemoveSymlink(t *testing.T) { } } - lib.RemoveSymlink(symlinkPathSrc) + RemoveSymlink(symlinkPathSrc) lnCheck, _ := os.Readlink(symlinkPathSrc) if lnCheck == symlinkPathDest { @@ -116,7 +113,7 @@ func TestCheckSymlink(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - log.Fatal(errCurr) + logger.Fatal(errCurr) } symlinkPathSrc := filepath.Join(homedir, testSymlinkSrc) symlinkPathDest := filepath.Join(homedir, testSymlinkDest) @@ -130,7 +127,7 @@ func TestCheckSymlink(t *testing.T) { } } - symlinkExist := lib.CheckSymlink(symlinkPathSrc) + symlinkExist := CheckSymlink(symlinkPathSrc) if symlinkExist { t.Logf("Symlink does exist %v [expected]", ln) diff --git a/main.go b/main.go index cf31d027..00e4a5fe 100644 --- a/main.go +++ b/main.go @@ -20,7 +20,6 @@ package main import ( "fmt" "io/ioutil" - "log" "os" "path/filepath" "strings" @@ -48,7 +47,8 @@ const ( versionPrefix = "terraform_" ) -var version = "0.12.0\n" +var logger = lib.InitLogger() +var version = "0.12.0" func main() { dir := lib.GetCurrentDirectory() @@ -72,7 +72,7 @@ func main() { homedir, err := homedir.Dir() if err != nil { - fmt.Printf("Unable to get home directory: %v\n", err) + logger.Fatalf("Unable to get home directory: %v", err) os.Exit(1) } @@ -85,7 +85,7 @@ func main() { switch { case *versionFlag: //if *versionFlag { - fmt.Printf("\nVersion: %v\n", version) + logger.Infof("Version: %s", version) case *helpFlag: //} else if *helpFlag { usageMessage() @@ -141,7 +141,7 @@ func main() { /* if Terraform Version environment variable is set */ case checkTFEnvExist() && len(args) == 0 && version == "": tfversion := os.Getenv("TF_VERSION") - fmt.Printf("Terraform version environment variable: %s\n", tfversion) + logger.Infof("\"TF_VERSION\" environment variable value: %q", tfversion) installVersion(tfversion, &binPath, mirrorURL) /* if terragrunt.hcl file found (IN ADDITION TO A TOML FILE) */ case fileExists(TGHACLFile) && checkVersionDefinedHCL(&TGHACLFile) && len(args) == 0: @@ -213,7 +213,7 @@ func main() { /* if Terraform Version environment variable is set */ case checkTFEnvExist() && len(args) == 0: tfversion := os.Getenv("TF_VERSION") - fmt.Printf("Terraform version environment variable: %s\n", tfversion) + logger.Infof("\"TF_VERSION\" environment variable value: %q", tfversion) installVersion(tfversion, custBinPath, mirrorURL) /* if default version is provided - Pick this instead of going for prompt */ @@ -244,21 +244,21 @@ func installLatestVersion(custBinPath, mirrorURL *string) { // show install latest stable tf version func showLatestVersion(custBinPath, mirrorURL *string) { tfversion, _ := lib.GetTFLatest(*mirrorURL) - fmt.Printf("%s\n", tfversion) + logger.Infof("%s", tfversion) } // install latest - argument (version) must be provided func installLatestImplicitVersion(requestedVersion string, custBinPath, mirrorURL *string, preRelease bool) { _, err := semver.NewConstraint(requestedVersion) if err != nil { - fmt.Printf("error parsing constraint: %s\n", err) + logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) } //if lib.ValidMinorVersionFormat(requestedVersion) { tfversion, err := lib.GetTFLatestImplicit(*mirrorURL, preRelease, requestedVersion) if err == nil && tfversion != "" { lib.Install(tfversion, *custBinPath, *mirrorURL) } - fmt.Printf("Error parsing constraint: %s\n", err) + logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) lib.PrintInvalidMinorTFVersion() } @@ -267,10 +267,9 @@ func showLatestImplicitVersion(requestedVersion string, custBinPath, mirrorURL * if lib.ValidMinorVersionFormat(requestedVersion) { tfversion, _ := lib.GetTFLatestImplicit(*mirrorURL, preRelease, requestedVersion) if len(tfversion) > 0 { - fmt.Printf("%s\n", tfversion) + logger.Infof("%s", tfversion) } else { - fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") - os.Exit(1) + logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") } } else { lib.PrintInvalidMinorTFVersion() @@ -288,7 +287,7 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) { recentDownloadFile := lib.CheckFileExist(installFileVersionPath) if recentDownloadFile { lib.ChangeSymlink(installFileVersionPath, *custBinPath) - fmt.Printf("Switched terraform to version %q \n", requestedVersion) + logger.Infof("Switched terraform to version %q", requestedVersion) lib.AddRecent(requestedVersion) //add to recent file for faster lookup os.Exit(0) } @@ -301,13 +300,12 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) { if exist { lib.Install(requestedVersion, *custBinPath, *mirrorURL) } else { - fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") - os.Exit(1) + logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") } } else { lib.PrintInvalidTFVersion() - fmt.Println("Args must be a valid terraform version") + logger.Error("Args must be a valid terraform version") usageMessage() os.Exit(1) } @@ -317,9 +315,7 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) { func retrieveFileContents(file string) string { fileContents, err := ioutil.ReadFile(file) if err != nil { - fmt.Printf("Failed to read %s file. Follow the README.md instructions for setup. https://github.com/warrensbox/terraform-switcher/blob/master/README.md\n", tfvFilename) - fmt.Printf("Error: %s\n", err) - os.Exit(1) + logger.Fatalf("Failed reading %q file: %v\n Follow the README.md instructions for setup: https://github.com/warrensbox/terraform-switcher/blob/master/README.md", tfvFilename, err) } tfversion := strings.TrimSuffix(string(fileContents), "\n") return tfversion @@ -327,7 +323,7 @@ func retrieveFileContents(file string) string { // Print message reading file content of : func readingFileMsg(filename string) { - fmt.Printf("Reading file %s \n", filename) + logger.Infof("Reading file %q", filename) } // fileExists checks if a file exists and is not a directory before we try using it to prevent further errors. @@ -364,8 +360,7 @@ func getParamsTOML(binPath string, dir string) (string, string) { path, err := homedir.Dir() if err != nil { - fmt.Printf("Unable to get home directory: %v\n", err) - os.Exit(1) + logger.Fatalf("Unable to get home directory: %v", err) } if dir == path { @@ -373,24 +368,22 @@ func getParamsTOML(binPath string, dir string) (string, string) { } else { path = "current directory" } - fmt.Printf("Reading configuration from %s\n", path+" for "+tomlFilename) //takes the default bin (defaultBin) if user does not specify bin path - configfileName := lib.GetFileName(tomlFilename) //get the config file + logger.Infof("Reading %q configuration from %q", tomlFilename, path) // Takes the default bin (defaultBin) if user does not specify bin path + configfileName := lib.GetFileName(tomlFilename) //get the config file viper.SetConfigType("toml") viper.SetConfigName(configfileName) viper.AddConfigPath(dir) errs := viper.ReadInConfig() // Find and read the config file if errs != nil { - fmt.Printf("Unable to read %s provided\n", tomlFilename) // Handle errors reading the config file - fmt.Println(errs) - os.Exit(1) // exit immediately if config file provided but it is unable to read it + logger.Fatalf("Failed to read %q: %v", tomlFilename, errs) } bin := viper.Get("bin") // read custom binary location if binPath == lib.ConvertExecutableExt(lib.GetDefaultBin()) && bin != nil { // if the bin path is the same as the default binary path and if the custom binary is provided in the toml file (use it) binPath = os.ExpandEnv(bin.(string)) } - //fmt.Println(binPath) //uncomment this to debug + //logger.Debug(binPath) // Uncomment this to debug version := viper.Get("version") //attempt to get the version if it's provided in the toml if version == nil { version = "" @@ -415,8 +408,8 @@ func installOption(listAll bool, custBinPath, mirrorURL *string) { tflist = lib.RemoveDuplicateVersions(tflist) //remove duplicate version if len(tflist) == 0 { - fmt.Println("[ERROR] : List is empty") - os.Exit(1) + + logger.Fatalf("Terraform version list is empty: %s", *mirrorURL) } /* prompt user to select version of terraform */ prompt := promptui.Select{ @@ -428,8 +421,7 @@ func installOption(listAll bool, custBinPath, mirrorURL *string) { tfversion = strings.Trim(tfversion, " *recent") //trim versions with the string " *recent" appended if errPrompt != nil { - log.Printf("Prompt failed %v\n", errPrompt) - os.Exit(1) + logger.Fatalf("Prompt failed %v", errPrompt) } lib.Install(tfversion, *custBinPath, *mirrorURL) @@ -438,7 +430,7 @@ func installOption(listAll bool, custBinPath, mirrorURL *string) { // install when tf file is provided func installTFProvidedModule(dir string, custBinPath, mirrorURL *string) { - fmt.Printf("Reading required version from terraform file\n") + logger.Infof("Reading required version from terraform module at %q", dir) module, _ := tfconfig.LoadModule(dir) tfconstraint := module.RequiredCore[0] //we skip duplicated definitions and use only first one installFromConstraint(&tfconstraint, custBinPath, mirrorURL) @@ -451,19 +443,16 @@ func installFromConstraint(tfconstraint *string, custBinPath, mirrorURL *string) if err == nil { lib.Install(tfversion, *custBinPath, *mirrorURL) } - fmt.Println(err) - 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) + logger.Fatalf("No version found to match constraint: %v.\n Follow the README.md instructions for setup: https://github.com/warrensbox/terraform-switcher/blob/master/README.md", err) } // Install using version constraint from terragrunt file func installTGHclFile(tgFile *string, custBinPath, mirrorURL *string) { - fmt.Printf("Terragrunt file found: %s\n", *tgFile) + logger.Infof("Terragrunt file found: %q", *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) + logger.Fatalf("Unable to parse %q file", *tgFile) } var version terragruntVersionConstraints gohcl.DecodeBody(file.Body, nil, &version) @@ -479,8 +468,7 @@ func checkVersionDefinedHCL(tgFile *string) bool { 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) + logger.Fatalf("Unable to parse %q file", *tgFile) } var version terragruntVersionConstraints gohcl.DecodeBody(file.Body, nil, &version)