From 7c423ab8b9dd9bdebcd255a119d483bd03cc690b Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Sun, 8 Nov 2020 23:52:13 -0600 Subject: [PATCH 1/9] added switch stmt --- main.go | 75 ++++++++++++++++++++++++++++++++++++--------------------- test.tf | 8 ++++++ 2 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 test.tf diff --git a/main.go b/main.go index c8a63951..a669385d 100644 --- a/main.go +++ b/main.go @@ -70,11 +70,45 @@ func main() { rcfile := dir + fmt.Sprintf("/%s", rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose) configfile := dir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) - if *versionFlag { + switch { + case *versionFlag: + //if *versionFlag { fmt.Printf("\nVersion: %v\n", version) - } else if *helpFlag { + case *helpFlag: + //} else if *helpFlag { usageMessage() - } else { + case *listAllFlag: + fmt.Println("passing list") + listAll := true //set list all true - all versions including beta and rc will be displayed + installOption(listAll, custBinPath) + case len(args) == 1: + fmt.Println("pass arg number") + if lib.ValidVersionFormat(args[0]) { + + requestedVersion := args[0] + listAll := true //set list all true - all versions including beta and rc will be displayed + tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions + exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it + + if exist { + lib.Install(requestedVersion, *custBinPath) + } else { + fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") + } + + } else { + fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") + fmt.Println("Args must be a valid terraform version") + usageMessage() + } + case fileExists(configfile) && len(args) == 0: + fmt.Println(configfile) + case fileExists(rcfile) && len(args) == 0: + fmt.Println(rcfile) + case fileExists(tfvfile) && len(args) == 0: + fmt.Println(tfvfile) + default: + //} else { /* This block checks to see if the tfswitch toml file is provided in the current path. * If the .tfswitch.toml file exist, it has a higher precedence than the .tfswitchrc file * You can specify the custom binary path and the version you desire @@ -118,6 +152,7 @@ func main() { if *listAllFlag { //show all terraform version including betas and RCs listAll := true //set list all true - all versions including beta and rc will be displayed + fmt.Println("testing listing all version") installOption(listAll, &binPath) } else if tfversion == "" { // if no version is provided, show a dropdown of available release versions listAll := false //set list all false - only official release will be displayed @@ -209,30 +244,6 @@ func main() { fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") os.Exit(1) } - } else if len(args) == 1 { //if tf version is provided in command line - if lib.ValidVersionFormat(args[0]) { - - requestedVersion := args[0] - listAll := true //set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions - exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it - - if exist { - lib.Install(requestedVersion, *custBinPath) - } else { - fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") - } - - } else { - fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") - fmt.Println("Args must be a valid terraform version") - usageMessage() - } - - } else if *listAllFlag { - listAll := true //set list all true - all versions including beta and rc will be displayed - installOption(listAll, custBinPath) - } else if len(args) == 0 { //if there are no commmand line arguments listAll := false //set list all false - only official release will be displayed @@ -244,6 +255,16 @@ func main() { } } +// fileExists checks if a file exists and is not a directory before we +// try using it to prevent further errors. +func fileExists(filename string) bool { + info, err := os.Stat(filename) + if os.IsNotExist(err) { + return false + } + return !info.IsDir() +} + func usageMessage() { fmt.Print("\n\n") getopt.PrintUsage(os.Stderr) diff --git a/test.tf b/test.tf new file mode 100644 index 00000000..998dc471 --- /dev/null +++ b/test.tf @@ -0,0 +1,8 @@ +terraform { + required_version = ">= 0.12.9" + + required_providers { + aws = ">= 2.52.0" + kubernetes = ">= 1.11.1" + } +} \ No newline at end of file From c623fdde6cd73a6b8c05db5e0a79807d5ecb60f3 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Tue, 10 Nov 2020 19:19:09 -0600 Subject: [PATCH 2/9] refactor config file logic --- go.sum | 1 + main.go | 389 ++++++++++++++++++++++++++++++++------------------------ version | 2 +- 3 files changed, 222 insertions(+), 170 deletions(-) diff --git a/go.sum b/go.sum index 7d6fda6f..3998a86e 100644 --- a/go.sum +++ b/go.sum @@ -214,5 +214,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099 h1:XJP7lxbSxWLOMNdBE4B/STaqVy6L73o0knwj2vIlxnw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= diff --git a/main.go b/main.go index a669385d..63254b19 100644 --- a/main.go +++ b/main.go @@ -25,11 +25,11 @@ import ( "sort" "strings" - "github.com/Masterminds/semver" - // original hashicorp upstream have broken dependencies, so using fork as workaround // TODO: move back to upstream + "github.com/Masterminds/semver" "github.com/kiranjthomas/terraform-config-inspect/tfconfig" + // "github.com/hashicorp/terraform-config-inspect/tfconfig" "github.com/manifoldco/promptui" @@ -47,7 +47,7 @@ const ( tomlFilename = ".tfswitch.toml" ) -var version = "0.8.0\n" +var version = "0.9.0\n" func main() { @@ -66,9 +66,9 @@ func main() { os.Exit(1) } - tfvfile := dir + fmt.Sprintf("/%s", tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible) - rcfile := dir + fmt.Sprintf("/%s", rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose) - configfile := dir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) + tfvfile := dir + fmt.Sprintf("/%s", tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible) + 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) switch { case *versionFlag: @@ -77,186 +77,145 @@ func main() { case *helpFlag: //} else if *helpFlag { usageMessage() - case *listAllFlag: - fmt.Println("passing list") - listAll := true //set list all true - all versions including beta and rc will be displayed - installOption(listAll, custBinPath) - case len(args) == 1: - fmt.Println("pass arg number") - if lib.ValidVersionFormat(args[0]) { - - requestedVersion := args[0] - listAll := true //set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions - exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it - - if exist { - lib.Install(requestedVersion, *custBinPath) - } else { - fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") - } - - } else { - fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") - fmt.Println("Args must be a valid terraform version") - usageMessage() + /* Checks if the .tfswitch.toml file exist */ + /* This block checks to see if the tfswitch toml file is provided in the current path. + * If the .tfswitch.toml file exist, it has a higher precedence than the .tfswitchrc file + * You can specify the custom binary path and the version you desire + * If you provide a custom binary path with the -b option, this will override the bin value in the toml file + * If you provide a version on the command line, this will override the version value in the toml file + */ + case fileExists(tomlconfigfile): + + readingFileMsg(tomlFilename) + version, binPath := getParamsTOML(custBinPath, dir) + + switch { + case version != "": + installVersion(version, &binPath) + case len(args) == 1: + installVersion(args[0], &binPath) + case *listAllFlag: + listAll := true //set list all true - all versions including beta and rc will be displayed + installOption(listAll, &binPath) + case checkTFModuleFileExist(dir): + installTFProvidedModule(dir, &binPath) + default: + listAll := false //set list all false - only official release will be displayed + installOption(listAll, &binPath) } - case fileExists(configfile) && len(args) == 0: - fmt.Println(configfile) - case fileExists(rcfile) && len(args) == 0: - fmt.Println(rcfile) - case fileExists(tfvfile) && len(args) == 0: - fmt.Println(tfvfile) - default: - //} else { - /* This block checks to see if the tfswitch toml file is provided in the current path. - * If the .tfswitch.toml file exist, it has a higher precedence than the .tfswitchrc file - * You can specify the custom binary path and the version you desire - * If you provide a custom binary path with the -b option, this will override the bin value in the toml file - * If you provide a version on the command line, this will override the version value in the toml file - */ - if _, err := os.Stat(configfile); err == nil { - fmt.Printf("Reading configuration from %s\n", tomlFilename) - tfversion := "" - binPath := *custBinPath //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(err) - os.Exit(1) // exit immediately if config file provided but it is unable to read it - } - bin := viper.Get("bin") // read custom binary location - if binPath == defaultBin && 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)) - } - version := viper.Get("version") //attempt to get the version if it's provided in the toml - - if len(args) == 1 { //if the version is passed in the command line - requestedVersion := args[0] - listAll := true //set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions - exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it - - if exist { - tfversion = requestedVersion // set tfversion = the version needed - } - } else if version != nil { // if the required version in the toml file is provided (use it) - tfversion = version.(string) - } - - if *listAllFlag { //show all terraform version including betas and RCs - listAll := true //set list all true - all versions including beta and rc will be displayed - fmt.Println("testing listing all version") - installOption(listAll, &binPath) - } else if tfversion == "" { // if no version is provided, show a dropdown of available release versions - listAll := false //set list all false - only official release will be displayed - installOption(listAll, &binPath) - } else { - if lib.ValidVersionFormat(tfversion) { //check if version is correct - lib.Install(tfversion, binPath) - } else { - fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") - os.Exit(1) - } - } - } else if module, _ := tfconfig.LoadModule(dir); len(module.RequiredCore) >= 1 && len(args) == 0 { //if there is a version.tf file, and no commmand line arguments - - tfversion := "" - tfconstraint := module.RequiredCore[0] //we skip duplicated definitions and use only first one - 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) - - 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() - os.Exit(1) - } - 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. - if err != nil { - fmt.Printf("Error parsing version: %s", err) - os.Exit(1) - } - - versions[i] = version - } + // if len(args) == 1 { //if the version is passed in the command line + // if lib.ValidVersionFormat(args[0]) { + // requestedVersion := args[0] + // listAll := true //set list all true - all versions including beta and rc will be displayed + // tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions + // exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it + + // if exist { + // tfversion = requestedVersion // set tfversion = the version needed + // } + // } else if version != "" { // if the required version in the toml file is provided (use it) + // tfversion = version + // } + // } + + // if *listAllFlag { //show all terraform version including betas and RCs + // listAll := true //set list all true - all versions including beta and rc will be displayed + // installOption(listAll, &binPath) + // } else if tfversion == "" { // if no version is provided, show a dropdown of available release versions + // listAll := false //set list all false - only official release will be displayed + // installOption(listAll, &binPath) + // } else { + //if lib.ValidVersionFormat(tfversion) { //check if version is correct + // lib.Install(tfversion, binPath) + // } else { + // printInvalidTFVersion() + // os.Exit(1) + // } + // } + /* list all versions, //show all terraform version including betas and RCs*/ + case *listAllFlag: + installWithListAll(custBinPath) - sort.Sort(sort.Reverse(semver.Collection(versions))) + /* version provided on command line as arg */ + case len(args) == 1: + installVersion(args[0], custBinPath) - for _, element := range versions { + /* provide an tfswitchrc file */ + case fileExists(rcfile) && len(args) == 0: + readingFileMsg(rcfile) + tfversion := retrieveFileContents(rcfile) + installVersion(tfversion, custBinPath) - if constrains.Check(element) { // Validate a version against a constraint - tfversion = element.String() + /* if .terraform-version file found */ + case fileExists(tfvfile) && len(args) == 0: + readingFileMsg(tfvFilename) + tfversion := retrieveFileContents(tfvfile) + installVersion(tfversion, custBinPath) - fmt.Printf("Matched version: %s\n", tfversion) - if lib.ValidVersionFormat(tfversion) { //check if version format is correct - lib.Install(tfversion, *custBinPath) - } else { - fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") - os.Exit(1) - } - } - } + /* if versions.tf file found */ + case checkTFModuleFileExist(dir) && len(args) == 0: + installTFProvidedModule(dir, 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) + // if no arg is provided + default: + listAll := false //set list all false - only official release will be displayed + installOption(listAll, custBinPath) + } +} - } else if _, err := os.Stat(rcfile); err == nil && len(args) == 0 { //if there is a .tfswitchrc file, and no commmand line arguments - fmt.Printf("Reading required terraform version %s \n", rcFilename) +/* Helper functions */ - fileContents, err := ioutil.ReadFile(rcfile) - 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", rcFilename) - fmt.Printf("Error: %s\n", err) - os.Exit(1) - } - tfversion := strings.TrimSuffix(string(fileContents), "\n") +// install with all possible versions, including beta and rc +func installWithListAll(custBinPath *string) { + listAll := true //set list all true - all versions including beta and rc will be displayed + installOption(listAll, custBinPath) +} - if lib.ValidVersionFormat(tfversion) { //check if version is correct - lib.Install(string(tfversion), *custBinPath) - } else { - fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") - os.Exit(1) - } - } else if _, err := os.Stat(tfvfile); err == nil && len(args) == 0 { //if there is a .terraform-version file, and no command line arguments - fmt.Printf("Reading required terraform version %s \n", tfvFilename) +// install with provided version as argument +func installVersion(arg string, custBinPath *string) { + if lib.ValidVersionFormat(arg) { + requestedVersion := arg + listAll := true //set list all true - all versions including beta and rc will be displayed + tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions + exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it - fileContents, err := ioutil.ReadFile(tfvfile) - 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) - } - tfversion := strings.TrimSuffix(string(fileContents), "\n") + if exist { + lib.Install(requestedVersion, *custBinPath) + } else { + fmt.Println("The provided terraform version does not exist. Try `tfswitch -l` to see all available versions.") + } - if lib.ValidVersionFormat(tfversion) { //check if version is correct - lib.Install(string(tfversion), *custBinPath) - } else { - fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") - os.Exit(1) - } - } else if len(args) == 0 { //if there are no commmand line arguments + } else { + printInvalidTFVersion() + fmt.Println("Args must be a valid terraform version") + usageMessage() + } +} - listAll := false //set list all false - only official release will be displayed - installOption(listAll, custBinPath) +// Print invalid TF version +func printInvalidTFVersion() { + fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") +} - } else { - usageMessage() - } +//retrive file content of regular file +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) } + tfversion := strings.TrimSuffix(string(fileContents), "\n") + return tfversion } -// fileExists checks if a file exists and is not a directory before we -// try using it to prevent further errors. +// Print message reading file content of : +func readingFileMsg(filename string) { + fmt.Printf("Reading required terraform version %s \n", filename) +} + +// fileExists checks if a file exists and is not a directory before we try using it to prevent further errors. func fileExists(filename string) bool { info, err := os.Stat(filename) if os.IsNotExist(err) { @@ -265,6 +224,53 @@ func fileExists(filename string) bool { return !info.IsDir() } +// fileExists checks if a file exists and is not a directory before we +// try using it to prevent further errors. +func checkTFModuleFileExist(dir string) bool { + + module, _ := tfconfig.LoadModule(dir) + if len(module.RequiredCore) >= 1 { + return true + } + return false +} + +/* valid install */ +// func simpleInstall(tfversion string, custBinPath *string) { +// if lib.ValidVersionFormat(tfversion) { //check if version is correct +// lib.Install(string(tfversion), *custBinPath) +// } else { +// fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") +// os.Exit(1) +// } +// } + +/* parses everything in the toml file, return required version and bin path */ +func getParamsTOML(custBinPath *string, dir string) (string, string) { + + fmt.Printf("Reading configuration from %s\n", tomlFilename) + binPath := *custBinPath //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 + } + + bin := viper.Get("bin") // read custom binary location + if binPath == defaultBin && 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)) + } + version := viper.Get("version") //attempt to get the version if it's provided in the toml + + return version.(string), binPath +} + func usageMessage() { fmt.Print("\n\n") getopt.PrintUsage(os.Stderr) @@ -298,3 +304,48 @@ func installOption(listAll bool, custBinPath *string) { lib.Install(tfversion, *custBinPath) os.Exit(0) } + +// installation when +func installTFProvidedModule(dir string, custBinPath *string) { + tfversion := "" + module, _ := tfconfig.LoadModule(dir) + tfconstraint := module.RequiredCore[0] //we skip duplicated definitions and use only first one + 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) + + 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() + os.Exit(1) + } + 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. + if err != nil { + fmt.Printf("Error parsing version: %s", err) + os.Exit(1) + } + + versions[i] = version + } + + sort.Sort(sort.Reverse(semver.Collection(versions))) + + for _, element := range versions { + if constrains.Check(element) { // Validate a version against a constraint + tfversion = element.String() + fmt.Printf("Matched version: %s\n", tfversion) + if lib.ValidVersionFormat(tfversion) { //check if version format is correct + lib.Install(tfversion, *custBinPath) + } else { + printInvalidTFVersion() + os.Exit(1) + } + } + } + + 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) +} diff --git a/version b/version index 524a135d..512833fc 100644 --- a/version +++ b/version @@ -1 +1 @@ -RELEASE_VERSION=0.8 \ No newline at end of file +RELEASE_VERSION=0.9 \ No newline at end of file From efaf227d275cf6897080c38afe5c173fea31acb6 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Tue, 10 Nov 2020 19:24:09 -0600 Subject: [PATCH 3/9] update comments --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 63254b19..a98bf069 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package main /* * Version 0.6.0 -* Compatible with Mac OS X ONLY +* Compatible with Mac OS X AND other LINUX OS ONLY */ /*** OPERATION WORKFLOW ***/ From ea1bb975259daee85d38c676096c20ebb3065d95 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 11 Nov 2020 17:47:51 -0600 Subject: [PATCH 4/9] added home path option for toml file --- go.mod | 1 + go.sum | 2 + main.go | 86 +++++++++++++++--------------------- test.tf => test-data/test.tf | 0 4 files changed, 39 insertions(+), 50 deletions(-) rename test.tf => test-data/test.tf (100%) diff --git a/go.mod b/go.mod index 0709ef58..99932fc4 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/manifoldco/promptui v0.2.2-0.20180308161052-c0c0d3afc6a0 github.com/mattn/go-colorable v0.0.9 // indirect github.com/mattn/go-isatty v0.0.3 // indirect + github.com/mitchellh/go-homedir v1.1.0 github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 github.com/pelletier/go-toml v1.4.0 // indirect github.com/spf13/afero v1.2.2 // indirect diff --git a/go.sum b/go.sum index 3998a86e..b7f5d836 100644 --- a/go.sum +++ b/go.sum @@ -98,6 +98,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 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= diff --git a/main.go b/main.go index a98bf069..5414330a 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,7 @@ import ( // TODO: move back to upstream "github.com/Masterminds/semver" "github.com/kiranjthomas/terraform-config-inspect/tfconfig" + "github.com/mitchellh/go-homedir" // "github.com/hashicorp/terraform-config-inspect/tfconfig" @@ -60,15 +61,22 @@ func main() { getopt.Parse() args := getopt.Args() - dir, err := os.Getwd() + dir, err := os.Getwd() //get current directory if err != nil { log.Printf("Failed to get current directory %v\n", err) os.Exit(1) } - tfvfile := dir + fmt.Sprintf("/%s", tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible) - 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) + homedir, errHome := homedir.Dir() + if errHome != nil { + log.Printf("Failed to get home directory %v\n", errHome) + os.Exit(1) + } + + curr_tfvfile := dir + fmt.Sprintf("/%s", tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible) + curr_rcfile := dir + fmt.Sprintf("/%s", rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose) + curr_tomlconfigfile := dir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) + home_tomlconfigfile := homedir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) switch { case *versionFlag: @@ -77,19 +85,26 @@ func main() { case *helpFlag: //} else if *helpFlag { usageMessage() - /* Checks if the .tfswitch.toml file exist */ + /* Checks if the .tfswitch.toml file exist in home or current directory */ /* This block checks to see if the tfswitch toml file is provided in the current path. * If the .tfswitch.toml file exist, it has a higher precedence than the .tfswitchrc file * You can specify the custom binary path and the version you desire * If you provide a custom binary path with the -b option, this will override the bin value in the toml file * If you provide a version on the command line, this will override the version value in the toml file */ - case fileExists(tomlconfigfile): - - readingFileMsg(tomlFilename) - version, binPath := getParamsTOML(custBinPath, dir) + case fileExists(curr_tomlconfigfile) || fileExists(home_tomlconfigfile): + + version := "" + binPath := *custBinPath + if fileExists(curr_tomlconfigfile) { //read from toml from current directory + version, binPath = getParamsTOML(binPath, dir) + } else { // else read from toml from home directory + version, binPath = getParamsTOML(binPath, homedir) + } switch { + case checkTFModuleFileExist(dir): + installTFProvidedModule(dir, &binPath) case version != "": installVersion(version, &binPath) case len(args) == 1: @@ -97,42 +112,11 @@ func main() { case *listAllFlag: listAll := true //set list all true - all versions including beta and rc will be displayed installOption(listAll, &binPath) - case checkTFModuleFileExist(dir): - installTFProvidedModule(dir, &binPath) default: listAll := false //set list all false - only official release will be displayed installOption(listAll, &binPath) } - // if len(args) == 1 { //if the version is passed in the command line - // if lib.ValidVersionFormat(args[0]) { - // requestedVersion := args[0] - // listAll := true //set list all true - all versions including beta and rc will be displayed - // tflist, _ := lib.GetTFList(hashiURL, listAll) //get list of versions - // exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it - - // if exist { - // tfversion = requestedVersion // set tfversion = the version needed - // } - // } else if version != "" { // if the required version in the toml file is provided (use it) - // tfversion = version - // } - // } - - // if *listAllFlag { //show all terraform version including betas and RCs - // listAll := true //set list all true - all versions including beta and rc will be displayed - // installOption(listAll, &binPath) - // } else if tfversion == "" { // if no version is provided, show a dropdown of available release versions - // listAll := false //set list all false - only official release will be displayed - // installOption(listAll, &binPath) - // } else { - //if lib.ValidVersionFormat(tfversion) { //check if version is correct - // lib.Install(tfversion, binPath) - // } else { - // printInvalidTFVersion() - // os.Exit(1) - // } - // } /* list all versions, //show all terraform version including betas and RCs*/ case *listAllFlag: installWithListAll(custBinPath) @@ -142,15 +126,15 @@ func main() { installVersion(args[0], custBinPath) /* provide an tfswitchrc file */ - case fileExists(rcfile) && len(args) == 0: - readingFileMsg(rcfile) - tfversion := retrieveFileContents(rcfile) + case fileExists(curr_rcfile) && len(args) == 0: + readingFileMsg(rcFilename) + tfversion := retrieveFileContents(curr_rcfile) installVersion(tfversion, custBinPath) /* if .terraform-version file found */ - case fileExists(tfvfile) && len(args) == 0: + case fileExists(curr_tfvfile) && len(args) == 0: readingFileMsg(tfvFilename) - tfversion := retrieveFileContents(tfvfile) + tfversion := retrieveFileContents(curr_tfvfile) installVersion(tfversion, custBinPath) /* if versions.tf file found */ @@ -212,7 +196,7 @@ func retrieveFileContents(file string) string { // Print message reading file content of : func readingFileMsg(filename string) { - fmt.Printf("Reading required terraform version %s \n", filename) + fmt.Printf("Reading file %s \n", filename) } // fileExists checks if a file exists and is not a directory before we try using it to prevent further errors. @@ -246,11 +230,10 @@ func checkTFModuleFileExist(dir string) bool { // } /* parses everything in the toml file, return required version and bin path */ -func getParamsTOML(custBinPath *string, dir string) (string, string) { +func getParamsTOML(binPath string, dir string) (string, string) { - fmt.Printf("Reading configuration from %s\n", tomlFilename) - binPath := *custBinPath //takes the default bin (defaultBin) if user does not specify bin path - configfileName := lib.GetFileName(tomlFilename) //get the config file + fmt.Printf("Reading configuration from %s\n", tomlFilename) //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) @@ -267,6 +250,9 @@ func getParamsTOML(custBinPath *string, dir string) (string, string) { binPath = os.ExpandEnv(bin.(string)) } version := viper.Get("version") //attempt to get the version if it's provided in the toml + if version == nil { + version = "" + } return version.(string), binPath } diff --git a/test.tf b/test-data/test.tf similarity index 100% rename from test.tf rename to test-data/test.tf From 4ea84ffb16145b6a6014bd3e8cdf3bf928a3e778 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 11 Nov 2020 19:45:10 -0600 Subject: [PATCH 5/9] added test cases --- main.go | 26 ++++++++++++++----- .../terraform-version/.terraform-version | 1 + test-data/{test.tf => versiontf/version.tf} | 0 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 test-data/terraform-version/.terraform-version rename test-data/{test.tf => versiontf/version.tf} (100%) diff --git a/main.go b/main.go index 5414330a..e6c656d5 100644 --- a/main.go +++ b/main.go @@ -76,7 +76,7 @@ func main() { curr_tfvfile := dir + fmt.Sprintf("/%s", tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible) curr_rcfile := dir + fmt.Sprintf("/%s", rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose) curr_tomlconfigfile := dir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) - home_tomlconfigfile := homedir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) + home_tomlconfigfile := homedir + fmt.Sprintf("/%s", tomlFilename) //settings for .tfswitch.toml file in home directory (option to specify bin directory) switch { case *versionFlag: @@ -105,13 +105,21 @@ func main() { switch { case checkTFModuleFileExist(dir): installTFProvidedModule(dir, &binPath) - case version != "": - installVersion(version, &binPath) case len(args) == 1: installVersion(args[0], &binPath) case *listAllFlag: listAll := true //set list all true - all versions including beta and rc will be displayed installOption(listAll, &binPath) + case fileExists(curr_rcfile): + readingFileMsg(rcFilename) + tfversion := retrieveFileContents(curr_rcfile) + installVersion(tfversion, custBinPath) + case fileExists(curr_tfvfile): + readingFileMsg(tfvFilename) + tfversion := retrieveFileContents(curr_tfvfile) + installVersion(tfversion, custBinPath) + case version != "": + installVersion(version, &binPath) default: listAll := false //set list all false - only official release will be displayed installOption(listAll, &binPath) @@ -231,9 +239,14 @@ func checkTFModuleFileExist(dir string) bool { /* parses everything in the toml file, return required version and bin path */ func getParamsTOML(binPath string, dir string) (string, string) { - - fmt.Printf("Reading configuration from %s\n", tomlFilename) //takes the default bin (defaultBin) if user does not specify bin path - configfileName := lib.GetFileName(tomlFilename) //get the config file + path, _ := homedir.Dir() + if dir == path { + path = "home directory" + } 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 viper.SetConfigType("toml") viper.SetConfigName(configfileName) viper.AddConfigPath(dir) @@ -249,6 +262,7 @@ func getParamsTOML(binPath string, dir string) (string, string) { if binPath == defaultBin && 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) version := viper.Get("version") //attempt to get the version if it's provided in the toml if version == nil { version = "" diff --git a/test-data/terraform-version/.terraform-version b/test-data/terraform-version/.terraform-version new file mode 100644 index 00000000..d9df1bbc --- /dev/null +++ b/test-data/terraform-version/.terraform-version @@ -0,0 +1 @@ +0.11.0 diff --git a/test-data/test.tf b/test-data/versiontf/version.tf similarity index 100% rename from test-data/test.tf rename to test-data/versiontf/version.tf From 5889268664a269631e668c7390f40e90733c405e Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 11 Nov 2020 20:24:49 -0600 Subject: [PATCH 6/9] added test data --- .../.terraform-version | 0 test-data/{versiontf => test_versiontf}/version.tf | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test-data/{terraform-version => test_terraform-version}/.terraform-version (100%) rename test-data/{versiontf => test_versiontf}/version.tf (100%) diff --git a/test-data/terraform-version/.terraform-version b/test-data/test_terraform-version/.terraform-version similarity index 100% rename from test-data/terraform-version/.terraform-version rename to test-data/test_terraform-version/.terraform-version diff --git a/test-data/versiontf/version.tf b/test-data/test_versiontf/version.tf similarity index 100% rename from test-data/versiontf/version.tf rename to test-data/test_versiontf/version.tf From 212f4c76ccdbeebc642cd97f21307eb2d8e2f37a Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 11 Nov 2020 20:30:46 -0600 Subject: [PATCH 7/9] added more test data --- .gitignore | 3 --- test-data/test_tfswitchrc/.tfswitchrc | 1 + test-data/test_tfswitchtoml/.tfswitch.toml | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 test-data/test_tfswitchrc/.tfswitchrc create mode 100644 test-data/test_tfswitchtoml/.tfswitch.toml diff --git a/.gitignore b/.gitignore index 3de84fc4..50898570 100644 --- a/.gitignore +++ b/.gitignore @@ -29,10 +29,7 @@ docs/.bundle/** .sass-cache -.tfswitchrc - tfswitch* build-script.sh -.tfswitch.toml \ No newline at end of file diff --git a/test-data/test_tfswitchrc/.tfswitchrc b/test-data/test_tfswitchrc/.tfswitchrc new file mode 100644 index 00000000..9028ec63 --- /dev/null +++ b/test-data/test_tfswitchrc/.tfswitchrc @@ -0,0 +1 @@ +0.10.5 diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/test_tfswitchtoml/.tfswitch.toml new file mode 100644 index 00000000..22b7544b --- /dev/null +++ b/test-data/test_tfswitchtoml/.tfswitch.toml @@ -0,0 +1,2 @@ +bin = "/Users/uveerum/bin2/terraform" +version = "0.10.8" From ee4b83043a28e841bde292b04de6b059ead66423 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Wed, 11 Nov 2020 20:51:09 -0600 Subject: [PATCH 8/9] added readme update --- README.md | 2 +- test-data/test_tfswitchtoml/.tfswitch.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea8e8704..393da40a 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ This is similiar to using a .tfswitchrc file, but you can specify a custom binar 1. Create a custom binary path. Ex: `mkdir /Users/warrenveerasingam/bin` (replace warrenveerasingam with your username) 2. Add the path to your PATH. Ex: `export PATH=$PATH:/Users/warrenveerasingam/bin` (add this to your bash profile or zsh profile) 3. Pass -b or --bin parameter with your custom path to install terraform. Ex: `tfswitch -b /Users/warrenveerasingam/bin/terraform 0.10.8 ` -4. Optionally, you can create a `.tfswitch.toml` file in your terraform directory. +4. Optionally, you can create a `.tfswitch.toml` file in your terraform directory (current .tfswitch.toml) OR in your home (~/.tfswitch.toml) directory. The toml file in the current directory has a higher precedence than toml file in the home directory 5. Your `.tfswitch.toml` file should look like this: ``` bin = "/Users/warrenveerasingam/bin/terraform" diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/test_tfswitchtoml/.tfswitch.toml index 22b7544b..57d3a2f3 100644 --- a/test-data/test_tfswitchtoml/.tfswitch.toml +++ b/test-data/test_tfswitchtoml/.tfswitch.toml @@ -1,2 +1,2 @@ -bin = "/Users/uveerum/bin2/terraform" +bin = "/Users/uveerum/bin/terraform" version = "0.10.8" From be1da1f23b62dc2c5adb10268eb608a41347fb3d Mon Sep 17 00:00:00 2001 From: "warren.veerasingam" Date: Thu, 12 Nov 2020 18:01:14 -0600 Subject: [PATCH 9/9] updated main file --- main.go | 20 +++++--------------- test-data/test_tfswitchtoml/.tfswitch.toml | 2 +- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index e6c656d5..e12f487a 100644 --- a/main.go +++ b/main.go @@ -85,8 +85,8 @@ func main() { case *helpFlag: //} else if *helpFlag { usageMessage() - /* Checks if the .tfswitch.toml file exist in home or current directory */ - /* This block checks to see if the tfswitch toml file is provided in the current path. + /* Checks if the .tfswitch.toml file exist in home or current directory + * This block checks to see if the tfswitch toml file is provided in the current path. * If the .tfswitch.toml file exist, it has a higher precedence than the .tfswitchrc file * You can specify the custom binary path and the version you desire * If you provide a custom binary path with the -b option, this will override the bin value in the toml file @@ -113,11 +113,11 @@ func main() { case fileExists(curr_rcfile): readingFileMsg(rcFilename) tfversion := retrieveFileContents(curr_rcfile) - installVersion(tfversion, custBinPath) + installVersion(tfversion, &binPath) case fileExists(curr_tfvfile): readingFileMsg(tfvFilename) tfversion := retrieveFileContents(curr_tfvfile) - installVersion(tfversion, custBinPath) + installVersion(tfversion, &binPath) case version != "": installVersion(version, &binPath) default: @@ -227,16 +227,6 @@ func checkTFModuleFileExist(dir string) bool { return false } -/* valid install */ -// func simpleInstall(tfversion string, custBinPath *string) { -// if lib.ValidVersionFormat(tfversion) { //check if version is correct -// lib.Install(string(tfversion), *custBinPath) -// } else { -// fmt.Println("Invalid terraform version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") -// os.Exit(1) -// } -// } - /* parses everything in the toml file, return required version and bin path */ func getParamsTOML(binPath string, dir string) (string, string) { path, _ := homedir.Dir() @@ -262,7 +252,7 @@ func getParamsTOML(binPath string, dir string) (string, string) { if binPath == defaultBin && 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) + //fmt.Println(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 = "" diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/test_tfswitchtoml/.tfswitch.toml index 57d3a2f3..63df82e7 100644 --- a/test-data/test_tfswitchtoml/.tfswitch.toml +++ b/test-data/test_tfswitchtoml/.tfswitch.toml @@ -1,2 +1,2 @@ bin = "/Users/uveerum/bin/terraform" -version = "0.10.8" +version = "0.11.3"