From c5a54ad6ff414ff6149ed9e27adba489c3826734 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 2 Apr 2024 09:49:43 +0200 Subject: [PATCH 01/49] - extract params into own struct for better usability - extracted all parameter parsing into an explicit package and ensured the precedence --- lib/param_parsing/environment.go | 8 + lib/param_parsing/environment_test.go | 17 + lib/param_parsing/parameters.go | 113 +++++ lib/param_parsing/parameters_test.go | 79 ++++ lib/param_parsing/terraform_version.go | 29 ++ lib/param_parsing/terraform_version_test.go | 17 + lib/param_parsing/terragrunt.go | 43 ++ lib/param_parsing/terragrunt_test.go | 19 + lib/param_parsing/tfswitch.go | 29 ++ lib/param_parsing/tfswitch_test.go | 15 + lib/param_parsing/toml.go | 38 ++ lib/param_parsing/toml_test.go | 33 ++ lib/param_parsing/versiontf.go | 33 ++ lib/param_parsing/versiontf_test.go | 19 + lib/semver.go | 17 +- main.go | 402 +++--------------- main_test.go | 2 +- test-data/test_precedence/.terraform-version | 1 + test-data/test_precedence/.tfswitch.toml | 2 + test-data/test_precedence/.tfswitchrc | 1 + test-data/test_precedence/terragrunt.hcl | 1 + .../test_terraform-version/.terraform-version | 2 +- test-data/test_terragrunt_hcl/terragrunt.hcl | 17 +- test-data/test_tfswitchrc/.tfswitchrc | 2 +- test-data/test_tfswitchtoml/.tfswitch.toml | 4 +- 25 files changed, 566 insertions(+), 377 deletions(-) create mode 100644 lib/param_parsing/environment.go create mode 100644 lib/param_parsing/environment_test.go create mode 100644 lib/param_parsing/parameters.go create mode 100644 lib/param_parsing/parameters_test.go create mode 100644 lib/param_parsing/terraform_version.go create mode 100644 lib/param_parsing/terraform_version_test.go create mode 100644 lib/param_parsing/terragrunt.go create mode 100644 lib/param_parsing/terragrunt_test.go create mode 100644 lib/param_parsing/tfswitch.go create mode 100644 lib/param_parsing/tfswitch_test.go create mode 100644 lib/param_parsing/toml.go create mode 100644 lib/param_parsing/toml_test.go create mode 100644 lib/param_parsing/versiontf.go create mode 100644 lib/param_parsing/versiontf_test.go create mode 100644 test-data/test_precedence/.terraform-version create mode 100644 test-data/test_precedence/.tfswitch.toml create mode 100644 test-data/test_precedence/.tfswitchrc create mode 100644 test-data/test_precedence/terragrunt.hcl diff --git a/lib/param_parsing/environment.go b/lib/param_parsing/environment.go new file mode 100644 index 00000000..086ac12a --- /dev/null +++ b/lib/param_parsing/environment.go @@ -0,0 +1,8 @@ +package param_parsing + +import "os" + +func GetParamsFromEnvironment(params Params) Params { + params.Version = os.Getenv("TF_VERSION") + return params +} diff --git a/lib/param_parsing/environment_test.go b/lib/param_parsing/environment_test.go new file mode 100644 index 00000000..438e7d07 --- /dev/null +++ b/lib/param_parsing/environment_test.go @@ -0,0 +1,17 @@ +package param_parsing + +import ( + "os" + "testing" +) + +func TestGetParamsFromEnvironment_version_from_env(t *testing.T) { + var params Params + expected := "1.0.0_from_env" + _ = os.Setenv("TF_VERSION", expected) + params = initParams(params) + params = GetParamsFromEnvironment(params) + if params.Version != expected { + t.Error("Determined version is not matchching. Got " + params.Version + ", expected " + expected) + } +} diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go new file mode 100644 index 00000000..02c9435e --- /dev/null +++ b/lib/param_parsing/parameters.go @@ -0,0 +1,113 @@ +package param_parsing + +import ( + "fmt" + "github.com/pborman/getopt" + "github.com/warrensbox/terraform-switcher/lib" + "os" +) + +type Params struct { + CustomBinaryPath string + ListAllFlag bool + LatestPre string + ShowLatestPre string + LatestStable string + ShowLatestStable string + LatestFlag bool + ShowLatestFlag bool + MirrorURL string + ChDirPath string + VersionFlag bool + DefaultVersion string + HelpFlag bool + Version string +} + +const ( + defaultMirror = "https://releases.hashicorp.com/terraform" + defaultLatest = "" +) + +func GetParameters() Params { + var params Params + params = initParams(params) + + getopt.StringVarLong(¶ms.ChDirPath, "chdir", 'c', "Switch to a different working directory before executing the given command. Ex: tfswitch --chdir terraform_project will run tfswitch in the terraform_project directory") + getopt.BoolVarLong(¶ms.VersionFlag, "version", 'v', "Displays the version of tfswitch") + getopt.BoolVarLong(¶ms.HelpFlag, "help", 'h', "Displays help message") + getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+defaultMirror) + getopt.StringVarLong(¶ms.CustomBinaryPath, "bin", 'b', "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) + getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") + getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") + getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") + getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") + getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") + getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") + getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") + getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") + + // Parse the command line parameters to fetch stuff like chdir + getopt.Parse() + + // Read configuration files + if tomlFileExists(params) { + params = getParamsTOML(params) + } else if tfSwitchFileExists(params) { + params = GetParamsFromTfSwitch(params) + } else if terraformVersionFileExists(params) { + params = GetParamsFromTerraformVersion(params) + } else if versionTFFileExists(params) { + params = GetVersionFromVersionsTF(params) + } else if terraGruntFileExists(params) { + params = GetVersionFromTerragrunt(params) + } else { + params = GetParamsFromEnvironment(params) + } + + // Parse again to overwrite anything that might by defined on the cli AND in any config file (CLI always wins) + getopt.Parse() + args := getopt.Args() + if len(args) == 1 { + /* version provided on command line as arg */ + params.Version = args[0] + } + return params +} + +func getCommandlineParams(params Params) { + getopt.StringVarLong(¶ms.CustomBinaryPath, "bin", 'b', "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) + getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") + getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") + getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") + getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") + getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") + + getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") + getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") + getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") +} + +func initParams(params Params) Params { + params.ChDirPath = lib.GetCurrentDirectory() + params.CustomBinaryPath = lib.ConvertExecutableExt(lib.GetDefaultBin()) + params.MirrorURL = defaultMirror + params.LatestPre = defaultLatest + params.ShowLatestPre = defaultLatest + params.LatestStable = defaultLatest + params.ShowLatestStable = defaultLatest + params.MirrorURL = defaultMirror + params.DefaultVersion = defaultLatest + params.ListAllFlag = false + params.LatestFlag = false + params.ShowLatestFlag = false + params.VersionFlag = false + params.HelpFlag = false + return params +} + +func UsageMessage() { + fmt.Print("\n\n") + getopt.PrintUsage(os.Stderr) + fmt.Println("Supply the terraform version as an argument, or choose from a menu") +} diff --git a/lib/param_parsing/parameters_test.go b/lib/param_parsing/parameters_test.go new file mode 100644 index 00000000..f2725a41 --- /dev/null +++ b/lib/param_parsing/parameters_test.go @@ -0,0 +1,79 @@ +package param_parsing + +import ( + "github.com/pborman/getopt" + "os" + "testing" +) + +func TestGetParameters_version_from_args(t *testing.T) { + expected := "0.13args" + os.Args = []string{"cmd", expected} + params := GetParameters() + actual := params.Version + if actual != expected { + t.Error("Version Param was not parsed correctly. Actual: " + actual + ", Expected: " + expected) + } + t.Cleanup(func() { + getopt.CommandLine = getopt.New() + }) +} +func TestGetParameters_params_are_overridden_by_toml_file(t *testing.T) { + t.Cleanup(func() { + getopt.CommandLine = getopt.New() + }) + expected := "../../test-data/test_tfswitchtoml" + os.Args = []string{"cmd", "--chdir=" + expected} + params := GetParameters() + actual := params.ChDirPath + if actual != expected { + t.Error("ChDir Param was not parsed correctly. Actual: " + actual + ", Expected: " + expected) + } + + expected = "/usr/local/bin/terraform_from_toml" + actual = params.CustomBinaryPath + if actual != expected { + t.Error("CustomBinaryPath Param was not as expected. Actual: " + actual + ", Expected: " + expected) + } + expected = "0.11.3_toml" + actual = params.Version + if actual != expected { + t.Error("Version Param was not as expected. Actual: " + actual + ", Expected: " + expected) + } +} +func TestGetParameters_toml_params_are_overridden_by_cli(t *testing.T) { + t.Cleanup(func() { + getopt.CommandLine = getopt.New() + }) + expected := "../../test-data/test_tfswitchtoml" + os.Args = []string{"cmd", "--chdir=" + expected, "--bin=/usr/test/bin"} + params := GetParameters() + actual := params.ChDirPath + if actual != expected { + t.Error("ChDir Param was not parsed correctly. Actual: " + actual + ", Expected: " + expected) + } + + expected = "/usr/test/bin" + actual = params.CustomBinaryPath + if actual != expected { + t.Error("CustomBinaryPath Param was not as expected. Actual: " + actual + ", Expected: " + expected) + } + expected = "0.11.3_toml" + actual = params.Version + if actual != expected { + t.Error("Version Param was not as expected. Actual: " + actual + ", Expected: " + expected) + } +} + +func TestGetParameters_check_config_precedence(t *testing.T) { + t.Cleanup(func() { + getopt.CommandLine = getopt.New() + }) + os.Args = []string{"cmd", "--chdir=../../test-data/test_precedence"} + parameters := prepare() + parameters = GetParameters() + expected := "0.11.3" + if parameters.Version != expected { + t.Error("Version Param was not as expected. Actual: " + parameters.Version + ", Expected: " + expected) + } +} diff --git a/lib/param_parsing/terraform_version.go b/lib/param_parsing/terraform_version.go new file mode 100644 index 00000000..2e3df088 --- /dev/null +++ b/lib/param_parsing/terraform_version.go @@ -0,0 +1,29 @@ +package param_parsing + +import ( + "fmt" + "github.com/warrensbox/terraform-switcher/lib" + "log" + "os" + "strings" +) + +const terraformVersionFileName = ".terraform-version" + +func GetParamsFromTerraformVersion(params Params) Params { + filePath := params.ChDirPath + "/" + terraformVersionFileName + if lib.CheckFileExist(filePath) { + fmt.Printf("Reading configuration from %s\n", filePath) + content, err := os.ReadFile(filePath) + if err != nil { + log.Fatal("Could not read file content", filePath, err) + } + params.Version = strings.TrimSpace(string(content)) + } + return params +} + +func terraformVersionFileExists(params Params) bool { + filePath := params.ChDirPath + "/" + terraformVersionFileName + return lib.CheckFileExist(filePath) +} diff --git a/lib/param_parsing/terraform_version_test.go b/lib/param_parsing/terraform_version_test.go new file mode 100644 index 00000000..457b6adf --- /dev/null +++ b/lib/param_parsing/terraform_version_test.go @@ -0,0 +1,17 @@ +package param_parsing + +import ( + "fmt" + "testing" +) + +func TestGetParamsFromTerraformVersion(t *testing.T) { + var params Params + params.ChDirPath = "../../test-data/test_terraform-version" + params = GetParamsFromTerraformVersion(params) + expected := "0.11.0_tfversion" + if params.Version != expected { + fmt.Printf("Version from .terraform-version not read correctly. Got: %v, Expect: %v", params.Version, expected) + t.Errorf("Version from .terraform-version not read correctly. Got: %v, Expect: %v", params.Version, expected) + } +} diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go new file mode 100644 index 00000000..77a519cb --- /dev/null +++ b/lib/param_parsing/terragrunt.go @@ -0,0 +1,43 @@ +package param_parsing + +import ( + "fmt" + "github.com/hashicorp/hcl2/gohcl" + "github.com/hashicorp/hcl2/hclparse" + "github.com/warrensbox/terraform-switcher/lib" + "log" +) + +const terraGruntFileName = "terragrunt.hcl" + +type terragruntVersionConstraints struct { + TerraformVersionConstraint string `hcl:"terraform_version_constraint"` +} + +func GetVersionFromTerragrunt(params Params) Params { + filePath := params.ChDirPath + "/" + terraGruntFileName + if lib.CheckFileExist(filePath) { + fmt.Printf("Reading configuration from %s\n", filePath) + parser := hclparse.NewParser() + hclFile, diagnostics := parser.ParseHCLFile(filePath) + if diagnostics.HasErrors() { + log.Fatal("Unable to parse HCL file", filePath) + } + var versionFromTerragrunt terragruntVersionConstraints + diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) + if diagnostics.HasErrors() { + log.Fatal("Could not decode body of HCL file.") + } + version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) + if err != nil { + log.Fatal("Could not determine semantic version") + } + params.Version = version + } + return params +} + +func terraGruntFileExists(params Params) bool { + filePath := params.ChDirPath + "/" + terraGruntFileName + return lib.CheckFileExist(filePath) +} diff --git a/lib/param_parsing/terragrunt_test.go b/lib/param_parsing/terragrunt_test.go new file mode 100644 index 00000000..c0452678 --- /dev/null +++ b/lib/param_parsing/terragrunt_test.go @@ -0,0 +1,19 @@ +package param_parsing + +import ( + "github.com/hashicorp/go-version" + "testing" +) + +func TestGetVersionFromTerragrunt(t *testing.T) { + var params Params + params = initParams(params) + params.ChDirPath = "../../test-data/test_terragrunt_hcl" + params = GetVersionFromTerragrunt(params) + v1, _ := version.NewVersion("0.13") + v2, _ := version.NewVersion("0.14") + actualVersion, _ := version.NewVersion(params.Version) + if !actualVersion.GreaterThanOrEqual(v1) || !actualVersion.LessThan(v2) { + t.Error("Determined version is not between 0.13 and 0.14") + } +} diff --git a/lib/param_parsing/tfswitch.go b/lib/param_parsing/tfswitch.go new file mode 100644 index 00000000..db537191 --- /dev/null +++ b/lib/param_parsing/tfswitch.go @@ -0,0 +1,29 @@ +package param_parsing + +import ( + "fmt" + "github.com/warrensbox/terraform-switcher/lib" + "log" + "os" + "strings" +) + +const tfSwitchFileName = ".tfswitchrc" + +func GetParamsFromTfSwitch(params Params) Params { + filePath := params.ChDirPath + "/" + tfSwitchFileName + if lib.CheckFileExist(filePath) { + fmt.Printf("Reading configuration from %s\n", filePath) + content, err := os.ReadFile(filePath) + if err != nil { + log.Fatal("Could not read file content", filePath, err) + } + params.Version = strings.TrimSpace(string(content)) + } + return params +} + +func tfSwitchFileExists(params Params) bool { + filePath := params.ChDirPath + "/" + tfSwitchFileName + return lib.CheckFileExist(filePath) +} diff --git a/lib/param_parsing/tfswitch_test.go b/lib/param_parsing/tfswitch_test.go new file mode 100644 index 00000000..5cac9213 --- /dev/null +++ b/lib/param_parsing/tfswitch_test.go @@ -0,0 +1,15 @@ +package param_parsing + +import ( + "testing" +) + +func TestGetParamsFromTfSwitch(t *testing.T) { + var params Params + params.ChDirPath = "../../test-data/test_tfswitchrc" + params = GetParamsFromTfSwitch(params) + expected := "0.10.5_tfswitch" + if params.Version != expected { + t.Error("Version from tfswitchrc not read correctly. Actual: " + params.Version + ", Expected: " + expected) + } +} diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go new file mode 100644 index 00000000..010acdb5 --- /dev/null +++ b/lib/param_parsing/toml.go @@ -0,0 +1,38 @@ +package param_parsing + +import ( + "fmt" + "github.com/spf13/viper" + "github.com/warrensbox/terraform-switcher/lib" + "log" +) + +const tfSwitchTOMLFileName = ".tfswitch.toml" + +// getParamsTOML parses everything in the toml file, return required version and bin path +func getParamsTOML(params Params) Params { + tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName + if tomlFileExists(params) { + fmt.Printf("Reading configuration from %s\n", tomlPath) + configfileName := lib.GetFileName(tfSwitchTOMLFileName) + viper.SetConfigType("toml") + viper.SetConfigName(configfileName) + viper.AddConfigPath(params.ChDirPath) + + errs := viper.ReadInConfig() // Find and read the config file + if errs != nil { + log.Fatalf("Unable to read %s provided\n", tomlPath) + } + + params.Version = viper.GetString("version") //attempt to get the version if it's provided in the toml + params.CustomBinaryPath = viper.GetString("bin") + } else { + fmt.Println("No configuration file at " + tomlPath) + } + return params +} + +func tomlFileExists(params Params) bool { + tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName + return lib.CheckFileExist(tomlPath) +} diff --git a/lib/param_parsing/toml_test.go b/lib/param_parsing/toml_test.go new file mode 100644 index 00000000..9fc7c025 --- /dev/null +++ b/lib/param_parsing/toml_test.go @@ -0,0 +1,33 @@ +package param_parsing + +import ( + "testing" +) + +func prepare() Params { + var params Params + params.ChDirPath = "../../test-data/test_tfswitchtoml" + return params +} + +func TestGetParamsTOML_BinaryPath(t *testing.T) { + expected := "/usr/local/bin/terraform_from_toml" + params := prepare() + params = getParamsTOML(params) + if params.CustomBinaryPath != expected { + t.Log("Actual:", params.CustomBinaryPath) + t.Log("Expected:", expected) + t.Error("BinaryPath not matching") + } +} + +func TestGetParamsTOML_Version(t *testing.T) { + expected := "0.11.3_toml" + params := prepare() + params = getParamsTOML(params) + if params.Version != expected { + t.Log("Actual:", params.Version) + t.Log("Expected:", expected) + t.Error("Version not matching") + } +} diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go new file mode 100644 index 00000000..b759cae8 --- /dev/null +++ b/lib/param_parsing/versiontf.go @@ -0,0 +1,33 @@ +package param_parsing + +import ( + "fmt" + "github.com/hashicorp/terraform-config-inspect/tfconfig" + "github.com/warrensbox/terraform-switcher/lib" + "log" +) + +const versionTfFileName = "version.tf" + +func GetVersionFromVersionsTF(params Params) Params { + filePath := params.ChDirPath + "/" + versionTfFileName + if lib.CheckFileExist(filePath) { + fmt.Printf("Reading version from %s\n", filePath) + module, err := tfconfig.LoadModule(params.ChDirPath) + if err != nil { + log.Fatal("Could not load terraform module") + } + tfconstraint := module.RequiredCore[0] + version, err2 := lib.GetSemver(tfconstraint, params.MirrorURL) + if err2 != nil { + log.Fatal("Could not determine semantic version") + } + params.Version = version + } + return params +} + +func versionTFFileExists(params Params) bool { + filePath := params.ChDirPath + "/" + versionTfFileName + return lib.CheckFileExist(filePath) +} diff --git a/lib/param_parsing/versiontf_test.go b/lib/param_parsing/versiontf_test.go new file mode 100644 index 00000000..345fa96f --- /dev/null +++ b/lib/param_parsing/versiontf_test.go @@ -0,0 +1,19 @@ +package param_parsing + +import ( + "github.com/hashicorp/go-version" + "testing" +) + +func TestGetVersionFromVersionsTF(t *testing.T) { + var params Params + params = initParams(params) + params.ChDirPath = "../../test-data/test_versiontf" + params = GetVersionFromVersionsTF(params) + v1, _ := version.NewVersion("1.0.0") + v2, _ := version.NewVersion("2.0.0") + actualVersion, _ := version.NewVersion(params.Version) + if !actualVersion.GreaterThanOrEqual(v1) || !actualVersion.LessThan(v2) { + t.Error("Determined version is not between 1.0.0 and 2.0.0") + } +} diff --git a/lib/semver.go b/lib/semver.go index 38bbb90d..002dc166 100644 --- a/lib/semver.go +++ b/lib/semver.go @@ -7,17 +7,16 @@ import ( semver "github.com/hashicorp/go-version" ) -// GetSemver : returns version that will be installed based on server constaint provided -func GetSemver(tfconstraint *string, mirrorURL *string) (string, error) { - +// GetSemver : returns version that will be installed based on server constraint provided +func GetSemver(tfconstraint string, mirrorURL string) (string, error) { listAll := true - tflist, _ := GetTFList(*mirrorURL, listAll) //get list of versions - logger.Infof("Reading required version from constraint: %q", *tfconstraint) - tfversion, err := SemVerParser(tfconstraint, tflist) + tflist, _ := GetTFList(mirrorURL, listAll) //get list of versions + logger.Infof("Reading required version from constraint: %q", tfconstraint) + tfversion, err := SemVerParser(&tfconstraint, tflist) return tfversion, err } -// ValidateSemVer : Goes through the list of terraform version, return a valid tf version for contraint provided +// SemVerParser : Goes through the list of terraform version, return a valid tf version for contraint provided func SemVerParser(tfconstraint *string, tflist []string) (string, error) { tfversion := "" constraints, err := semver.NewConstraint(*tfconstraint) //NewConstraint returns a Constraints instance that a Version instance can be checked against @@ -50,12 +49,12 @@ func SemVerParser(tfconstraint *string, tflist []string) (string, error) { return "", fmt.Errorf("error parsing constraint: %s", *tfconstraint) } -// Print invalid TF version +// PrintInvalidTFVersion Print invalid TF version func PrintInvalidTFVersion() { 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 +// PrintInvalidMinorTFVersion Print invalid minor TF version func PrintInvalidMinorTFVersion() { logger.Info("Invalid minor terraform version format.\n Format should be #.# where # are numbers. For example, 0.11 is valid version") } diff --git a/main.go b/main.go index c9d75edf..be814cbb 100644 --- a/main.go +++ b/main.go @@ -19,30 +19,19 @@ package main import ( "fmt" + "github.com/warrensbox/terraform-switcher/lib/param_parsing" "os" "path/filepath" "strings" semver "github.com/hashicorp/go-version" - "github.com/hashicorp/hcl2/gohcl" - "github.com/hashicorp/hcl2/hclparse" - "github.com/hashicorp/terraform-config-inspect/tfconfig" - "github.com/mitchellh/go-homedir" - "github.com/manifoldco/promptui" - "github.com/pborman/getopt" - "github.com/spf13/viper" - lib "github.com/warrensbox/terraform-switcher/lib" ) const ( - defaultMirror = "https://releases.hashicorp.com/terraform" - defaultLatest = "" - tfvFilename = ".terraform-version" - rcFilename = ".tfswitchrc" - tomlFilename = ".tfswitch.toml" - tgHclFilename = "terragrunt.hcl" + tfvFilename = ".terraform-version" + versionPrefix = "terraform_" ) @@ -50,229 +39,82 @@ var logger = lib.InitLogger() var version string func main() { - dir := lib.GetCurrentDirectory() - custBinPath := getopt.StringLong("bin", 'b', lib.ConvertExecutableExt(lib.GetDefaultBin()), "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) - listAllFlag := getopt.BoolLong("list-all", 'l', "List all versions of terraform - including beta and rc") - latestPre := getopt.StringLong("latest-pre", 'p', defaultLatest, "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") - showLatestPre := getopt.StringLong("show-latest-pre", 'P', defaultLatest, "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") - latestStable := getopt.StringLong("latest-stable", 's', defaultLatest, "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") - showLatestStable := getopt.StringLong("show-latest-stable", 'S', defaultLatest, "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") - latestFlag := getopt.BoolLong("latest", 'u', "Get latest stable version") - showLatestFlag := getopt.BoolLong("show-latest", 'U', "Show latest stable version") - mirrorURL := getopt.StringLong("mirror", 'm', defaultMirror, "Install from a remote API other than the default. Default: "+defaultMirror) - chDirPath := getopt.StringLong("chdir", 'c', dir, "Switch to a different working directory before executing the given command. Ex: tfswitch --chdir terraform_project will run tfswitch in the terraform_project directory") - versionFlag := getopt.BoolLong("version", 'v', "Displays the version of tfswitch") - defaultVersion := getopt.StringLong("default", 'd', defaultLatest, "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") - - getopt.StringVarLong(&lib.PubKeyId, "public-key-id", 'k', "The ID of the public key to check the checksums against") - getopt.StringVarLong(&lib.PubKeyPrefix, "public-key-prefix", 'x', "The prefix of the public key. i.e. \"hashicorp_\"") - getopt.StringVarLong(&lib.PubKeyUri, "public-key-uri", 'y', "The URI to download the public key from") - - helpFlag := getopt.BoolLong("help", 'h', "Displays help message") - _ = versionFlag - getopt.Parse() - args := getopt.Args() - - homedir, err := homedir.Dir() - if err != nil { - logger.Fatalf("Unable to get home directory: %v", err) - os.Exit(1) - } - TFVersionFile := filepath.Join(*chDirPath, tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible) - RCFile := filepath.Join(*chDirPath, rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose) - TOMLConfigFile := filepath.Join(*chDirPath, tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory) - HomeTOMLConfigFile := filepath.Join(homedir, tomlFilename) //settings for .tfswitch.toml file in home directory (option to specify bin directory) - TGHACLFile := filepath.Join(*chDirPath, tgHclFilename) //settings for terragrunt.hcl file in current directory (option to specify bin directory) + parameters := param_parsing.GetParameters() + //defaults := lib.GetDefaults() switch { - case *versionFlag: - //if *versionFlag { + case parameters.VersionFlag: if version != "" { fmt.Printf("Version: %s\n", version) } else { fmt.Println("Version not defined during build.") } - 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. - * 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 lib.FileExists(TOMLConfigFile) || lib.FileExists(HomeTOMLConfigFile): - version := "" - binPath := *custBinPath - if lib.FileExists(TOMLConfigFile) { //read from toml from current directory - version, binPath = getParamsTOML(binPath, *chDirPath) - } else { // else read from toml from home directory - version, binPath = getParamsTOML(binPath, homedir) - } - - switch { - /* GIVEN A TOML FILE, */ + case parameters.HelpFlag: + param_parsing.UsageMessage() + case parameters.ListAllFlag: /* show all terraform version including betas and RCs*/ - case *listAllFlag: - listAll := true //set list all true - all versions including beta and rc will be displayed - installOption(listAll, &binPath, mirrorURL) + installOption(true, parameters.CustomBinaryPath, parameters.MirrorURL) + case parameters.LatestPre != "": /* latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ - case *latestPre != "": - preRelease := true - installLatestImplicitVersion(*latestPre, &binPath, mirrorURL, preRelease) - /* latest implicit version. Ex: tfswitch --latest 0.13 downloads 0.13.5 (latest) */ - case *latestStable != "": - preRelease := false - installLatestImplicitVersion(*latestStable, &binPath, mirrorURL, preRelease) + installLatestImplicitVersion(parameters.LatestPre, parameters.CustomBinaryPath, parameters.MirrorURL, true) + case parameters.ShowLatestPre != "": + /* show latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ + showLatestImplicitVersion(parameters.ShowLatestPre, parameters.MirrorURL, true) + case parameters.LatestStable != "": + /* latest implicit version. Ex: tfswitch --latest-stable 0.13 downloads 0.13.5 (latest) */ + installLatestImplicitVersion(parameters.LatestStable, parameters.CustomBinaryPath, parameters.MirrorURL, false) + case parameters.ShowLatestStable != "": + /* show latest implicit stable version. Ex: tfswitch --show-latest-stable 0.13 downloads 0.13.5 (latest) */ + showLatestImplicitVersion(parameters.ShowLatestStable, parameters.MirrorURL, false) + case parameters.LatestFlag: /* latest stable version */ - case *latestFlag: - installLatestVersion(&binPath, mirrorURL) - /* version provided on command line as arg */ - case len(args) == 1: - installVersion(args[0], &binPath, mirrorURL) - /* provide an tfswitchrc file (IN ADDITION TO A TOML FILE) */ - case lib.FileExists(RCFile) && len(args) == 0: - readingFileMsg(rcFilename) - tfversion := retrieveFileContents(RCFile) - installVersion(tfversion, &binPath, mirrorURL) - /* if .terraform-version file found (IN ADDITION TO A TOML FILE) */ - case lib.FileExists(TFVersionFile) && len(args) == 0: - readingFileMsg(tfvFilename) - tfversion := retrieveFileContents(TFVersionFile) - installVersion(tfversion, &binPath, mirrorURL) - /* if versions.tf file found (IN ADDITION TO A TOML FILE) */ - case checkTFModuleFileExist(*chDirPath) && len(args) == 0: - installTFProvidedModule(*chDirPath, &binPath, mirrorURL) - /* if Terraform Version environment variable is set */ - case checkTFEnvExist() && len(args) == 0 && version == "": - tfversion := os.Getenv("TF_VERSION") - 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 lib.FileExists(TGHACLFile) && checkVersionDefinedHCL(&TGHACLFile) && len(args) == 0: - installTGHclFile(&TGHACLFile, &binPath, mirrorURL) - // if no arg is provided - but toml file is provided - case version != "": - installVersion(version, &binPath, mirrorURL) - default: - listAll := false //set list all false - only official release will be displayed - installOption(listAll, &binPath, mirrorURL) - } - - /* show all terraform version including betas and RCs*/ - case *listAllFlag: - installWithListAll(custBinPath, mirrorURL) - - /* latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ - case *latestPre != "": - preRelease := true - installLatestImplicitVersion(*latestPre, custBinPath, mirrorURL, preRelease) - - /* show latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ - case *showLatestPre != "": - preRelease := true - showLatestImplicitVersion(*showLatestPre, custBinPath, mirrorURL, preRelease) - - /* latest implicit version. Ex: tfswitch --latest 0.13 downloads 0.13.5 (latest) */ - case *latestStable != "": - preRelease := false - installLatestImplicitVersion(*latestStable, custBinPath, mirrorURL, preRelease) - - /* show latest implicit stable version. Ex: tfswitch --latest 0.13 downloads 0.13.5 (latest) */ - case *showLatestStable != "": - preRelease := false - showLatestImplicitVersion(*showLatestStable, custBinPath, mirrorURL, preRelease) - - /* latest stable version */ - case *latestFlag: - installLatestVersion(custBinPath, mirrorURL) - - /* show latest stable version */ - case *showLatestFlag: - showLatestVersion(custBinPath, mirrorURL) - - /* version provided on command line as arg */ - case len(args) == 1: - installVersion(args[0], custBinPath, mirrorURL) - - /* provide an tfswitchrc file */ - case lib.FileExists(RCFile) && len(args) == 0: - readingFileMsg(rcFilename) - tfversion := retrieveFileContents(RCFile) - installVersion(tfversion, custBinPath, mirrorURL) - - /* if .terraform-version file found */ - case lib.FileExists(TFVersionFile) && len(args) == 0: - readingFileMsg(tfvFilename) - tfversion := retrieveFileContents(TFVersionFile) - installVersion(tfversion, custBinPath, mirrorURL) - - /* if versions.tf file found */ - case checkTFModuleFileExist(*chDirPath) && len(args) == 0: - installTFProvidedModule(*chDirPath, custBinPath, mirrorURL) - - /* if terragrunt.hcl file found */ - case lib.FileExists(TGHACLFile) && checkVersionDefinedHCL(&TGHACLFile) && len(args) == 0: - installTGHclFile(&TGHACLFile, custBinPath, mirrorURL) - - /* if Terraform Version environment variable is set */ - case checkTFEnvExist() && len(args) == 0: - tfversion := os.Getenv("TF_VERSION") - 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 */ - case *defaultVersion != "": - installVersion(*defaultVersion, custBinPath, mirrorURL) - - // if no arg is provided + installLatestVersion(parameters.CustomBinaryPath, parameters.MirrorURL) + case parameters.ShowLatestFlag: + /* show latest stable version */ + showLatestVersion(parameters.MirrorURL) + case parameters.Version != "": + installVersion(parameters.Version, parameters.CustomBinaryPath, parameters.MirrorURL) + case parameters.DefaultVersion != "": + /* if default version is provided - Pick this instead of going for prompt */ + installVersion(parameters.DefaultVersion, parameters.CustomBinaryPath, parameters.MirrorURL) default: - listAll := false //set list all false - only official release will be displayed - installOption(listAll, custBinPath, mirrorURL) + //set list all false - only official release will be displayed + installOption(false, parameters.CustomBinaryPath, parameters.MirrorURL) } } -/* Helper functions */ - -// install with all possible versions, including beta and rc -func installWithListAll(custBinPath, mirrorURL *string) { - listAll := true //set list all true - all versions including beta and rc will be displayed - installOption(listAll, custBinPath, mirrorURL) -} - // install latest stable tf version -func installLatestVersion(custBinPath, mirrorURL *string) { - tfversion, _ := lib.GetTFLatest(*mirrorURL) - lib.Install(tfversion, *custBinPath, *mirrorURL) +func installLatestVersion(customBinaryPath, mirrorURL string) { + tfversion, _ := lib.GetTFLatest(mirrorURL) + lib.Install(tfversion, customBinaryPath, mirrorURL) } // show install latest stable tf version -func showLatestVersion(custBinPath, mirrorURL *string) { - tfversion, _ := lib.GetTFLatest(*mirrorURL) +func showLatestVersion(mirrorURL string) { + tfversion, _ := lib.GetTFLatest(mirrorURL) logger.Infof("%s", tfversion) } // install latest - argument (version) must be provided -func installLatestImplicitVersion(requestedVersion string, custBinPath, mirrorURL *string, preRelease bool) { +func installLatestImplicitVersion(requestedVersion, customBinaryPath, mirrorURL string, preRelease bool) { _, err := semver.NewConstraint(requestedVersion) if err != nil { logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) } //if lib.ValidMinorVersionFormat(requestedVersion) { - tfversion, err := lib.GetTFLatestImplicit(*mirrorURL, preRelease, requestedVersion) + tfversion, err := lib.GetTFLatestImplicit(mirrorURL, preRelease, requestedVersion) if err == nil && tfversion != "" { - lib.Install(tfversion, *custBinPath, *mirrorURL) + lib.Install(tfversion, customBinaryPath, mirrorURL) } logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) lib.PrintInvalidMinorTFVersion() } // show latest - argument (version) must be provided -func showLatestImplicitVersion(requestedVersion string, custBinPath, mirrorURL *string, preRelease bool) { +func showLatestImplicitVersion(requestedVersion, mirrorURL string, preRelease bool) { if lib.ValidMinorVersionFormat(requestedVersion) { - tfversion, _ := lib.GetTFLatestImplicit(*mirrorURL, preRelease, requestedVersion) + tfversion, _ := lib.GetTFLatestImplicit(mirrorURL, preRelease, requestedVersion) if len(tfversion) > 0 { logger.Infof("%s", tfversion) } else { @@ -285,7 +127,7 @@ func showLatestImplicitVersion(requestedVersion string, custBinPath, mirrorURL * } // install with provided version as argument -func installVersion(arg string, custBinPath *string, mirrorURL *string) { +func installVersion(arg, customBinaryPath, mirrorURL string) { if lib.ValidVersionFormat(arg) { requestedVersion := arg @@ -294,19 +136,19 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) { installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(installLocation, versionPrefix+requestedVersion)) recentDownloadFile := lib.CheckFileExist(installFileVersionPath) if recentDownloadFile { - lib.ChangeSymlink(installFileVersionPath, *custBinPath) + lib.ChangeSymlink(installFileVersionPath, customBinaryPath) logger.Infof("Switched terraform to version %q", requestedVersion) lib.AddRecent(requestedVersion) //add to recent file for faster lookup os.Exit(0) } //if the requested version had not been downloaded before - listAll := true //set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(*mirrorURL, listAll) //get list of versions + //set list all true - all versions including beta and rc will be displayed + tflist, _ := lib.GetTFList(mirrorURL, true) //get list of versions exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it if exist { - lib.Install(requestedVersion, *custBinPath, *mirrorURL) + lib.Install(requestedVersion, customBinaryPath, mirrorURL) } else { logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") os.Exit(1) @@ -315,100 +157,19 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) { } else { lib.PrintInvalidTFVersion() logger.Error("Args must be a valid terraform version") - usageMessage() + param_parsing.UsageMessage() os.Exit(1) } } -// retrive file content of regular file -func retrieveFileContents(file string) string { - fileContents, err := os.ReadFile(file) - if err != nil { - 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) - os.Exit(1) - } - tfversion := strings.TrimSuffix(string(fileContents), "\n") - return tfversion -} - -// Print message reading file content of : -func readingFileMsg(filename string) { - 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. -func checkTFModuleFileExist(dir string) bool { - - module, _ := tfconfig.LoadModule(dir) - if len(module.RequiredCore) >= 1 { - return true - } - return false -} - -// checkTFEnvExist - checks if the TF_VERSION environment variable is set -func checkTFEnvExist() bool { - tfversion := os.Getenv("TF_VERSION") - if tfversion != "" { - return true - } - return false -} - -/* parses everything in the toml file, return required version and bin path */ -func getParamsTOML(binPath string, dir string) (string, string) { - path, err := homedir.Dir() - - if err != nil { - logger.Fatalf("Unable to get home directory: %v", err) - os.Exit(1) - } - - if dir == path { - path = "home directory" - } else { - path = "current directory" - } - 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 { - logger.Fatalf("Failed to read %q: %v", tomlFilename, errs) - os.Exit(1) - } - - 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)) - } - //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 = "" - } - - return version.(string), binPath -} - -func usageMessage() { - fmt.Print("\n\n") - getopt.PrintUsage(os.Stderr) - fmt.Println("Supply the terraform version as an argument, or choose from a menu") -} - /* installOption : displays & installs tf version */ /* listAll = true - all versions including beta and rc will be displayed */ /* listAll = false - only official stable release are displayed */ -func installOption(listAll bool, custBinPath, mirrorURL *string) { - tflist, _ := lib.GetTFList(*mirrorURL, listAll) //get list of versions - recentVersions, _ := lib.GetRecentVersions() //get recent versions from RECENT file - tflist = append(recentVersions, tflist...) //append recent versions to the top of the list - tflist = lib.RemoveDuplicateVersions(tflist) //remove duplicate version +func installOption(listAll bool, customBinaryPath, mirrorURL string) { + tflist, _ := lib.GetTFList(mirrorURL, listAll) //get list of versions + recentVersions, _ := lib.GetRecentVersions() //get recent versions from RECENT file + tflist = append(recentVersions, tflist...) //append recent versions to the top of the list + tflist = lib.RemoveDuplicateVersions(tflist) //remove duplicate version if len(tflist) == 0 { logger.Fatalf("Terraform version list is empty: %s", *mirrorURL) @@ -429,59 +190,6 @@ func installOption(listAll bool, custBinPath, mirrorURL *string) { os.Exit(1) } - lib.Install(tfversion, *custBinPath, *mirrorURL) + lib.Install(tfversion, customBinaryPath, mirrorURL) os.Exit(0) } - -// install when tf file is provided -func installTFProvidedModule(dir string, custBinPath, mirrorURL *string) { - 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) -} - -// install using a version constraint -func installFromConstraint(tfconstraint *string, custBinPath, mirrorURL *string) { - - tfversion, err := lib.GetSemver(tfconstraint, mirrorURL) - if err == nil { - lib.Install(tfversion, *custBinPath, *mirrorURL) - } - 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) - os.Exit(1) -} - -// Install using version constraint from terragrunt file -func installTGHclFile(tgFile *string, custBinPath, mirrorURL *string) { - 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() { - logger.Fatalf("Unable to parse %q file", *tgFile) - os.Exit(1) - } - var version terragruntVersionConstraints - gohcl.DecodeBody(file.Body, nil, &version) - installFromConstraint(&version.TerraformVersionConstraint, custBinPath, mirrorURL) -} - -type terragruntVersionConstraints struct { - TerraformVersionConstraint string `hcl:"terraform_version_constraint"` -} - -// check if version is defined in hcl file /* lazy-emergency fix - will improve later */ -func checkVersionDefinedHCL(tgFile *string) bool { - parser := hclparse.NewParser() - file, diags := parser.ParseHCLFile(*tgFile) //use hcl parser to parse HCL file - if diags.HasErrors() { - logger.Fatalf("Unable to parse %q file", *tgFile) - os.Exit(1) - } - var version terragruntVersionConstraints - gohcl.DecodeBody(file.Body, nil, &version) - if version == (terragruntVersionConstraints{}) { - return false - } - return true -} diff --git a/main_test.go b/main_test.go index e6be58fb..f4156d6e 100644 --- a/main_test.go +++ b/main_test.go @@ -1,4 +1,4 @@ -package main_test +package main import ( "os/user" diff --git a/test-data/test_precedence/.terraform-version b/test-data/test_precedence/.terraform-version new file mode 100644 index 00000000..d9df1bbc --- /dev/null +++ b/test-data/test_precedence/.terraform-version @@ -0,0 +1 @@ +0.11.0 diff --git a/test-data/test_precedence/.tfswitch.toml b/test-data/test_precedence/.tfswitch.toml new file mode 100644 index 00000000..b5ee7fe5 --- /dev/null +++ b/test-data/test_precedence/.tfswitch.toml @@ -0,0 +1,2 @@ +bin = "/usr/local/bin/terraform_from_toml" +version = "0.11.3" diff --git a/test-data/test_precedence/.tfswitchrc b/test-data/test_precedence/.tfswitchrc new file mode 100644 index 00000000..9028ec63 --- /dev/null +++ b/test-data/test_precedence/.tfswitchrc @@ -0,0 +1 @@ +0.10.5 diff --git a/test-data/test_precedence/terragrunt.hcl b/test-data/test_precedence/terragrunt.hcl new file mode 100644 index 00000000..549e96ec --- /dev/null +++ b/test-data/test_precedence/terragrunt.hcl @@ -0,0 +1 @@ +terraform_version_constraint = ">= 0.13, < 0.14" \ No newline at end of file diff --git a/test-data/test_terraform-version/.terraform-version b/test-data/test_terraform-version/.terraform-version index d9df1bbc..e1a6ee7b 100644 --- a/test-data/test_terraform-version/.terraform-version +++ b/test-data/test_terraform-version/.terraform-version @@ -1 +1 @@ -0.11.0 +0.11.0_tfversion diff --git a/test-data/test_terragrunt_hcl/terragrunt.hcl b/test-data/test_terragrunt_hcl/terragrunt.hcl index 806b304f..549e96ec 100644 --- a/test-data/test_terragrunt_hcl/terragrunt.hcl +++ b/test-data/test_terragrunt_hcl/terragrunt.hcl @@ -1,16 +1 @@ -include { - path = "${find_in_parent_folders()}" -} - -terraform { - source = "..." - - extra_arguments "variables" { - commands = get_terraform_commands_that_need_vars() - } -} - inputs = merge( - jsondecode(file("${find_in_parent_folders("general.tfvars")}")) -) - -terraform_version_constraint=">= 0.13, < 0.14" \ No newline at end of file +terraform_version_constraint = ">= 0.13, < 0.14" \ No newline at end of file diff --git a/test-data/test_tfswitchrc/.tfswitchrc b/test-data/test_tfswitchrc/.tfswitchrc index 9028ec63..4b90204e 100644 --- a/test-data/test_tfswitchrc/.tfswitchrc +++ b/test-data/test_tfswitchrc/.tfswitchrc @@ -1 +1 @@ -0.10.5 +0.10.5_tfswitch diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/test_tfswitchtoml/.tfswitch.toml index f234e9cc..9af1b141 100644 --- a/test-data/test_tfswitchtoml/.tfswitch.toml +++ b/test-data/test_tfswitchtoml/.tfswitch.toml @@ -1,2 +1,2 @@ -bin = "/usr/local/bin/terraform" -version = "0.11.3" +bin = "/usr/local/bin/terraform_from_toml" +version = "0.11.3_toml" From 0462a64ef99cef7c9a4b7eb58ae732566bcbed97 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Wed, 3 Apr 2024 20:42:01 +0200 Subject: [PATCH 02/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- lib/param_parsing/environment_test.go | 2 +- lib/param_parsing/toml.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/param_parsing/environment_test.go b/lib/param_parsing/environment_test.go index 438e7d07..c6a45cae 100644 --- a/lib/param_parsing/environment_test.go +++ b/lib/param_parsing/environment_test.go @@ -12,6 +12,6 @@ func TestGetParamsFromEnvironment_version_from_env(t *testing.T) { params = initParams(params) params = GetParamsFromEnvironment(params) if params.Version != expected { - t.Error("Determined version is not matchching. Got " + params.Version + ", expected " + expected) + t.Error("Determined version is not matching. Got " + params.Version + ", expected " + expected) } } diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 010acdb5..515e5e76 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -24,7 +24,7 @@ func getParamsTOML(params Params) Params { log.Fatalf("Unable to read %s provided\n", tomlPath) } - params.Version = viper.GetString("version") //attempt to get the version if it's provided in the toml + params.Version = viper.GetString("version") // Attempt to get the version if it's provided in the toml params.CustomBinaryPath = viper.GetString("bin") } else { fmt.Println("No configuration file at " + tomlPath) From 67b96c951406135bf20d341bfad096073586817d Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Wed, 3 Apr 2024 20:54:21 +0200 Subject: [PATCH 03/49] - implement suggestions from review --- lib/param_parsing/parameters.go | 59 ++++++++------------ lib/param_parsing/terraform_version_test.go | 2 - lib/param_parsing/toml_test.go | 8 +-- test-data/test_precedence/terragrunt.hcl | 2 +- test-data/test_terragrunt_hcl/terragrunt.hcl | 2 +- 5 files changed, 27 insertions(+), 46 deletions(-) diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 02c9435e..2c0cda19 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -8,20 +8,20 @@ import ( ) type Params struct { + ChDirPath string CustomBinaryPath string - ListAllFlag bool + DefaultVersion string + HelpFlag bool + LatestFlag bool LatestPre string - ShowLatestPre string LatestStable string - ShowLatestStable string - LatestFlag bool - ShowLatestFlag bool + ListAllFlag bool MirrorURL string - ChDirPath string - VersionFlag bool - DefaultVersion string - HelpFlag bool + ShowLatestFlag bool + ShowLatestPre string + ShowLatestStable string Version string + VersionFlag bool } const ( @@ -34,18 +34,18 @@ func GetParameters() Params { params = initParams(params) getopt.StringVarLong(¶ms.ChDirPath, "chdir", 'c', "Switch to a different working directory before executing the given command. Ex: tfswitch --chdir terraform_project will run tfswitch in the terraform_project directory") - getopt.BoolVarLong(¶ms.VersionFlag, "version", 'v', "Displays the version of tfswitch") - getopt.BoolVarLong(¶ms.HelpFlag, "help", 'h', "Displays help message") - getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+defaultMirror) getopt.StringVarLong(¶ms.CustomBinaryPath, "bin", 'b', "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) + getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") + getopt.BoolVarLong(¶ms.HelpFlag, "help", 'h', "Displays help message") + getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") - getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") - getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") - getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") - getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") + getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+defaultMirror) getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") + getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") + getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") + getopt.BoolVarLong(¶ms.VersionFlag, "version", 'v', "Displays the version of tfswitch") // Parse the command line parameters to fetch stuff like chdir getopt.Parse() @@ -75,34 +75,21 @@ func GetParameters() Params { return params } -func getCommandlineParams(params Params) { - getopt.StringVarLong(¶ms.CustomBinaryPath, "bin", 'b', "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) - getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") - getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") - getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") - getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") - getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") - - getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") - getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") - getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") -} - func initParams(params Params) Params { params.ChDirPath = lib.GetCurrentDirectory() params.CustomBinaryPath = lib.ConvertExecutableExt(lib.GetDefaultBin()) - params.MirrorURL = defaultMirror + params.DefaultVersion = defaultLatest + params.HelpFlag = false + params.LatestFlag = false params.LatestPre = defaultLatest - params.ShowLatestPre = defaultLatest params.LatestStable = defaultLatest - params.ShowLatestStable = defaultLatest - params.MirrorURL = defaultMirror - params.DefaultVersion = defaultLatest params.ListAllFlag = false - params.LatestFlag = false + params.MirrorURL = defaultMirror params.ShowLatestFlag = false + params.ShowLatestPre = defaultLatest + params.ShowLatestStable = defaultLatest + params.Version = defaultLatest params.VersionFlag = false - params.HelpFlag = false return params } diff --git a/lib/param_parsing/terraform_version_test.go b/lib/param_parsing/terraform_version_test.go index 457b6adf..d915ca51 100644 --- a/lib/param_parsing/terraform_version_test.go +++ b/lib/param_parsing/terraform_version_test.go @@ -1,7 +1,6 @@ package param_parsing import ( - "fmt" "testing" ) @@ -11,7 +10,6 @@ func TestGetParamsFromTerraformVersion(t *testing.T) { params = GetParamsFromTerraformVersion(params) expected := "0.11.0_tfversion" if params.Version != expected { - fmt.Printf("Version from .terraform-version not read correctly. Got: %v, Expect: %v", params.Version, expected) t.Errorf("Version from .terraform-version not read correctly. Got: %v, Expect: %v", params.Version, expected) } } diff --git a/lib/param_parsing/toml_test.go b/lib/param_parsing/toml_test.go index 9fc7c025..1da5d8af 100644 --- a/lib/param_parsing/toml_test.go +++ b/lib/param_parsing/toml_test.go @@ -15,9 +15,7 @@ func TestGetParamsTOML_BinaryPath(t *testing.T) { params := prepare() params = getParamsTOML(params) if params.CustomBinaryPath != expected { - t.Log("Actual:", params.CustomBinaryPath) - t.Log("Expected:", expected) - t.Error("BinaryPath not matching") + t.Errorf("BinaryPath not matching. Got %v, expected %v", params.CustomBinaryPath, expected) } } @@ -26,8 +24,6 @@ func TestGetParamsTOML_Version(t *testing.T) { params := prepare() params = getParamsTOML(params) if params.Version != expected { - t.Log("Actual:", params.Version) - t.Log("Expected:", expected) - t.Error("Version not matching") + t.Errorf("Version not matching. Got %v, expected %v", params.Version, expected) } } diff --git a/test-data/test_precedence/terragrunt.hcl b/test-data/test_precedence/terragrunt.hcl index 549e96ec..9237b428 100644 --- a/test-data/test_precedence/terragrunt.hcl +++ b/test-data/test_precedence/terragrunt.hcl @@ -1 +1 @@ -terraform_version_constraint = ">= 0.13, < 0.14" \ No newline at end of file +terraform_version_constraint = ">= 0.13, < 0.14" diff --git a/test-data/test_terragrunt_hcl/terragrunt.hcl b/test-data/test_terragrunt_hcl/terragrunt.hcl index 549e96ec..9237b428 100644 --- a/test-data/test_terragrunt_hcl/terragrunt.hcl +++ b/test-data/test_terragrunt_hcl/terragrunt.hcl @@ -1 +1 @@ -terraform_version_constraint = ">= 0.13, < 0.14" \ No newline at end of file +terraform_version_constraint = ">= 0.13, < 0.14" From 007dd1bbe0eb0f4d7a5d4a9f405c824de610fd16 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Wed, 3 Apr 2024 21:18:21 +0200 Subject: [PATCH 04/49] - explicitly create viper parser --- lib/param_parsing/toml.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 515e5e76..4486bb37 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -15,17 +15,18 @@ func getParamsTOML(params Params) Params { if tomlFileExists(params) { fmt.Printf("Reading configuration from %s\n", tomlPath) configfileName := lib.GetFileName(tfSwitchTOMLFileName) - viper.SetConfigType("toml") - viper.SetConfigName(configfileName) - viper.AddConfigPath(params.ChDirPath) + viperParser := viper.New() + viperParser.SetConfigType("toml") + viperParser.SetConfigName(configfileName) + viperParser.AddConfigPath(params.ChDirPath) - errs := viper.ReadInConfig() // Find and read the config file + errs := viperParser.ReadInConfig() // Find and read the config file if errs != nil { log.Fatalf("Unable to read %s provided\n", tomlPath) } - params.Version = viper.GetString("version") // Attempt to get the version if it's provided in the toml - params.CustomBinaryPath = viper.GetString("bin") + params.Version = viperParser.GetString("version") // Attempt to get the version if it's provided in the toml + params.CustomBinaryPath = viperParser.GetString("bin") } else { fmt.Println("No configuration file at " + tomlPath) } From 04fa46ba1a07fb5f2f921d87512f1be0641e34ea Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Wed, 3 Apr 2024 21:25:37 +0200 Subject: [PATCH 05/49] - update test files --- lib/param_parsing/parameters_test.go | 4 ++-- lib/param_parsing/terraform_version_test.go | 2 +- lib/param_parsing/tfswitch_test.go | 2 +- lib/param_parsing/toml_test.go | 2 +- test-data/test_terraform-version/.terraform-version | 2 +- test-data/test_tfswitchrc/.tfswitchrc | 2 +- test-data/test_tfswitchtoml/.tfswitch.toml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/param_parsing/parameters_test.go b/lib/param_parsing/parameters_test.go index f2725a41..0e1f9042 100644 --- a/lib/param_parsing/parameters_test.go +++ b/lib/param_parsing/parameters_test.go @@ -35,7 +35,7 @@ func TestGetParameters_params_are_overridden_by_toml_file(t *testing.T) { if actual != expected { t.Error("CustomBinaryPath Param was not as expected. Actual: " + actual + ", Expected: " + expected) } - expected = "0.11.3_toml" + expected = "0.11.4" actual = params.Version if actual != expected { t.Error("Version Param was not as expected. Actual: " + actual + ", Expected: " + expected) @@ -58,7 +58,7 @@ func TestGetParameters_toml_params_are_overridden_by_cli(t *testing.T) { if actual != expected { t.Error("CustomBinaryPath Param was not as expected. Actual: " + actual + ", Expected: " + expected) } - expected = "0.11.3_toml" + expected = "0.11.4" actual = params.Version if actual != expected { t.Error("Version Param was not as expected. Actual: " + actual + ", Expected: " + expected) diff --git a/lib/param_parsing/terraform_version_test.go b/lib/param_parsing/terraform_version_test.go index d915ca51..883ce29f 100644 --- a/lib/param_parsing/terraform_version_test.go +++ b/lib/param_parsing/terraform_version_test.go @@ -8,7 +8,7 @@ func TestGetParamsFromTerraformVersion(t *testing.T) { var params Params params.ChDirPath = "../../test-data/test_terraform-version" params = GetParamsFromTerraformVersion(params) - expected := "0.11.0_tfversion" + expected := "0.11.0" if params.Version != expected { t.Errorf("Version from .terraform-version not read correctly. Got: %v, Expect: %v", params.Version, expected) } diff --git a/lib/param_parsing/tfswitch_test.go b/lib/param_parsing/tfswitch_test.go index 5cac9213..12261c47 100644 --- a/lib/param_parsing/tfswitch_test.go +++ b/lib/param_parsing/tfswitch_test.go @@ -8,7 +8,7 @@ func TestGetParamsFromTfSwitch(t *testing.T) { var params Params params.ChDirPath = "../../test-data/test_tfswitchrc" params = GetParamsFromTfSwitch(params) - expected := "0.10.5_tfswitch" + expected := "0.10.5" if params.Version != expected { t.Error("Version from tfswitchrc not read correctly. Actual: " + params.Version + ", Expected: " + expected) } diff --git a/lib/param_parsing/toml_test.go b/lib/param_parsing/toml_test.go index 1da5d8af..679be62b 100644 --- a/lib/param_parsing/toml_test.go +++ b/lib/param_parsing/toml_test.go @@ -20,7 +20,7 @@ func TestGetParamsTOML_BinaryPath(t *testing.T) { } func TestGetParamsTOML_Version(t *testing.T) { - expected := "0.11.3_toml" + expected := "0.11.4" params := prepare() params = getParamsTOML(params) if params.Version != expected { diff --git a/test-data/test_terraform-version/.terraform-version b/test-data/test_terraform-version/.terraform-version index e1a6ee7b..d9df1bbc 100644 --- a/test-data/test_terraform-version/.terraform-version +++ b/test-data/test_terraform-version/.terraform-version @@ -1 +1 @@ -0.11.0_tfversion +0.11.0 diff --git a/test-data/test_tfswitchrc/.tfswitchrc b/test-data/test_tfswitchrc/.tfswitchrc index 4b90204e..9028ec63 100644 --- a/test-data/test_tfswitchrc/.tfswitchrc +++ b/test-data/test_tfswitchrc/.tfswitchrc @@ -1 +1 @@ -0.10.5_tfswitch +0.10.5 diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/test_tfswitchtoml/.tfswitch.toml index 9af1b141..dd8d5095 100644 --- a/test-data/test_tfswitchtoml/.tfswitch.toml +++ b/test-data/test_tfswitchtoml/.tfswitch.toml @@ -1,2 +1,2 @@ bin = "/usr/local/bin/terraform_from_toml" -version = "0.11.3_toml" +version = "0.11.4" From c9f802873ec2466335785969ec17a648325aeb6f Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 4 Apr 2024 08:48:54 +0200 Subject: [PATCH 06/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- main.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index be814cbb..872101d5 100644 --- a/main.go +++ b/main.go @@ -79,7 +79,7 @@ func main() { /* if default version is provided - Pick this instead of going for prompt */ installVersion(parameters.DefaultVersion, parameters.CustomBinaryPath, parameters.MirrorURL) default: - //set list all false - only official release will be displayed + // Set list all false - only official release will be displayed installOption(false, parameters.CustomBinaryPath, parameters.MirrorURL) } } @@ -143,8 +143,8 @@ func installVersion(arg, customBinaryPath, mirrorURL string) { } //if the requested version had not been downloaded before - //set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(mirrorURL, true) //get list of versions + // Set list all true - all versions including beta and rc will be displayed + tflist, _ := lib.GetTFList(mirrorURL, true) // Get list of versions exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it if exist { @@ -166,10 +166,10 @@ func installVersion(arg, customBinaryPath, mirrorURL string) { /* listAll = true - all versions including beta and rc will be displayed */ /* listAll = false - only official stable release are displayed */ func installOption(listAll bool, customBinaryPath, mirrorURL string) { - tflist, _ := lib.GetTFList(mirrorURL, listAll) //get list of versions - recentVersions, _ := lib.GetRecentVersions() //get recent versions from RECENT file - tflist = append(recentVersions, tflist...) //append recent versions to the top of the list - tflist = lib.RemoveDuplicateVersions(tflist) //remove duplicate version + tflist, _ := lib.GetTFList(mirrorURL, listAll) // Get list of versions + recentVersions, _ := lib.GetRecentVersions() // Get recent versions from RECENT file + tflist = append(recentVersions, tflist...) // Append recent versions to the top of the list + tflist = lib.RemoveDuplicateVersions(tflist) // Remove duplicate version if len(tflist) == 0 { logger.Fatalf("Terraform version list is empty: %s", *mirrorURL) From f2faf5f18bfd914211c546b4c58833a86f43e402 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 4 Apr 2024 16:58:50 +0200 Subject: [PATCH 07/49] - try to use terragrunt parser --- go.mod | 66 ++++++++++++++++++-- lib/param_parsing/terragrunt.go | 44 ++++++++----- test-data/test_terragrunt_hcl/terragrunt.hcl | 15 +++++ 3 files changed, 107 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 709ee2d2..b0379427 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ 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 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/go-homedir v1.1.0 @@ -16,9 +15,49 @@ require ( ) require ( - github.com/agext/levenshtein v1.2.2 // indirect - github.com/apparentlymart/go-textseg v1.0.0 // indirect + cloud.google.com/go v0.111.0 // indirect + cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/kms v1.15.5 // indirect + cloud.google.com/go/storage v1.35.1 // indirect + filippo.io/age v1.1.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-cidr v1.1.0 // indirect + github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/apparentlymart/go-versions v1.0.1 // indirect + github.com/aws/aws-sdk-go v1.50.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.21.1 // indirect + github.com/aws/aws-sdk-go-v2/config v1.18.44 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.42 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.42 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.44 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.36 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.24.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.15.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.23.1 // indirect + github.com/aws/smithy-go v1.15.0 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/blang/semver v3.5.1+incompatible // indirect + github.com/bmatcuk/doublestar v1.1.5 // indirect + github.com/cenkalti/backoff/v3 v3.2.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect + github.com/cloudflare/circl v1.3.7 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/creack/pty v1.1.17 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.15.0 // 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 @@ -27,11 +66,22 @@ require ( 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 - github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-zglob v0.0.3 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/panicwrap v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -46,6 +96,14 @@ require ( 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 + golang.org/x/time v0.5.0 // indirect + google.golang.org/api v0.153.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/grpc v1.61.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index 77a519cb..f94e3adf 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -1,9 +1,10 @@ package param_parsing import ( + "context" "fmt" - "github.com/hashicorp/hcl2/gohcl" - "github.com/hashicorp/hcl2/hclparse" + "github.com/gruntwork-io/terragrunt/config" + "github.com/gruntwork-io/terragrunt/options" "github.com/warrensbox/terraform-switcher/lib" "log" ) @@ -18,21 +19,36 @@ func GetVersionFromTerragrunt(params Params) Params { filePath := params.ChDirPath + "/" + terraGruntFileName if lib.CheckFileExist(filePath) { fmt.Printf("Reading configuration from %s\n", filePath) - parser := hclparse.NewParser() - hclFile, diagnostics := parser.ParseHCLFile(filePath) - if diagnostics.HasErrors() { - log.Fatal("Unable to parse HCL file", filePath) - } - var versionFromTerragrunt terragruntVersionConstraints - diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) - if diagnostics.HasErrors() { - log.Fatal("Could not decode body of HCL file.") + optionsWithConfigPath, err := options.NewTerragruntOptionsWithConfigPath(filePath) + if err != nil { + log.Fatal(err) } - version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) + ctx := config.NewParsingContext(context.Background(), optionsWithConfigPath) + configFile, err := config.PartialParseConfigFile(ctx, filePath, nil) if err != nil { - log.Fatal("Could not determine semantic version") + log.Fatal(err) } - params.Version = version + fmt.Printf(configFile.TerraformVersionConstraint) + + //tgConfig, err := config.PartialParseConfigFile(filePath, &options.TerragruntOptions{ + // TerragruntConfigPath: filePath, + // MaxFoldersToCheck: 10, + //}, config.TerragruntVersionConstraints) + //parser := hclparse.NewParser() + //hclFile, diagnostics := parser.ParseHCLFile(filePath) + //if diagnostics.HasErrors() { + // log.Fatal("Unable to parse HCL file", filePath) + //} + //var versionFromTerragrunt terragruntVersionConstraints + //diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) + //if diagnostics.HasErrors() { + // log.Fatal("Could not decode body of HCL file.") + //} + //version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) + //if err != nil { + // log.Fatal("Could not determine semantic version") + //} + //params.Version = version } return params } diff --git a/test-data/test_terragrunt_hcl/terragrunt.hcl b/test-data/test_terragrunt_hcl/terragrunt.hcl index 9237b428..1ad73c86 100644 --- a/test-data/test_terragrunt_hcl/terragrunt.hcl +++ b/test-data/test_terragrunt_hcl/terragrunt.hcl @@ -1 +1,16 @@ +include { + path = "${find_in_parent_folders()}" +} + +terraform { + source = "..." + + extra_arguments "variables" { + commands = get_terraform_commands_that_need_vars() + } +} +inputs = merge( + jsondecode(file("${find_in_parent_folders("general.tfvars")}")) +) + terraform_version_constraint = ">= 0.13, < 0.14" From 9e61257764160dc94ea1f612c91372dd1e41fac7 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 4 Apr 2024 22:06:21 +0200 Subject: [PATCH 08/49] Revert "- try to use terragrunt parser" This reverts commit 9a8e6c1411ec4fb3e826d1e8c3b6519198b7aec8. --- go.mod | 144 +++++++++---------- lib/param_parsing/terragrunt.go | 44 ++---- test-data/test_terragrunt_hcl/terragrunt.hcl | 15 -- 3 files changed, 85 insertions(+), 118 deletions(-) diff --git a/go.mod b/go.mod index b0379427..5a2912f4 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ 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 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/go-homedir v1.1.0 @@ -15,95 +16,92 @@ require ( ) require ( - cloud.google.com/go v0.111.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/kms v1.15.5 // indirect - cloud.google.com/go/storage v1.35.1 // indirect - filippo.io/age v1.1.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect - github.com/agext/levenshtein v1.2.3 // indirect - github.com/apparentlymart/go-cidr v1.1.0 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/apparentlymart/go-versions v1.0.1 // indirect - github.com/aws/aws-sdk-go v1.50.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.21.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.18.44 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.42 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.12 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.42 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.44 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.36 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.24.6 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.15.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.23.1 // indirect - github.com/aws/smithy-go v1.15.0 // indirect - github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect - github.com/blang/semver v3.5.1+incompatible // indirect - github.com/bmatcuk/doublestar v1.1.5 // indirect - github.com/cenkalti/backoff/v3 v3.2.2 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/agext/levenshtein v1.2.2 // indirect + github.com/apparentlymart/go-textseg v1.0.0 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect - github.com/cloudflare/circl v1.3.7 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/creack/pty v1.1.17 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fatih/color v1.15.0 // 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/getsops/gopgagent v0.0.0-20170926210634-4d7ea76ff71a // indirect + github.com/getsops/sops/v3 v3.8.1 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-jose/go-jose/v3 v3.0.3 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang-jwt/jwt/v5 v5.0.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/gruntwork-io/go-commons v0.17.1 // indirect + github.com/gruntwork-io/gruntwork-cli v0.7.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/hcl v1.0.1-vault // indirect + github.com/hashicorp/hcl/v2 v2.17.0 // indirect + github.com/hashicorp/terraform v0.15.3 // indirect + github.com/hashicorp/terraform-svchost v0.0.1 // indirect + github.com/hashicorp/vault/api v1.10.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/mattn/go-zglob v0.0.3 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/panicwrap v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect 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/stretchr/testify v1.8.4 // 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 + github.com/ulikunitz/xz v0.5.11 // indirect + github.com/urfave/cli v1.22.14 // indirect + github.com/urfave/cli/v2 v2.26.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/zclconf/go-cty v1.13.2 // indirect + github.com/zclconf/go-cty-yaml v1.0.3 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/otel v1.23.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.23.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.23.1 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.23.1 // indirect + go.opentelemetry.io/otel/sdk v1.23.1 // indirect + go.opentelemetry.io/otel/sdk/metric v1.23.1 // indirect + go.opentelemetry.io/otel/trace v1.23.1 // indirect + go.opentelemetry.io/proto/otlp 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-20231006140011-7918f672742d // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sync v0.5.0 // indirect + golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.5.0 // indirect - google.golang.org/api v0.153.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/grpc v1.61.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index f94e3adf..77a519cb 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -1,10 +1,9 @@ package param_parsing import ( - "context" "fmt" - "github.com/gruntwork-io/terragrunt/config" - "github.com/gruntwork-io/terragrunt/options" + "github.com/hashicorp/hcl2/gohcl" + "github.com/hashicorp/hcl2/hclparse" "github.com/warrensbox/terraform-switcher/lib" "log" ) @@ -19,36 +18,21 @@ func GetVersionFromTerragrunt(params Params) Params { filePath := params.ChDirPath + "/" + terraGruntFileName if lib.CheckFileExist(filePath) { fmt.Printf("Reading configuration from %s\n", filePath) - optionsWithConfigPath, err := options.NewTerragruntOptionsWithConfigPath(filePath) - if err != nil { - log.Fatal(err) + parser := hclparse.NewParser() + hclFile, diagnostics := parser.ParseHCLFile(filePath) + if diagnostics.HasErrors() { + log.Fatal("Unable to parse HCL file", filePath) + } + var versionFromTerragrunt terragruntVersionConstraints + diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) + if diagnostics.HasErrors() { + log.Fatal("Could not decode body of HCL file.") } - ctx := config.NewParsingContext(context.Background(), optionsWithConfigPath) - configFile, err := config.PartialParseConfigFile(ctx, filePath, nil) + version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) if err != nil { - log.Fatal(err) + log.Fatal("Could not determine semantic version") } - fmt.Printf(configFile.TerraformVersionConstraint) - - //tgConfig, err := config.PartialParseConfigFile(filePath, &options.TerragruntOptions{ - // TerragruntConfigPath: filePath, - // MaxFoldersToCheck: 10, - //}, config.TerragruntVersionConstraints) - //parser := hclparse.NewParser() - //hclFile, diagnostics := parser.ParseHCLFile(filePath) - //if diagnostics.HasErrors() { - // log.Fatal("Unable to parse HCL file", filePath) - //} - //var versionFromTerragrunt terragruntVersionConstraints - //diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) - //if diagnostics.HasErrors() { - // log.Fatal("Could not decode body of HCL file.") - //} - //version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) - //if err != nil { - // log.Fatal("Could not determine semantic version") - //} - //params.Version = version + params.Version = version } return params } diff --git a/test-data/test_terragrunt_hcl/terragrunt.hcl b/test-data/test_terragrunt_hcl/terragrunt.hcl index 1ad73c86..9237b428 100644 --- a/test-data/test_terragrunt_hcl/terragrunt.hcl +++ b/test-data/test_terragrunt_hcl/terragrunt.hcl @@ -1,16 +1 @@ -include { - path = "${find_in_parent_folders()}" -} - -terraform { - source = "..." - - extra_arguments "variables" { - commands = get_terraform_commands_that_need_vars() - } -} -inputs = merge( - jsondecode(file("${find_in_parent_folders("general.tfvars")}")) -) - terraform_version_constraint = ">= 0.13, < 0.14" From b248c9e650c5ed4b536c5fff2cf5faee3336dd06 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 19:54:05 +0200 Subject: [PATCH 09/49] - rebase --- go.mod | 73 ++++++++------------------------------------------------- main.go | 2 +- 2 files changed, 11 insertions(+), 64 deletions(-) diff --git a/go.mod b/go.mod index 5a2912f4..db624848 100644 --- a/go.mod +++ b/go.mod @@ -16,92 +16,39 @@ require ( ) require ( - github.com/agext/levenshtein v1.2.2 // indirect + github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg v1.0.0 // indirect + github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/getsops/gopgagent v0.0.0-20170926210634-4d7ea76ff71a // indirect - github.com/getsops/sops/v3 v3.8.1 // indirect - github.com/go-errors/errors v1.4.2 // indirect - github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-logr/logr v1.4.1 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang-jwt/jwt/v5 v5.0.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect - github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect - github.com/gruntwork-io/go-commons v0.17.1 // indirect - github.com/gruntwork-io/gruntwork-cli v0.7.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.1 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.1 // indirect - github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect - github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-uuid v1.0.3 // 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.1-vault // indirect github.com/hashicorp/hcl/v2 v2.17.0 // indirect - github.com/hashicorp/terraform v0.15.3 // indirect - github.com/hashicorp/terraform-svchost v0.0.1 // indirect - github.com/hashicorp/vault/api v1.10.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.17.0 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect 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.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect - github.com/urfave/cli v1.22.14 // indirect - github.com/urfave/cli/v2 v2.26.0 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // 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.13.2 // indirect - github.com/zclconf/go-cty-yaml v1.0.3 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.23.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.23.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.23.1 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.23.1 // indirect - go.opentelemetry.io/otel/sdk v1.23.1 // indirect - go.opentelemetry.io/otel/sdk/metric v1.23.1 // indirect - go.opentelemetry.io/otel/trace v1.23.1 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/main.go b/main.go index 872101d5..f4c5dfd9 100644 --- a/main.go +++ b/main.go @@ -172,7 +172,7 @@ func installOption(listAll bool, customBinaryPath, mirrorURL string) { tflist = lib.RemoveDuplicateVersions(tflist) // Remove duplicate version if len(tflist) == 0 { - logger.Fatalf("Terraform version list is empty: %s", *mirrorURL) + logger.Fatalf("Terraform version list is empty: %s", mirrorURL) os.Exit(1) } From 43395655a15b315062f8b36c3554a728f247c6bd Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 20:12:01 +0200 Subject: [PATCH 10/49] - adapt to logging --- lib/defaults.go | 5 +++++ lib/param_parsing/parameters.go | 21 +++++++++------------ lib/param_parsing/terraform_version.go | 7 +++---- lib/param_parsing/terragrunt.go | 14 ++++++++------ lib/param_parsing/tfswitch.go | 7 +++---- lib/param_parsing/toml.go | 10 +++++----- lib/param_parsing/versiontf.go | 8 +++----- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/lib/defaults.go b/lib/defaults.go index 2bf1f297..586cbbcf 100644 --- a/lib/defaults.go +++ b/lib/defaults.go @@ -30,3 +30,8 @@ func GetDefaultBin() string { } return defaultBin } + +const ( + DefaultMirror = "https://releases.hashicorp.com/terraform" + DefaultLatest = "" +) diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 2c0cda19..53e7f97f 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -24,10 +24,7 @@ type Params struct { VersionFlag bool } -const ( - defaultMirror = "https://releases.hashicorp.com/terraform" - defaultLatest = "" -) +var logger = lib.InitLogger() func GetParameters() Params { var params Params @@ -41,7 +38,7 @@ func GetParameters() Params { getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") - getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+defaultMirror) + getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+lib.DefaultMirror) getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") @@ -78,17 +75,17 @@ func GetParameters() Params { func initParams(params Params) Params { params.ChDirPath = lib.GetCurrentDirectory() params.CustomBinaryPath = lib.ConvertExecutableExt(lib.GetDefaultBin()) - params.DefaultVersion = defaultLatest + params.DefaultVersion = lib.DefaultLatest params.HelpFlag = false params.LatestFlag = false - params.LatestPre = defaultLatest - params.LatestStable = defaultLatest + params.LatestPre = lib.DefaultLatest + params.LatestStable = lib.DefaultLatest params.ListAllFlag = false - params.MirrorURL = defaultMirror + params.MirrorURL = lib.DefaultMirror params.ShowLatestFlag = false - params.ShowLatestPre = defaultLatest - params.ShowLatestStable = defaultLatest - params.Version = defaultLatest + params.ShowLatestPre = lib.DefaultLatest + params.ShowLatestStable = lib.DefaultLatest + params.Version = lib.DefaultLatest params.VersionFlag = false return params } diff --git a/lib/param_parsing/terraform_version.go b/lib/param_parsing/terraform_version.go index 2e3df088..e072d496 100644 --- a/lib/param_parsing/terraform_version.go +++ b/lib/param_parsing/terraform_version.go @@ -1,9 +1,7 @@ package param_parsing import ( - "fmt" "github.com/warrensbox/terraform-switcher/lib" - "log" "os" "strings" ) @@ -13,10 +11,11 @@ const terraformVersionFileName = ".terraform-version" func GetParamsFromTerraformVersion(params Params) Params { filePath := params.ChDirPath + "/" + terraformVersionFileName if lib.CheckFileExist(filePath) { - fmt.Printf("Reading configuration from %s\n", filePath) + logger.Infof("Reading configuration from %s", filePath) content, err := os.ReadFile(filePath) if err != nil { - log.Fatal("Could not read file content", filePath, err) + logger.Errorf("Could not read file content at %s:%v", filePath, err) + os.Exit(1) } params.Version = strings.TrimSpace(string(content)) } diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index 77a519cb..c233573f 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -1,11 +1,10 @@ package param_parsing import ( - "fmt" "github.com/hashicorp/hcl2/gohcl" "github.com/hashicorp/hcl2/hclparse" "github.com/warrensbox/terraform-switcher/lib" - "log" + "os" ) const terraGruntFileName = "terragrunt.hcl" @@ -17,20 +16,23 @@ type terragruntVersionConstraints struct { func GetVersionFromTerragrunt(params Params) Params { filePath := params.ChDirPath + "/" + terraGruntFileName if lib.CheckFileExist(filePath) { - fmt.Printf("Reading configuration from %s\n", filePath) + logger.Infof("Reading configuration from %s", filePath) parser := hclparse.NewParser() hclFile, diagnostics := parser.ParseHCLFile(filePath) if diagnostics.HasErrors() { - log.Fatal("Unable to parse HCL file", filePath) + logger.Fatalf("Unable to parse HCL file %s", filePath) + os.Exit(1) } var versionFromTerragrunt terragruntVersionConstraints diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) if diagnostics.HasErrors() { - log.Fatal("Could not decode body of HCL file.") + logger.Fatal("Could not decode body of HCL file.") + os.Exit(1) } version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) if err != nil { - log.Fatal("Could not determine semantic version") + logger.Fatal("Could not determine semantic version") + os.Exit(1) } params.Version = version } diff --git a/lib/param_parsing/tfswitch.go b/lib/param_parsing/tfswitch.go index db537191..c027239c 100644 --- a/lib/param_parsing/tfswitch.go +++ b/lib/param_parsing/tfswitch.go @@ -1,9 +1,7 @@ package param_parsing import ( - "fmt" "github.com/warrensbox/terraform-switcher/lib" - "log" "os" "strings" ) @@ -13,10 +11,11 @@ const tfSwitchFileName = ".tfswitchrc" func GetParamsFromTfSwitch(params Params) Params { filePath := params.ChDirPath + "/" + tfSwitchFileName if lib.CheckFileExist(filePath) { - fmt.Printf("Reading configuration from %s\n", filePath) + logger.Infof("Reading configuration from %s", filePath) content, err := os.ReadFile(filePath) if err != nil { - log.Fatal("Could not read file content", filePath, err) + logger.Fatalf("Could not read file content %s: %v", filePath, err) + os.Exit(1) } params.Version = strings.TrimSpace(string(content)) } diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 4486bb37..203739eb 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -1,10 +1,9 @@ package param_parsing import ( - "fmt" "github.com/spf13/viper" "github.com/warrensbox/terraform-switcher/lib" - "log" + "os" ) const tfSwitchTOMLFileName = ".tfswitch.toml" @@ -13,7 +12,7 @@ const tfSwitchTOMLFileName = ".tfswitch.toml" func getParamsTOML(params Params) Params { tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName if tomlFileExists(params) { - fmt.Printf("Reading configuration from %s\n", tomlPath) + logger.Infof("Reading configuration from %s", tomlPath) configfileName := lib.GetFileName(tfSwitchTOMLFileName) viperParser := viper.New() viperParser.SetConfigType("toml") @@ -22,13 +21,14 @@ func getParamsTOML(params Params) Params { errs := viperParser.ReadInConfig() // Find and read the config file if errs != nil { - log.Fatalf("Unable to read %s provided\n", tomlPath) + logger.Fatalf("Unable to read %s provided", tomlPath) + os.Exit(1) } params.Version = viperParser.GetString("version") // Attempt to get the version if it's provided in the toml params.CustomBinaryPath = viperParser.GetString("bin") } else { - fmt.Println("No configuration file at " + tomlPath) + logger.Infof("No configuration file at %s", tomlPath) } return params } diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index b759cae8..af3fbf32 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -1,10 +1,8 @@ package param_parsing import ( - "fmt" "github.com/hashicorp/terraform-config-inspect/tfconfig" "github.com/warrensbox/terraform-switcher/lib" - "log" ) const versionTfFileName = "version.tf" @@ -12,15 +10,15 @@ const versionTfFileName = "version.tf" func GetVersionFromVersionsTF(params Params) Params { filePath := params.ChDirPath + "/" + versionTfFileName if lib.CheckFileExist(filePath) { - fmt.Printf("Reading version from %s\n", filePath) + logger.Infof("Reading version from %s", filePath) module, err := tfconfig.LoadModule(params.ChDirPath) if err != nil { - log.Fatal("Could not load terraform module") + logger.Fatal("Could not load terraform module") } tfconstraint := module.RequiredCore[0] version, err2 := lib.GetSemver(tfconstraint, params.MirrorURL) if err2 != nil { - log.Fatal("Could not determine semantic version") + logger.Fatal("Could not determine semantic version") } params.Version = version } From f79fa5b51b90970b7c5c6676da021f6d4fef006f Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 20:36:24 +0200 Subject: [PATCH 11/49] - move defaults --- lib/defaults.go | 9 +++++++-- lib/install.go | 9 --------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/defaults.go b/lib/defaults.go index 586cbbcf..95ec57ad 100644 --- a/lib/defaults.go +++ b/lib/defaults.go @@ -32,6 +32,11 @@ func GetDefaultBin() string { } const ( - DefaultMirror = "https://releases.hashicorp.com/terraform" - DefaultLatest = "" + DefaultMirror = "https://releases.hashicorp.com/terraform" + DefaultLatest = "" + installFile = "terraform" + versionPrefix = "terraform_" + installPath = ".terraform.versions" + recentFile = "RECENT" + tfDarwinArm64StartVersion = "1.0.2" ) diff --git a/lib/install.go b/lib/install.go index 2c37c4a4..fc19e0e9 100644 --- a/lib/install.go +++ b/lib/install.go @@ -11,15 +11,6 @@ import ( "github.com/mitchellh/go-homedir" ) -const ( - installFile = "terraform" - versionPrefix = "terraform_" - installPath = ".terraform.versions" - recentFile = "RECENT" - defaultBin = "/usr/local/bin/terraform" //default bin installation dir - tfDarwinArm64StartVersion = "1.0.2" -) - var ( installLocation = "/tmp" ) From 3eb7618f428a3679d792a17a01461b86cf112be9 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 21:38:46 +0200 Subject: [PATCH 12/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- lib/param_parsing/terraform_version.go | 4 ++-- lib/param_parsing/terragrunt.go | 8 ++++---- lib/param_parsing/tfswitch.go | 4 ++-- lib/param_parsing/toml.go | 2 +- lib/param_parsing/versiontf.go | 6 ++++-- main.go | 4 ++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/param_parsing/terraform_version.go b/lib/param_parsing/terraform_version.go index e072d496..6ad6c60d 100644 --- a/lib/param_parsing/terraform_version.go +++ b/lib/param_parsing/terraform_version.go @@ -11,10 +11,10 @@ const terraformVersionFileName = ".terraform-version" func GetParamsFromTerraformVersion(params Params) Params { filePath := params.ChDirPath + "/" + terraformVersionFileName if lib.CheckFileExist(filePath) { - logger.Infof("Reading configuration from %s", filePath) + logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) if err != nil { - logger.Errorf("Could not read file content at %s:%v", filePath, err) + logger.Errorf("Could not read file content at %q: %v", filePath, err) os.Exit(1) } params.Version = strings.TrimSpace(string(content)) diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index c233573f..22e78427 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -16,22 +16,22 @@ type terragruntVersionConstraints struct { func GetVersionFromTerragrunt(params Params) Params { filePath := params.ChDirPath + "/" + terraGruntFileName if lib.CheckFileExist(filePath) { - logger.Infof("Reading configuration from %s", filePath) + logger.Infof("Reading configuration from %q", filePath) parser := hclparse.NewParser() hclFile, diagnostics := parser.ParseHCLFile(filePath) if diagnostics.HasErrors() { - logger.Fatalf("Unable to parse HCL file %s", filePath) + logger.Fatalf("Unable to parse HCL file %q", filePath) os.Exit(1) } var versionFromTerragrunt terragruntVersionConstraints diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) if diagnostics.HasErrors() { - logger.Fatal("Could not decode body of HCL file.") + logger.Fatalf("Could not decode body of HCL file %q", filePath) os.Exit(1) } version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) if err != nil { - logger.Fatal("Could not determine semantic version") + logger.Fatalf("No version found matching %q", versionFromTerragrunt.TerraformVersionConstraint) os.Exit(1) } params.Version = version diff --git a/lib/param_parsing/tfswitch.go b/lib/param_parsing/tfswitch.go index c027239c..8c033a5f 100644 --- a/lib/param_parsing/tfswitch.go +++ b/lib/param_parsing/tfswitch.go @@ -11,10 +11,10 @@ const tfSwitchFileName = ".tfswitchrc" func GetParamsFromTfSwitch(params Params) Params { filePath := params.ChDirPath + "/" + tfSwitchFileName if lib.CheckFileExist(filePath) { - logger.Infof("Reading configuration from %s", filePath) + logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) if err != nil { - logger.Fatalf("Could not read file content %s: %v", filePath, err) + logger.Fatalf("Could not read file content from %q: %v", filePath, err) os.Exit(1) } params.Version = strings.TrimSpace(string(content)) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 203739eb..275a9ca2 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -12,7 +12,7 @@ const tfSwitchTOMLFileName = ".tfswitch.toml" func getParamsTOML(params Params) Params { tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName if tomlFileExists(params) { - logger.Infof("Reading configuration from %s", tomlPath) + logger.Infof("Reading configuration from %q", tomlPath) configfileName := lib.GetFileName(tfSwitchTOMLFileName) viperParser := viper.New() viperParser.SetConfigType("toml") diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index af3fbf32..6624fda4 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -10,15 +10,17 @@ const versionTfFileName = "version.tf" func GetVersionFromVersionsTF(params Params) Params { filePath := params.ChDirPath + "/" + versionTfFileName if lib.CheckFileExist(filePath) { - logger.Infof("Reading version from %s", filePath) + logger.Infof("Reading version from %q", filePath) module, err := tfconfig.LoadModule(params.ChDirPath) if err != nil { logger.Fatal("Could not load terraform module") + os.Exit(1) } tfconstraint := module.RequiredCore[0] version, err2 := lib.GetSemver(tfconstraint, params.MirrorURL) if err2 != nil { - logger.Fatal("Could not determine semantic version") + logger.Fatalf("No version found matching %q", tfconstraint) + os.Exit(1) } params.Version = version } diff --git a/main.go b/main.go index f4c5dfd9..95fd61ce 100644 --- a/main.go +++ b/main.go @@ -142,10 +142,10 @@ func installVersion(arg, customBinaryPath, mirrorURL string) { os.Exit(0) } - //if the requested version had not been downloaded before + // If the requested version had not been downloaded before // Set list all true - all versions including beta and rc will be displayed tflist, _ := lib.GetTFList(mirrorURL, true) // Get list of versions - exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it + exist := lib.VersionExist(requestedVersion, tflist) // Check if version exists before downloading it if exist { lib.Install(requestedVersion, customBinaryPath, mirrorURL) From 687b9ec5f8844ffea54996f83523a9a67b6d3131 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 21:41:48 +0200 Subject: [PATCH 13/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- lib/param_parsing/toml.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 275a9ca2..dd729ab9 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -21,7 +21,7 @@ func getParamsTOML(params Params) Params { errs := viperParser.ReadInConfig() // Find and read the config file if errs != nil { - logger.Fatalf("Unable to read %s provided", tomlPath) + logger.Fatalf("Could not to read %q: %v", tomlPath, errs) os.Exit(1) } From 9d5d479012a576d172835150b37acbdb0728cb8f Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 21:42:08 +0200 Subject: [PATCH 14/49] - apply suggested changes --- lib/defaults.go | 2 +- lib/param_parsing/toml.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/defaults.go b/lib/defaults.go index 95ec57ad..aeee0137 100644 --- a/lib/defaults.go +++ b/lib/defaults.go @@ -35,8 +35,8 @@ const ( DefaultMirror = "https://releases.hashicorp.com/terraform" DefaultLatest = "" installFile = "terraform" - versionPrefix = "terraform_" installPath = ".terraform.versions" recentFile = "RECENT" tfDarwinArm64StartVersion = "1.0.2" + versionPrefix = "terraform_" ) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index dd729ab9..68c86664 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -28,7 +28,7 @@ func getParamsTOML(params Params) Params { params.Version = viperParser.GetString("version") // Attempt to get the version if it's provided in the toml params.CustomBinaryPath = viperParser.GetString("bin") } else { - logger.Infof("No configuration file at %s", tomlPath) + logger.Debugf("No configuration file at %q", tomlPath) } return params } From 763c30a9b7fb9b73a33ef564f7d0990161f970c7 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 21:45:52 +0200 Subject: [PATCH 15/49] - apply suggested changes --- lib/defaults.go | 2 +- lib/install.go | 5 +++-- lib/param_parsing/versiontf.go | 1 + main.go | 8 +------- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/defaults.go b/lib/defaults.go index aeee0137..bdcde1c0 100644 --- a/lib/defaults.go +++ b/lib/defaults.go @@ -38,5 +38,5 @@ const ( installPath = ".terraform.versions" recentFile = "RECENT" tfDarwinArm64StartVersion = "1.0.2" - versionPrefix = "terraform_" + VersionPrefix = "terraform_" ) diff --git a/lib/install.go b/lib/install.go index fc19e0e9..be04f434 100644 --- a/lib/install.go +++ b/lib/install.go @@ -83,7 +83,7 @@ func Install(tfversion string, binPath string, mirrorURL string) { } /* check if selected version already downloaded */ - installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, versionPrefix+tfversion)) + installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, VersionPrefix+tfversion)) fileExist := CheckFileExist(installFileVersionPath) /* if selected version already exist, */ @@ -111,7 +111,8 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* if selected version already exist, */ /* proceed to download it from the hashicorp release page */ - zipFile, errDownload := DownloadFromURL(installLocation, mirrorURL, tfversion, versionPrefix, goos, goarch) + url := mirrorURL + tfversion + "/" + VersionPrefix + tfversion + "_" + goos + "_" + goarch + ".zip" + zipFile, errDownload := DownloadFromURL(installLocation, url) /* If unable to download file from url, exit(1) immediately */ if errDownload != nil { diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index 6624fda4..4e1c5ab7 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -3,6 +3,7 @@ package param_parsing import ( "github.com/hashicorp/terraform-config-inspect/tfconfig" "github.com/warrensbox/terraform-switcher/lib" + "os" ) const versionTfFileName = "version.tf" diff --git a/main.go b/main.go index 95fd61ce..8d4ae57e 100644 --- a/main.go +++ b/main.go @@ -29,12 +29,6 @@ import ( lib "github.com/warrensbox/terraform-switcher/lib" ) -const ( - tfvFilename = ".terraform-version" - - versionPrefix = "terraform_" -) - var logger = lib.InitLogger() var version string @@ -133,7 +127,7 @@ func installVersion(arg, customBinaryPath, mirrorURL string) { //check to see if the requested version has been downloaded before installLocation := lib.GetInstallLocation() - installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(installLocation, versionPrefix+requestedVersion)) + installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(installLocation, lib.VersionPrefix+requestedVersion)) recentDownloadFile := lib.CheckFileExist(installFileVersionPath) if recentDownloadFile { lib.ChangeSymlink(installFileVersionPath, customBinaryPath) From ec776ab817db09e84e36c5e93b6412bf628b7739 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 21:58:04 +0200 Subject: [PATCH 16/49] - remove unnecessary logging --- lib/param_parsing/toml.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 68c86664..490a5ef7 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -27,8 +27,6 @@ func getParamsTOML(params Params) Params { params.Version = viperParser.GetString("version") // Attempt to get the version if it's provided in the toml params.CustomBinaryPath = viperParser.GetString("bin") - } else { - logger.Debugf("No configuration file at %q", tomlPath) } return params } From 32f7185b2815dab06486e78bfa61fc290ef4dafe Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 22:01:09 +0200 Subject: [PATCH 17/49] - rebased and updated vulnerable dependencies --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index db624848..71a28e85 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect From 2af831f3b7ff54bb4fdc466d4ad760315c1da8df Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 22:28:24 +0200 Subject: [PATCH 18/49] - update dependencies --- go.mod | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 71a28e85..41e9a62c 100644 --- a/go.mod +++ b/go.mod @@ -18,20 +18,20 @@ require ( require ( github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg v1.0.0 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/google/go-cmp v0.6.0 // 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.1-vault // indirect - github.com/hashicorp/hcl/v2 v2.17.0 // indirect + github.com/hashicorp/hcl v1.0.1-vault-5 // indirect + github.com/hashicorp/hcl/v2 v2.20.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -41,13 +41,13 @@ require ( 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.13.2 // 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/sync v0.5.0 // indirect - golang.org/x/term v0.19.0 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.20.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect From 02b03ff95c1372cf54a0e2d591203286b6be4131 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 5 Apr 2024 22:36:22 +0200 Subject: [PATCH 19/49] - fix parameters for DownloadFromURL --- lib/install.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/install.go b/lib/install.go index be04f434..d38f1d5a 100644 --- a/lib/install.go +++ b/lib/install.go @@ -111,8 +111,7 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* if selected version already exist, */ /* proceed to download it from the hashicorp release page */ - url := mirrorURL + tfversion + "/" + VersionPrefix + tfversion + "_" + goos + "_" + goarch + ".zip" - zipFile, errDownload := DownloadFromURL(installLocation, url) + zipFile, errDownload := DownloadFromURL(installLocation, mirrorURL, tfversion, VersionPrefix, goos, goarch) /* If unable to download file from url, exit(1) immediately */ if errDownload != nil { From c5c1cd91bec0360e81f1ceb0f86f331ac37d2e47 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Sun, 7 Apr 2024 20:19:54 +0200 Subject: [PATCH 20/49] - remove fatal loggings from tests. Relates to #363 --- lib/download_test.go | 6 +++--- lib/files_test.go | 40 +++++++++++++++++++-------------------- lib/install_test.go | 16 ---------------- lib/list_versions_test.go | 31 +++++++++++++++--------------- lib/symlink_test.go | 16 ++++++++-------- main.go | 1 - 6 files changed, 46 insertions(+), 64 deletions(-) diff --git a/lib/download_test.go b/lib/download_test.go index e10daf0f..b0d60d1d 100644 --- a/lib/download_test.go +++ b/lib/download_test.go @@ -25,14 +25,14 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { logger.Fatalf("Could not detect home directory") } - logger.Infof("Current home directory: %q", home) + t.Logf("Current home directory: %q", home) var installLocation = "" if runtime.GOOS != "windows" { installLocation = filepath.Join(home, installPath) } else { installLocation = installPath } - logger.Infof("Install Location: %v", installLocation) + t.Logf("Install Location: %v", installLocation) // create /.terraform.versions_test/ directory to store code if _, err := os.Stat(installLocation); os.IsNotExist(err) { @@ -74,7 +74,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { t.Cleanup(func() { defer os.Remove(tempDir) - logger.Infof("Cleanup temporary directory %q", tempDir) + t.Logf("Cleanup temporary directory %q", tempDir) }) } diff --git a/lib/files_test.go b/lib/files_test.go index 7f59a9d1..2e2e8903 100644 --- a/lib/files_test.go +++ b/lib/files_test.go @@ -25,7 +25,7 @@ func TestRenameFile(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -71,7 +71,7 @@ func TestRemoveFiles(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -106,11 +106,11 @@ func TestUnzip(t *testing.T) { installPath := "/.terraform.versions_test/" absPath, _ := filepath.Abs("../test-data/test-data.zip") - logger.Infof("Absolute Path: %q", absPath) + t.Logf("Absolute Path: %q", absPath) homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -119,7 +119,7 @@ func TestUnzip(t *testing.T) { files, errUnzip := Unzip(absPath, installLocation) if errUnzip != nil { - logger.Fatalf("Unable to unzip %q file: %v", absPath, errUnzip) + t.Errorf("Unable to unzip %q file: %v", absPath, errUnzip) } tst := strings.Join(files, "") @@ -140,7 +140,7 @@ func TestCreateDirIfNotExist(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -175,7 +175,7 @@ func TestWriteLines(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -188,7 +188,7 @@ func TestWriteLines(t *testing.T) { if errWrite != nil { t.Logf("Write should work %v (unexpected)", errWrite) - logger.Fatal(errWrite) + t.Error(errWrite) } else { var ( file *os.File @@ -198,7 +198,7 @@ func TestWriteLines(t *testing.T) { lines []string ) if file, errOpen = os.Open(recentFilePath); errOpen != nil { - logger.Fatal(errOpen) + t.Error(errOpen) } reader := bufio.NewReader(file) @@ -218,12 +218,12 @@ func TestWriteLines(t *testing.T) { } if errRead != nil { - logger.Fatalf("Error: %s", errRead) + t.Errorf("Error: %s", errRead) } for _, line := range lines { if !semverRegex.MatchString(line) { - logger.Fatalf("Write to file is not invalid: %s", line) + t.Errorf("Write to file is not invalid: %s", line) break } } @@ -243,7 +243,7 @@ func TestReadLines(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -258,13 +258,13 @@ func TestReadLines(t *testing.T) { ) if file, errCreate = os.Create(recentFilePath); errCreate != nil { - logger.Fatalf("Error: %s", errCreate) + t.Errorf("Error: %s", errCreate) } for _, item := range test_array { _, err := file.WriteString(strings.TrimSpace(item) + "\n") if err != nil { - logger.Fatalf("Error: %s", err) + t.Errorf("Error: %s", err) break } } @@ -272,12 +272,12 @@ func TestReadLines(t *testing.T) { lines, errRead := ReadLines(recentFilePath) if errRead != nil { - logger.Fatalf("Error: %s", errRead) + t.Errorf("Error: %s", errRead) } for _, line := range lines { if !semverRegex.MatchString(line) { - logger.Fatalf("Write to file is not invalid: %s", line) + t.Errorf("Write to file is not invalid: %s", line) } } @@ -295,7 +295,7 @@ func TestIsDirEmpty(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -330,7 +330,7 @@ func TestCheckDirHasTFBin(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -359,7 +359,7 @@ func TestPath(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installLocation := filepath.Join(homedir, installPath) @@ -400,7 +400,7 @@ func TestGetFileName(t *testing.T) { func TestConvertExecutableExt(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } installPath := "/.terraform.versions_test/" diff --git a/lib/install_test.go b/lib/install_test.go index 0ec6a95b..12fc1d98 100644 --- a/lib/install_test.go +++ b/lib/install_test.go @@ -1,28 +1,12 @@ package lib_test import ( - "os" "os/user" - "runtime" "testing" "github.com/mitchellh/go-homedir" ) -// TestAddRecent : Create a file, check filename exist, -// rename file, check new filename exit -func GetInstallLocation(installPath string) string { - return string(os.PathSeparator) + installPath + string(os.PathSeparator) -} - -func getInstallFile(installFile string) string { - if runtime.GOOS == "windows" { - return installFile + ".exe" - } - - return installFile -} - func TestInstall(t *testing.T) { t.Run("User should exist", diff --git a/lib/list_versions_test.go b/lib/list_versions_test.go index 6830cdb1..f23f24bd 100644 --- a/lib/list_versions_test.go +++ b/lib/list_versions_test.go @@ -12,8 +12,7 @@ const ( // TestGetTFList : Get list from hashicorp func TestGetTFList(t *testing.T) { - listAll := true - list, _ := GetTFList(hashiURL, listAll) + list, _ := GetTFList(hashiURL, true) val := "0.1.0" var exists bool @@ -30,7 +29,7 @@ func TestGetTFList(t *testing.T) { } if !exists { - logger.Fatalf("Not able to find version: %s", val) + t.Errorf("Not able to find version: %s", val) } else { t.Log("Write versions exist (expected)") } @@ -40,12 +39,12 @@ func TestGetTFList(t *testing.T) { // 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"} + testArray := []string{"0.0.1", "0.0.2", "0.0.3", "0.0.1", "0.12.0-beta1", "0.12.0-beta1"} - list := RemoveDuplicateVersions(test_array) + list := RemoveDuplicateVersions(testArray) - if len(list) == len(test_array) { - logger.Fatalf("Not able to remove duplicate: %s\n", test_array) + if len(list) == len(testArray) { + t.Errorf("Not able to remove duplicate: %s\n", testArray) } else { t.Log("Write versions exist (expected)") } @@ -63,7 +62,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "1.11.9" @@ -73,7 +72,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "1.11.a" @@ -83,7 +82,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "22323" @@ -93,7 +92,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "@^&*!)!" @@ -103,7 +102,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "1.11.9-beta1" @@ -113,7 +112,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "0.12.0-rc2" @@ -123,7 +122,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "1.11.4-boom" @@ -133,7 +132,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == true { t.Logf("Valid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } version = "1.11.4-1" @@ -143,7 +142,7 @@ func TestValidVersionFormat(t *testing.T) { if valid == false { t.Logf("Invalid version format : %s (expected)", version) } else { - logger.Fatalf("Failed to verify version format: %s\n", version) + t.Errorf("Failed to verify version format: %s\n", version) } } diff --git a/lib/symlink_test.go b/lib/symlink_test.go index baf3a55e..cf9d1123 100644 --- a/lib/symlink_test.go +++ b/lib/symlink_test.go @@ -21,7 +21,7 @@ func TestCreateSymlink(t *testing.T) { home, err := homedir.Dir() if err != nil { - logger.Fatalf("Could not detect home directory.") + t.Errorf("Could not detect home directory.") } symlinkPathSrc := filepath.Join(home, testSymlinkSrc) symlinkPathDest := filepath.Join(home, testSymlinkDest) @@ -29,7 +29,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 { - logger.Fatalf("Could not create test dest file for symlink at %v", symlinkPathDest) + t.Errorf("Could not create test dest file for symlink at %v", symlinkPathDest) } defer create.Close() @@ -40,7 +40,7 @@ func TestCreateSymlink(t *testing.T) { t.Logf("Symlink does not exist %v [expected]", ln) } else { t.Logf("Symlink exist %v [expected]", ln) - os.Remove(symlinkPathSrc) + _ = os.Remove(symlinkPathSrc) t.Logf("Removed existing symlink for testing purposes") } } @@ -65,8 +65,8 @@ func TestCreateSymlink(t *testing.T) { } } - os.Remove(symlinkPathSrc) - os.Remove(symlinkPathDest) + _ = os.Remove(symlinkPathSrc) + _ = os.Remove(symlinkPathDest) } // TestRemoveSymlink : check if symlink exist-create if does not exist, @@ -79,7 +79,7 @@ func TestRemoveSymlink(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } symlinkPathSrc := filepath.Join(homedir, testSymlinkSrc) symlinkPathDest := filepath.Join(homedir, testSymlinkDest) @@ -114,7 +114,7 @@ func TestCheckSymlink(t *testing.T) { homedir, errCurr := homedir.Dir() if errCurr != nil { - logger.Fatal(errCurr) + t.Error(errCurr) } symlinkPathSrc := filepath.Join(homedir, testSymlinkSrc) symlinkPathDest := filepath.Join(homedir, testSymlinkDest) @@ -136,5 +136,5 @@ func TestCheckSymlink(t *testing.T) { t.Logf("Symlink does not exist %v [unexpected]", ln) } - os.Remove(symlinkPathSrc) + _ = os.Remove(symlinkPathSrc) } diff --git a/main.go b/main.go index 8d4ae57e..c83e477d 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,6 @@ var version string func main() { parameters := param_parsing.GetParameters() - //defaults := lib.GetDefaults() switch { case parameters.VersionFlag: From 64ee48c4e6f0e67fb85a4283c5eb3d56761e76db Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Sun, 7 Apr 2024 20:32:48 +0200 Subject: [PATCH 21/49] - make logger exit on fatal --- lib/logging.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/logging.go b/lib/logging.go index ec38d531..deda69d5 100644 --- a/lib/logging.go +++ b/lib/logging.go @@ -3,6 +3,7 @@ package lib import ( "github.com/gookit/slog" "github.com/gookit/slog/handler" + "os" ) const loggingTemplate = "{{datetime}} {{level}} [{{caller}}] {{message}} {{data}} {{extra}}\n" @@ -18,5 +19,6 @@ func InitLogger() *slog.Logger { h := handler.NewConsoleHandler(slog.AllLevels) h.SetFormatter(formatter) logger := slog.NewWithHandlers(h) + logger.ExitFunc = os.Exit return logger } From c3659d88f7e0fe5a99228e3b81e23455c2ab51cc Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Mon, 8 Apr 2024 14:44:12 +0200 Subject: [PATCH 22/49] - rebasing --- go.sum | 71 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/go.sum b/go.sum index 992a3508..c867add2 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,21 @@ github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= -github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -25,8 +30,8 @@ github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3a github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/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/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/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= @@ -39,10 +44,10 @@ github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FK 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= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl/v2 v2.0.0 h1:efQznTz+ydmQXq3BOnRa3AXzvCeTq1P4dKj/z5GLlY8= -github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= +github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= +github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= +github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 h1:PFfGModn55JA0oBsvFghhj0v93me+Ctr3uHC/UmFAls= github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72 h1:nZ5gGjbe5o7XUu1d7j+Y5Ztcxlp+yaumTKH9i0D3wlg= @@ -50,6 +55,7 @@ github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -66,8 +72,8 @@ github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GW 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= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -75,13 +81,13 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pborman/getopt v1.1.0 h1:eJ3aFZroQqq0bWmraivjQNt6Dmm5M0h2JcDW38/Azb0= github.com/pborman/getopt v1.1.0/go.mod h1:FxXoW1Re00sQG/+KIkuSqRL/LwQgSkv7uyac+STFsbk= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -102,8 +108,8 @@ github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMV github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -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/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -117,31 +123,34 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac 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= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -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= +github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= +github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -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/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= @@ -151,11 +160,13 @@ 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= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= From 06e781751f6ec40f4ead82420dd7286c733142b3 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Mon, 8 Apr 2024 14:44:31 +0200 Subject: [PATCH 23/49] - fix logging --- lib/param_parsing/terraform_version.go | 3 +-- lib/param_parsing/terragrunt.go | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/param_parsing/terraform_version.go b/lib/param_parsing/terraform_version.go index 6ad6c60d..0e38e4d6 100644 --- a/lib/param_parsing/terraform_version.go +++ b/lib/param_parsing/terraform_version.go @@ -14,8 +14,7 @@ func GetParamsFromTerraformVersion(params Params) Params { logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) if err != nil { - logger.Errorf("Could not read file content at %q: %v", filePath, err) - os.Exit(1) + logger.Fatalf("Could not read file content at %q: %v", filePath, err) } params.Version = strings.TrimSpace(string(content)) } diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index 22e78427..ecdf75c3 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -4,7 +4,6 @@ import ( "github.com/hashicorp/hcl2/gohcl" "github.com/hashicorp/hcl2/hclparse" "github.com/warrensbox/terraform-switcher/lib" - "os" ) const terraGruntFileName = "terragrunt.hcl" @@ -21,18 +20,15 @@ func GetVersionFromTerragrunt(params Params) Params { hclFile, diagnostics := parser.ParseHCLFile(filePath) if diagnostics.HasErrors() { logger.Fatalf("Unable to parse HCL file %q", filePath) - os.Exit(1) } var versionFromTerragrunt terragruntVersionConstraints diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) if diagnostics.HasErrors() { logger.Fatalf("Could not decode body of HCL file %q", filePath) - os.Exit(1) } version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) if err != nil { logger.Fatalf("No version found matching %q", versionFromTerragrunt.TerraformVersionConstraint) - os.Exit(1) } params.Version = version } From 8210443fadc246b6348ad442ad70fdfb65ff0f2e Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Mon, 8 Apr 2024 14:55:04 +0200 Subject: [PATCH 24/49] - don't rely on the terraform module file --- lib/param_parsing/parameters.go | 2 +- lib/param_parsing/parameters_test.go | 1 + lib/param_parsing/versiontf.go | 32 +++++++++++----------------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 53e7f97f..41bca82b 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -54,7 +54,7 @@ func GetParameters() Params { params = GetParamsFromTfSwitch(params) } else if terraformVersionFileExists(params) { params = GetParamsFromTerraformVersion(params) - } else if versionTFFileExists(params) { + } else if isTerraformModule(params) { params = GetVersionFromVersionsTF(params) } else if terraGruntFileExists(params) { params = GetVersionFromTerragrunt(params) diff --git a/lib/param_parsing/parameters_test.go b/lib/param_parsing/parameters_test.go index 0e1f9042..f0a7b2d4 100644 --- a/lib/param_parsing/parameters_test.go +++ b/lib/param_parsing/parameters_test.go @@ -18,6 +18,7 @@ func TestGetParameters_version_from_args(t *testing.T) { getopt.CommandLine = getopt.New() }) } + func TestGetParameters_params_are_overridden_by_toml_file(t *testing.T) { t.Cleanup(func() { getopt.CommandLine = getopt.New() diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index 4e1c5ab7..681fb133 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -3,32 +3,26 @@ package param_parsing import ( "github.com/hashicorp/terraform-config-inspect/tfconfig" "github.com/warrensbox/terraform-switcher/lib" - "os" ) const versionTfFileName = "version.tf" func GetVersionFromVersionsTF(params Params) Params { - filePath := params.ChDirPath + "/" + versionTfFileName - if lib.CheckFileExist(filePath) { - logger.Infof("Reading version from %q", filePath) - module, err := tfconfig.LoadModule(params.ChDirPath) - if err != nil { - logger.Fatal("Could not load terraform module") - os.Exit(1) - } - tfconstraint := module.RequiredCore[0] - version, err2 := lib.GetSemver(tfconstraint, params.MirrorURL) - if err2 != nil { - logger.Fatalf("No version found matching %q", tfconstraint) - os.Exit(1) - } - params.Version = version + logger.Infof("Reading version from terraform module at %q", params.ChDirPath) + module, err := tfconfig.LoadModule(params.ChDirPath) + if err != nil { + logger.Fatalf("Could not load terraform module at %q", params.ChDirPath) } + tfconstraint := module.RequiredCore[0] + version, err2 := lib.GetSemver(tfconstraint, params.MirrorURL) + if err2 != nil { + logger.Fatalf("No version found matching %q", tfconstraint) + } + params.Version = version return params } -func versionTFFileExists(params Params) bool { - filePath := params.ChDirPath + "/" + versionTfFileName - return lib.CheckFileExist(filePath) +func isTerraformModule(params Params) bool { + module, err := tfconfig.LoadModule(params.ChDirPath) + return err != nil && len(module.RequiredCore) > 0 } From 0f20b3bc21730c185db48662fb42721414225253 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Mon, 8 Apr 2024 14:55:23 +0200 Subject: [PATCH 25/49] - exit on version or usage print --- main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.go b/main.go index c83e477d..e9571833 100644 --- a/main.go +++ b/main.go @@ -43,8 +43,10 @@ func main() { } else { fmt.Println("Version not defined during build.") } + os.Exit(0) case parameters.HelpFlag: param_parsing.UsageMessage() + os.Exit(0) case parameters.ListAllFlag: /* show all terraform version including betas and RCs*/ installOption(true, parameters.CustomBinaryPath, parameters.MirrorURL) From 9fd3ecb32754cbc1a60b08435976049ad0e6b559 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Mon, 8 Apr 2024 15:27:52 +0200 Subject: [PATCH 26/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- lib/param_parsing/tfswitch.go | 1 - lib/param_parsing/toml.go | 1 - lib/param_parsing/versiontf.go | 2 -- 3 files changed, 4 deletions(-) diff --git a/lib/param_parsing/tfswitch.go b/lib/param_parsing/tfswitch.go index 8c033a5f..4744d686 100644 --- a/lib/param_parsing/tfswitch.go +++ b/lib/param_parsing/tfswitch.go @@ -15,7 +15,6 @@ func GetParamsFromTfSwitch(params Params) Params { content, err := os.ReadFile(filePath) if err != nil { logger.Fatalf("Could not read file content from %q: %v", filePath, err) - os.Exit(1) } params.Version = strings.TrimSpace(string(content)) } diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 490a5ef7..3b1a52c5 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -22,7 +22,6 @@ func getParamsTOML(params Params) Params { errs := viperParser.ReadInConfig() // Find and read the config file if errs != nil { logger.Fatalf("Could not to read %q: %v", tomlPath, errs) - os.Exit(1) } params.Version = viperParser.GetString("version") // Attempt to get the version if it's provided in the toml diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index 681fb133..0c9a2469 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -5,8 +5,6 @@ import ( "github.com/warrensbox/terraform-switcher/lib" ) -const versionTfFileName = "version.tf" - func GetVersionFromVersionsTF(params Params) Params { logger.Infof("Reading version from terraform module at %q", params.ChDirPath) module, err := tfconfig.LoadModule(params.ChDirPath) From ef6418e1312f0fa1fb4038b64e8fb4cf70bd6d98 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Mon, 8 Apr 2024 21:03:55 +0200 Subject: [PATCH 27/49] - fix imports and fix cancellation of prompt --- lib/param_parsing/toml.go | 1 - main.go | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 3b1a52c5..3b2b5d43 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -3,7 +3,6 @@ package param_parsing import ( "github.com/spf13/viper" "github.com/warrensbox/terraform-switcher/lib" - "os" ) const tfSwitchTOMLFileName = ".tfswitch.toml" diff --git a/main.go b/main.go index e9571833..0947c2b2 100644 --- a/main.go +++ b/main.go @@ -181,8 +181,13 @@ func installOption(listAll bool, customBinaryPath, mirrorURL string) { tfversion = strings.Trim(tfversion, " *recent") //trim versions with the string " *recent" appended if errPrompt != nil { - logger.Fatalf("Prompt failed %v", errPrompt) - os.Exit(1) + if errPrompt.Error() == "^C" { + // Cancel execution + os.Exit(1) + } else { + logger.Fatalf("Prompt failed %v", errPrompt) + os.Exit(1) + } } lib.Install(tfversion, customBinaryPath, mirrorURL) From 05bd380d5665e76993d72c57075a6c6b8d5ae734 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 9 Apr 2024 10:02:20 +0200 Subject: [PATCH 28/49] - fix race condition with waiting for deferred file closes and renaming target file which would occasionally lead to errors due to existing file handler - removed unnecessary os.Exit - added debug logging --- lib/checksum.go | 6 +- lib/download.go | 2 +- lib/files.go | 111 +++++++++++++++++++-------------- lib/list_versions.go | 27 ++++---- lib/param_parsing/versiontf.go | 2 +- lib/utils.go | 4 +- 6 files changed, 81 insertions(+), 71 deletions(-) diff --git a/lib/checksum.go b/lib/checksum.go index b0b0d2db..30a61b15 100644 --- a/lib/checksum.go +++ b/lib/checksum.go @@ -33,29 +33,27 @@ func getChecksumFromHashFile(signatureFilePath string, terraformFileName string) // checkChecksumMatches This will calculate and compare the check sum of the downloaded zip file func checkChecksumMatches(hashFile string, targetFile *os.File) bool { + logger.Debugf("Checksum comparison for %v", targetFile.Name()) var fileHandlersToClose []*os.File fileHandlersToClose = append(fileHandlersToClose, targetFile) + defer closeFileHandlers(fileHandlersToClose) _, fileName := filepath.Split(targetFile.Name()) expectedChecksum, err := getChecksumFromHashFile(hashFile, fileName) if err != nil { - closeFileHandlers(fileHandlersToClose) logger.Errorf("Could not get checksum from file %q: %v", hashFile, err) return false } hash := sha256.New() if _, err := io.Copy(hash, targetFile); err != nil { - closeFileHandlers(fileHandlersToClose) logger.Errorf("Checksum calculation failed for %q: %v", fileName, err) return false } checksum := hex.EncodeToString(hash.Sum(nil)) if expectedChecksum != checksum { - closeFileHandlers(fileHandlersToClose) logger.Errorf("Checksum mismatch for %q. Expected: %q, calculated: %v", fileName, expectedChecksum, checksum) return false } - closeFileHandlers(fileHandlersToClose) return true } diff --git a/lib/download.go b/lib/download.go index f8cfdf87..a03a6b55 100644 --- a/lib/download.go +++ b/lib/download.go @@ -121,7 +121,7 @@ func downloadFromURL(installLocation string, url string) (string, error) { func downloadPublicKey(installLocation string, targetFileName string) error { logger.Debugf("Looking up public key file at %q", targetFileName) - publicKeyFileExists := FileExists(targetFileName) + publicKeyFileExists := FileExistsAndIsNotDir(targetFileName) if !publicKeyFileExists { // Public key does not exist. Let's grab it from hashicorp pubKeyFile, errDl := downloadFromURL(installLocation, PubKeyUri) diff --git a/lib/files.go b/lib/files.go index 26cf8ecc..9f928417 100644 --- a/lib/files.go +++ b/lib/files.go @@ -4,19 +4,20 @@ import ( "archive/zip" "bufio" "bytes" + "fmt" "io" - "io/ioutil" "os" "path/filepath" "strings" + "sync" ) // RenameFile : rename file name func RenameFile(src string, dest string) { + logger.Debugf("Renaming file %v to %v", src, dest) err := os.Rename(src, dest) if err != nil { - logger.Error(err) - return + logger.Fatal(err) } } @@ -46,55 +47,27 @@ func CheckFileExist(file string) bool { // Unzip will decompress a zip archive, moving all files and folders // within the zip file (parameter 1) to an output directory (parameter 2). func Unzip(src string, dest string) ([]string, error) { + logger.Debugf("Unzipping file %v", src) var filenames []string - r, err := zip.OpenReader(src) + reader, err := zip.OpenReader(src) if err != nil { return filenames, err } - defer r.Close() - - for _, f := range r.File { - - filePath, _ := filepath.Abs(f.Name) - rc, err := f.Open() - if err != nil { - return filenames, err - } - defer rc.Close() - - // Store filename/path for returning and using later on - fpath := filepath.Join(dest, f.Name) - filenames = append(filenames, fpath) - - if f.FileInfo().IsDir() { - - // Make Folder - _ = os.MkdirAll(fpath, os.ModePerm) - + defer reader.Close() + destination, err := filepath.Abs(dest) + if err != nil { + logger.Fatalf("Could not open destination %v", err) + } + var wg sync.WaitGroup + for _, f := range reader.File { + wg.Add(1) + unzipErr := unzipFile(f, destination, &wg) + if unzipErr != nil { + logger.Fatalf("Error unzipping %s", unzipErr) } else { - if !strings.Contains(filePath, "..") { - // Make File - if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { - return filenames, err - } - - outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) - if err != nil { - return filenames, err - } - - _, err = io.Copy(outFile, rc) - - // Close the file without defer to close before next iteration of loop - _ = outFile.Close() - - if err != nil { - return filenames, err - } - } - + filenames = append(filenames, filepath.Join(destination, f.Name)) } } return filenames, nil @@ -188,10 +161,9 @@ func CheckDirHasTGBin(dir, prefix string) bool { exist := false - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { logger.Fatal(err) - os.Exit(1) } res := []string{} for _, f := range files { @@ -230,7 +202,50 @@ func GetCurrentDirectory() string { dir, err := os.Getwd() //get current directory if err != nil { logger.Fatalf("Failed to get current directory %v", err) - os.Exit(1) } return dir } + +func unzipFile(f *zip.File, destination string, wg *sync.WaitGroup) error { + defer wg.Done() + // 4. Check if file paths are not vulnerable to Zip Slip + filePath := filepath.Join(destination, f.Name) + if !strings.HasPrefix(filePath, filepath.Clean(destination)+string(os.PathSeparator)) { + return fmt.Errorf("invalid file path: %s", filePath) + } + + // 5. Create directory tree + if f.FileInfo().IsDir() { + logger.Debugf("Extracting Directory %v", filePath) + if err := os.MkdirAll(filePath, os.ModePerm); err != nil { + return err + } + return nil + } + + if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { + return err + } + + // 6. Create a destination file for unzipped content + destinationFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + if err != nil { + return err + } + + // 7. Unzip the content of a file and copy it to the destination file + zippedFile, err := f.Open() + if err != nil { + return err + } + + logger.Debugf("Extracting File %v", destinationFile.Name()) + if _, err := io.Copy(destinationFile, zippedFile); err != nil { + return err + } + logger.Debugf("Closing destination file handler %v", destinationFile.Name()) + _ = destinationFile.Close() + logger.Debugf("Closing zipped file handler %v", f.Name) + _ = zippedFile.Close() + return nil +} diff --git a/lib/list_versions.go b/lib/list_versions.go index a5c8759f..37a69203 100644 --- a/lib/list_versions.go +++ b/lib/list_versions.go @@ -2,9 +2,8 @@ package lib import ( "fmt" - "io/ioutil" + "io" "net/http" - "os" "reflect" "regexp" "strings" @@ -16,8 +15,8 @@ type tfVersionList struct { // GetTFList : Get the list of available terraform version given the hashicorp url func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { - - result, error := GetTFURLBody(mirrorURL) + logger.Debugf("Get list of terraform versions") + result, error := getTFURLBody(mirrorURL) if error != nil { return nil, error } @@ -42,7 +41,7 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { } if len(tfVersionList.tflist) == 0 { - logger.Infof("Cannot get version list from mirror: %s", mirrorURL) + logger.Errorf("Cannot get version list from mirror: %s", mirrorURL) } return tfVersionList.tflist, nil @@ -52,7 +51,7 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { // GetTFLatest : Get the latest terraform version given the hashicorp url func GetTFLatest(mirrorURL string) (string, error) { - result, error := GetTFURLBody(mirrorURL) + result, error := getTFURLBody(mirrorURL) if error != nil { return "", error } @@ -73,8 +72,8 @@ func GetTFLatest(mirrorURL string) (string, error) { // 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 - versions, error := GetTFURLBody(mirrorURL) + //TODO: use GetTFList() instead of getTFURLBody + versions, error := getTFURLBody(mirrorURL) if error != nil { return "", error } @@ -104,29 +103,27 @@ func GetTFLatestImplicit(mirrorURL string, preRelease bool, version string) (str return "", nil } -// GetTFURLBody : Get list of terraform versions from hashicorp releases -func GetTFURLBody(mirrorURL string) ([]string, error) { +// getTFURLBody : Get list of terraform versions from hashicorp releases +func getTFURLBody(mirrorURL string) ([]string, error) { hasSlash := strings.HasSuffix(mirrorURL, "/") - if !hasSlash { //if does not have slash - append slash + if !hasSlash { + //if it does not have slash - append slash mirrorURL = fmt.Sprintf("%s/", mirrorURL) } resp, errURL := http.Get(mirrorURL) if errURL != nil { logger.Fatalf("Error getting url: %v", errURL) - os.Exit(1) } defer resp.Body.Close() if resp.StatusCode != 200 { logger.Fatalf("Error retrieving contents from url: %s", mirrorURL) - os.Exit(1) } - body, errBody := ioutil.ReadAll(resp.Body) + body, errBody := io.ReadAll(resp.Body) if errBody != nil { logger.Fatalf("Error reading body: %v", errBody) - os.Exit(1) } bodyString := string(body) diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index 0c9a2469..0e9c1a2e 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -22,5 +22,5 @@ func GetVersionFromVersionsTF(params Params) Params { func isTerraformModule(params Params) bool { module, err := tfconfig.LoadModule(params.ChDirPath) - return err != nil && len(module.RequiredCore) > 0 + return err == nil && len(module.RequiredCore) > 0 } diff --git a/lib/utils.go b/lib/utils.go index 0bcddda9..cd33f0c0 100644 --- a/lib/utils.go +++ b/lib/utils.go @@ -4,8 +4,8 @@ import ( "os" ) -// 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 { +// FileExistsAndIsNotDir checks if a file exists and is not a directory before we try using it to prevent further errors +func FileExistsAndIsNotDir(filename string) bool { info, err := os.Stat(filename) if os.IsNotExist(err) { return false From cf1e230fd75e7050e96031231c0b5e2be2b4e67d Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 9 Apr 2024 10:49:25 +0200 Subject: [PATCH 29/49] - update to hcl/v2 package --- go.mod | 4 +-- go.sum | 51 --------------------------------- lib/param_parsing/terragrunt.go | 4 +-- 3 files changed, 3 insertions(+), 56 deletions(-) diff --git a/go.mod b/go.mod index 41e9a62c..73fe234b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ 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/hcl/v2 v2.20.1 github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/go-homedir v1.1.0 @@ -17,7 +17,6 @@ require ( require ( github.com/agext/levenshtein v1.2.3 // indirect - github.com/apparentlymart/go-textseg v1.0.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -26,7 +25,6 @@ require ( github.com/gookit/goutil v0.6.15 // indirect github.com/gookit/gsr v0.1.0 // indirect github.com/hashicorp/hcl v1.0.1-vault-5 // indirect - github.com/hashicorp/hcl/v2 v2.20.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect diff --git a/go.sum b/go.sum index c867add2..d32fc500 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,7 @@ -github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -22,14 +17,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= @@ -40,21 +31,14 @@ 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= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= -github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 h1:PFfGModn55JA0oBsvFghhj0v93me+Ctr3uHC/UmFAls= -github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72 h1:nZ5gGjbe5o7XUu1d7j+Y5Ztcxlp+yaumTKH9i0D3wlg= github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72/go.mod h1:l8HcFPm9cQh6Q0KSWoYPiePqMvRFenybP1CH2MjKdlg= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -62,23 +46,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= 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.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pborman/getopt v1.1.0 h1:eJ3aFZroQqq0bWmraivjQNt6Dmm5M0h2JcDW38/Azb0= github.com/pborman/getopt v1.1.0/go.mod h1:FxXoW1Re00sQG/+KIkuSqRL/LwQgSkv7uyac+STFsbk= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= @@ -92,15 +69,12 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= @@ -109,7 +83,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -119,61 +92,37 @@ 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.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -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/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.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= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= -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= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index ecdf75c3..b4e1c440 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -1,8 +1,8 @@ package param_parsing import ( - "github.com/hashicorp/hcl2/gohcl" - "github.com/hashicorp/hcl2/hclparse" + "github.com/hashicorp/hcl/v2/gohcl" + "github.com/hashicorp/hcl/v2/hclparse" "github.com/warrensbox/terraform-switcher/lib" ) From 09fed3742ca9eabedbb6aa42055766f32a51df26 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 11 Apr 2024 08:55:44 +0200 Subject: [PATCH 30/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- lib/checksum.go | 2 +- lib/files.go | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/checksum.go b/lib/checksum.go index 30a61b15..73de2e20 100644 --- a/lib/checksum.go +++ b/lib/checksum.go @@ -33,7 +33,7 @@ func getChecksumFromHashFile(signatureFilePath string, terraformFileName string) // checkChecksumMatches This will calculate and compare the check sum of the downloaded zip file func checkChecksumMatches(hashFile string, targetFile *os.File) bool { - logger.Debugf("Checksum comparison for %v", targetFile.Name()) + logger.Debugf("Checksum comparison for %q", targetFile.Name()) var fileHandlersToClose []*os.File fileHandlersToClose = append(fileHandlersToClose, targetFile) defer closeFileHandlers(fileHandlersToClose) diff --git a/lib/files.go b/lib/files.go index 9f928417..3149c823 100644 --- a/lib/files.go +++ b/lib/files.go @@ -14,7 +14,7 @@ import ( // RenameFile : rename file name func RenameFile(src string, dest string) { - logger.Debugf("Renaming file %v to %v", src, dest) + logger.Debugf("Renaming file %q to %q", src, dest) err := os.Rename(src, dest) if err != nil { logger.Fatal(err) @@ -47,7 +47,7 @@ func CheckFileExist(file string) bool { // Unzip will decompress a zip archive, moving all files and folders // within the zip file (parameter 1) to an output directory (parameter 2). func Unzip(src string, dest string) ([]string, error) { - logger.Debugf("Unzipping file %v", src) + logger.Debugf("Unzipping file %q", src) var filenames []string @@ -58,14 +58,14 @@ func Unzip(src string, dest string) ([]string, error) { defer reader.Close() destination, err := filepath.Abs(dest) if err != nil { - logger.Fatalf("Could not open destination %v", err) + logger.Fatalf("Could not open destination: %v", err) } var wg sync.WaitGroup for _, f := range reader.File { wg.Add(1) unzipErr := unzipFile(f, destination, &wg) if unzipErr != nil { - logger.Fatalf("Error unzipping %s", unzipErr) + logger.Fatalf("Error unzipping %v", unzipErr) } else { filenames = append(filenames, filepath.Join(destination, f.Name)) } @@ -211,12 +211,12 @@ func unzipFile(f *zip.File, destination string, wg *sync.WaitGroup) error { // 4. Check if file paths are not vulnerable to Zip Slip filePath := filepath.Join(destination, f.Name) if !strings.HasPrefix(filePath, filepath.Clean(destination)+string(os.PathSeparator)) { - return fmt.Errorf("invalid file path: %s", filePath) + return fmt.Errorf("Invalid file path: %q", filePath) } // 5. Create directory tree if f.FileInfo().IsDir() { - logger.Debugf("Extracting Directory %v", filePath) + logger.Debugf("Extracting directory %q", filePath) if err := os.MkdirAll(filePath, os.ModePerm); err != nil { return err } @@ -239,13 +239,13 @@ func unzipFile(f *zip.File, destination string, wg *sync.WaitGroup) error { return err } - logger.Debugf("Extracting File %v", destinationFile.Name()) + logger.Debugf("Extracting File %q", destinationFile.Name()) if _, err := io.Copy(destinationFile, zippedFile); err != nil { return err } - logger.Debugf("Closing destination file handler %v", destinationFile.Name()) + logger.Debugf("Closing destination file handler %q", destinationFile.Name()) _ = destinationFile.Close() - logger.Debugf("Closing zipped file handler %v", f.Name) + logger.Debugf("Closing zipped file handler %q", f.Name) _ = zippedFile.Close() return nil } From 778ffcc74fd6c5a60e3cae61c0d9d7fff6c8830a Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 11 Apr 2024 08:57:04 +0200 Subject: [PATCH 31/49] Apply suggestions from code review Co-authored-by: George L. Yermulnik --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index 0947c2b2..39022d6e 100644 --- a/main.go +++ b/main.go @@ -186,7 +186,6 @@ func installOption(listAll bool, customBinaryPath, mirrorURL string) { os.Exit(1) } else { logger.Fatalf("Prompt failed %v", errPrompt) - os.Exit(1) } } From 753cb53e652893b195213ac9e336215c6752350c Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 11 Apr 2024 09:28:12 +0200 Subject: [PATCH 32/49] - added log-level parameter --- lib/checksum_test.go | 1 + lib/logging.go | 32 ++++++++++++++++++++++++++------ lib/param_parsing/parameters.go | 7 ++++++- main.go | 5 ++--- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/checksum_test.go b/lib/checksum_test.go index cb68df06..60a77369 100644 --- a/lib/checksum_test.go +++ b/lib/checksum_test.go @@ -18,6 +18,7 @@ func Test_getChecksumFromHashFile(t *testing.T) { } func Test_checkChecksumMatches(t *testing.T) { + InitLogger("TRACE") targetFile, err := os.Open("../test-data/checksum-check-file") if err != nil { t.Errorf("[Error]: Could not open testfile for signature verification.") diff --git a/lib/logging.go b/lib/logging.go index deda69d5..2771b4b7 100644 --- a/lib/logging.go +++ b/lib/logging.go @@ -8,17 +8,37 @@ import ( const loggingTemplate = "{{datetime}} {{level}} [{{caller}}] {{message}} {{data}} {{extra}}\n" -var logger = InitLogger() +var logger *slog.Logger -func InitLogger() *slog.Logger { +func InitLogger(logLevel string) *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) + + var h *handler.ConsoleHandler + //params := param_parsing.GetParameters() + if logLevel == "TRACE" { + h = handler.NewConsoleHandler(TraceLogging) + } else if logLevel == "DEBUG" { + h = handler.NewConsoleHandler(DebugLogging) + } else if logLevel == "NOTICE" { + h = handler.NewConsoleHandler(NoticeLogging) + } else { + h = handler.NewConsoleHandler(NormalLogging) + } + h.SetFormatter(formatter) - logger := slog.NewWithHandlers(h) - logger.ExitFunc = os.Exit - return logger + newLogger := slog.NewWithHandlers(h) + newLogger.ExitFunc = os.Exit + logger = newLogger + return newLogger } + +var ( + NormalLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel} + NoticeLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel} + DebugLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel} + TraceLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel, slog.TraceLevel} +) diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 41bca82b..927f26ad 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -2,6 +2,7 @@ package param_parsing import ( "fmt" + "github.com/gookit/slog" "github.com/pborman/getopt" "github.com/warrensbox/terraform-switcher/lib" "os" @@ -16,6 +17,7 @@ type Params struct { LatestPre string LatestStable string ListAllFlag bool + LogLevel string MirrorURL string ShowLatestFlag bool ShowLatestPre string @@ -24,7 +26,7 @@ type Params struct { VersionFlag bool } -var logger = lib.InitLogger() +var logger *slog.Logger func GetParameters() Params { var params Params @@ -38,6 +40,7 @@ func GetParameters() Params { getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") + getopt.StringVarLong(¶ms.LogLevel, "log-level", 'g', "Set loglevel for tfswitch. One of (INFO, NOTICE, DEBUG, TRACE)") getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+lib.DefaultMirror) getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") @@ -47,6 +50,7 @@ func GetParameters() Params { // Parse the command line parameters to fetch stuff like chdir getopt.Parse() + logger = lib.InitLogger(params.LogLevel) // Read configuration files if tomlFileExists(params) { params = getParamsTOML(params) @@ -81,6 +85,7 @@ func initParams(params Params) Params { params.LatestPre = lib.DefaultLatest params.LatestStable = lib.DefaultLatest params.ListAllFlag = false + params.LogLevel = "INFO" params.MirrorURL = lib.DefaultMirror params.ShowLatestFlag = false params.ShowLatestPre = lib.DefaultLatest diff --git a/main.go b/main.go index 39022d6e..6a477328 100644 --- a/main.go +++ b/main.go @@ -29,13 +29,12 @@ import ( lib "github.com/warrensbox/terraform-switcher/lib" ) -var logger = lib.InitLogger() +var parameters = param_parsing.GetParameters() +var logger = lib.InitLogger(parameters.LogLevel) var version string func main() { - parameters := param_parsing.GetParameters() - switch { case parameters.VersionFlag: if version != "" { From ef175f632b6ab7e03f1b9daef65651cbac268ec6 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 11 Apr 2024 12:14:53 +0200 Subject: [PATCH 33/49] - moved all utility functions out of main. - refactored functions to private where possible. - removed main_test as it was not really a useful test. --- lib/common.go | 10 -- lib/download_test.go | 2 +- lib/files.go | 7 +- lib/files_test.go | 2 +- lib/install.go | 160 ++++++++++++++++++++++++-------- lib/list_versions.go | 73 +++++++++------ lib/list_versions_test.go | 22 ++--- lib/logging.go | 1 - lib/param_parsing/parameters.go | 10 +- lib/semver.go | 4 +- lib/symlink.go | 4 +- lib/utils.go | 8 ++ main.go | 143 +++------------------------- main_test.go | 25 ----- 14 files changed, 209 insertions(+), 262 deletions(-) delete mode 100644 main_test.go diff --git a/lib/common.go b/lib/common.go index b82a8f16..a201f02d 100644 --- a/lib/common.go +++ b/lib/common.go @@ -30,16 +30,6 @@ func createFile(path string) { logger.Infof("==> done creating %q file", path) } -func createDirIfNotExist(dir string) { - if _, err := os.Stat(dir); os.IsNotExist(err) { - logger.Infof("Creating directory for terraform: %v", dir) - err = os.MkdirAll(dir, 0755) - if err != nil { - logger.Panic("Unable to create %q directory for terraform: %v", dir, err) - } - } -} - func cleanUp(path string) { removeContents(path) removeFiles(path) diff --git a/lib/download_test.go b/lib/download_test.go index b0d60d1d..863ac16b 100644 --- a/lib/download_test.go +++ b/lib/download_test.go @@ -32,7 +32,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) { } else { installLocation = installPath } - t.Logf("Install Location: %v", installLocation) + t.Logf("install Location: %v", installLocation) // create /.terraform.versions_test/ directory to store code if _, err := os.Stat(installLocation); os.IsNotExist(err) { diff --git a/lib/files.go b/lib/files.go index 3149c823..0c0f227f 100644 --- a/lib/files.go +++ b/lib/files.go @@ -73,14 +73,13 @@ func Unzip(src string, dest string) ([]string, error) { return filenames, nil } -// CreateDirIfNotExist : create directory if directory does not exist -func CreateDirIfNotExist(dir string) { +// createDirIfNotExist : create directory if directory does not exist +func createDirIfNotExist(dir string) { if _, err := os.Stat(dir); os.IsNotExist(err) { logger.Infof("Creating directory for terraform binary at %q", dir) err = os.MkdirAll(dir, 0755) if err != nil { - logger.Error(err) - logger.Panicf("Unable to create directory for terraform binary at: %v", dir) + logger.Panicf("Unable to create %q directory for terraform: %v", dir, err) } } } diff --git a/lib/files_test.go b/lib/files_test.go index 2e2e8903..1726cf82 100644 --- a/lib/files_test.go +++ b/lib/files_test.go @@ -153,7 +153,7 @@ func TestCreateDirIfNotExist(t *testing.T) { t.Error("Directory should not exist") } - CreateDirIfNotExist(installLocation) + createDirIfNotExist(installLocation) t.Logf("Creating directory %v", installLocation) if _, err := os.Stat(installLocation); err == nil { diff --git a/lib/install.go b/lib/install.go index d38f1d5a..6d5ecd18 100644 --- a/lib/install.go +++ b/lib/install.go @@ -2,6 +2,7 @@ package lib import ( "fmt" + "github.com/manifoldco/promptui" "os" "path/filepath" "runtime" @@ -17,7 +18,6 @@ var ( // initialize : removes existing symlink to terraform binary based on provided binPath func initialize(binPath string) { - /* find terraform binary location if terraform is already installed*/ cmd := NewCommand(binPath) next := cmd.Find() @@ -35,42 +35,39 @@ func initialize(binPath string) { if symlinkExist { RemoveSymlink(binPath) } - } -// GetInstallLocation : get location where the terraform binary will be installed, +// getInstallLocation : get location where the terraform binary will be installed, // will create a directory in the home location if it does not exist -func GetInstallLocation() string { +func getInstallLocation() string { /* get current user */ - homedir, errCurr := homedir.Dir() + homeDir, errCurr := homedir.Dir() if errCurr != nil { logger.Fatal(errCurr) os.Exit(1) } - userCommon := homedir + userCommon := homeDir /* set installation location */ installLocation = filepath.Join(userCommon, installPath) /* Create local installation directory if it does not exist */ - CreateDirIfNotExist(installLocation) - + createDirIfNotExist(installLocation) return installLocation - } -// Install : Install the provided version in the argument -func Install(tfversion string, binPath string, mirrorURL string) { +// install : install the provided version in the argument +func install(tfversion string, binPath string, mirrorURL string) { /* 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 * Tell users to add $HOME/bin to their path */ - binPath = InstallableBinLocation(binPath) + binPath = installableBinLocation(binPath) initialize(binPath) //initialize path - installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file + installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file goarch := runtime.GOARCH goos := runtime.GOOS @@ -99,7 +96,7 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* set symlink to desired version */ CreateSymlink(installFileVersionPath, binPath) logger.Infof("Switched terraform to version %q", tfversion) - AddRecent(tfversion) //add to recent file for faster lookup + addRecent(tfversion) //add to recent file for faster lookup os.Exit(0) } @@ -116,14 +113,12 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* If unable to download file from url, exit(1) immediately */ if errDownload != nil { logger.Fatalf("Error downloading: %s", errDownload) - os.Exit(1) } /* unzip the downloaded zipfile */ _, errUnzip := Unzip(zipFile, installLocation) if errUnzip != nil { logger.Fatalf("Unable to unzip %q file: %v", zipFile, errUnzip) - os.Exit(1) } /* rename unzipped file to terraform version name - terraform_x.x.x */ @@ -143,14 +138,14 @@ func Install(tfversion string, binPath string, mirrorURL string) { /* set symlink to desired version */ CreateSymlink(installFileVersionPath, binPath) logger.Infof("Switched terraform to version %q", tfversion) - AddRecent(tfversion) //add to recent file for faster lookup + addRecent(tfversion) //add to recent file for faster lookup os.Exit(0) } -// AddRecent : add to recent file -func AddRecent(requestedVersion string) { +// addRecent : add to recent file +func addRecent(requestedVersion string) { - installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file + installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file versionFile := filepath.Join(installLocation, recentFile) fileExist := CheckFileExist(versionFile) @@ -163,7 +158,7 @@ func AddRecent(requestedVersion string) { } for _, line := range lines { - if !ValidVersionFormat(line) { + if !validVersionFormat(line) { logger.Infof("File %q is dirty (recreating cache file)", versionFile) RemoveFiles(versionFile) CreateRecentFile(requestedVersion) @@ -171,17 +166,17 @@ func AddRecent(requestedVersion string) { } } - versionExist := VersionExist(requestedVersion, lines) + versionExist := versionExist(requestedVersion, lines) if !versionExist { if len(lines) >= 3 { _, lines = lines[len(lines)-1], lines[:len(lines)-1] lines = append([]string{requestedVersion}, lines...) - WriteLines(lines, versionFile) + _ = WriteLines(lines, versionFile) } else { lines = append([]string{requestedVersion}, lines...) - WriteLines(lines, versionFile) + _ = WriteLines(lines, versionFile) } } @@ -190,17 +185,17 @@ func AddRecent(requestedVersion string) { } } -// GetRecentVersions : get recent version from file -func GetRecentVersions() ([]string, error) { +// getRecentVersions : get recent version from file +func getRecentVersions() ([]string, error) { - installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file + installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file versionFile := filepath.Join(installLocation, recentFile) fileExist := CheckFileExist(versionFile) if fileExist { lines, errRead := ReadLines(versionFile) - outputRecent := []string{} + var outputRecent []string if errRead != nil { logger.Errorf("Error reading %q file: %f", versionFile, errRead) @@ -212,7 +207,7 @@ func GetRecentVersions() ([]string, error) { If any version is invalid, it will be considered dirty and the recent file will be removed */ - if !ValidVersionFormat(line) { + if !validVersionFormat(line) { RemoveFiles(versionFile) return nil, errRead } @@ -229,12 +224,10 @@ func GetRecentVersions() ([]string, error) { return nil, nil } -// CreateRecentFile : create a recent file +// CreateRecentFile : create RECENT file func CreateRecentFile(requestedVersion string) { - - installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file - - WriteLines([]string{requestedVersion}, filepath.Join(installLocation, recentFile)) + installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file + _ = WriteLines([]string{requestedVersion}, filepath.Join(installLocation, recentFile)) } // ConvertExecutableExt : convert excutable with local OS extension @@ -250,9 +243,9 @@ func ConvertExecutableExt(fpath string) string { } } -// InstallableBinLocation : Checks if terraform is installable in the location provided by the user. +// installableBinLocation : Checks if terraform is installable in the location provided by the user. // If not, create $HOME/bin. Ask users to add $HOME/bin to $PATH and return $HOME/bin as install location -func InstallableBinLocation(userBinPath string) string { +func installableBinLocation(userBinPath string) string { homedir, errCurr := homedir.Dir() if errCurr != nil { @@ -280,7 +273,7 @@ func InstallableBinLocation(userBinPath string) string { } else { //if ~/bin directory does not exist, create ~/bin for terraform installation 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 + createDirIfNotExist(filepath.Join(homedir, "bin")) //create ~/bin logger.Warnf("Run `export PATH=\"$PATH:%s\"` to append bin to $PATH", filepath.Join(homedir, "bin")) return filepath.Join(homedir, "bin", "terraform") } @@ -293,3 +286,96 @@ func InstallableBinLocation(userBinPath string) string { os.Exit(1) return "" } + +// InstallLatestVersion install latest stable tf version +func InstallLatestVersion(customBinaryPath, mirrorURL string) { + tfversion, _ := getTFLatest(mirrorURL) + install(tfversion, customBinaryPath, mirrorURL) +} + +// InstallLatestImplicitVersion install latest - argument (version) must be provided +func InstallLatestImplicitVersion(requestedVersion, customBinaryPath, mirrorURL string, preRelease bool) { + _, err := version.NewConstraint(requestedVersion) + if err != nil { + logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) + } + //if lib.ValidMinorVersionFormat(requestedVersion) { + tfversion, err := getTFLatestImplicit(mirrorURL, preRelease, requestedVersion) + if err == nil && tfversion != "" { + install(tfversion, customBinaryPath, mirrorURL) + } + logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) + PrintInvalidMinorTFVersion() +} + +// InstallVersion install with provided version as argument +func InstallVersion(arg, customBinaryPath, mirrorURL string) { + if validVersionFormat(arg) { + requestedVersion := arg + + //check to see if the requested version has been downloaded before + installLocation := getInstallLocation() + installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, VersionPrefix+requestedVersion)) + recentDownloadFile := CheckFileExist(installFileVersionPath) + if recentDownloadFile { + ChangeSymlink(installFileVersionPath, customBinaryPath) + logger.Infof("Switched terraform to version %q", requestedVersion) + addRecent(requestedVersion) //add to recent file for faster lookup + os.Exit(0) + } + + // If the requested version had not been downloaded before + // Set list all true - all versions including beta and rc will be displayed + tflist, _ := getTFList(mirrorURL, true) // Get list of versions + exist := versionExist(requestedVersion, tflist) // Check if version exists before downloading it + + if exist { + install(requestedVersion, customBinaryPath, mirrorURL) + } else { + logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") + os.Exit(1) + } + + } else { + PrintInvalidTFVersion() + logger.Error("Args must be a valid terraform version") + UsageMessage() + os.Exit(1) + } +} + +// InstallOption displays & installs tf version +/* listAll = true - all versions including beta and rc will be displayed */ +/* listAll = false - only official stable release are displayed */ +func InstallOption(listAll bool, customBinaryPath, mirrorURL string) { + tflist, _ := getTFList(mirrorURL, listAll) // Get list of versions + recentVersions, _ := getRecentVersions() // Get recent versions from RECENT file + tflist = append(recentVersions, tflist...) // Append recent versions to the top of the list + tflist = removeDuplicateVersions(tflist) // Remove duplicate version + + if len(tflist) == 0 { + logger.Fatalf("Terraform version list is empty: %s", mirrorURL) + os.Exit(1) + } + + /* prompt user to select version of terraform */ + prompt := promptui.Select{ + Label: "Select Terraform version", + Items: tflist, + } + + _, tfversion, errPrompt := prompt.Run() + tfversion = strings.Trim(tfversion, " *recent") //trim versions with the string " *recent" appended + + if errPrompt != nil { + if errPrompt.Error() == "^C" { + // Cancel execution + os.Exit(1) + } else { + logger.Fatalf("Prompt failed %v", errPrompt) + } + } + + install(tfversion, customBinaryPath, mirrorURL) + os.Exit(0) +} diff --git a/lib/list_versions.go b/lib/list_versions.go index 37a69203..af151f10 100644 --- a/lib/list_versions.go +++ b/lib/list_versions.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "net/http" + "os" "reflect" "regexp" "strings" @@ -13,12 +14,12 @@ type tfVersionList struct { tflist []string } -// GetTFList : Get the list of available terraform version given the hashicorp url -func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { +// getTFList : Get the list of available terraform version given the hashicorp url +func getTFList(mirrorURL string, preRelease bool) ([]string, error) { logger.Debugf("Get list of terraform versions") - result, error := getTFURLBody(mirrorURL) - if error != nil { - return nil, error + result, err := getTFURLBody(mirrorURL) + if err != nil { + return nil, err } var tfVersionList tfVersionList @@ -43,17 +44,14 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) { if len(tfVersionList.tflist) == 0 { logger.Errorf("Cannot get version list from mirror: %s", mirrorURL) } - return tfVersionList.tflist, nil - } -// GetTFLatest : Get the latest terraform version given the hashicorp url -func GetTFLatest(mirrorURL string) (string, error) { - - result, error := getTFURLBody(mirrorURL) - if error != nil { - return "", error +// getTFLatest : Get the latest terraform version given the hashicorp url +func getTFLatest(mirrorURL string) (string, error) { + result, err := getTFURLBody(mirrorURL) + if err != nil { + return "", err } // Getting versions from body; should return match /X.X.X/ where X is a number semver := `\/?(\d+\.\d+\.\d+)\/?"` @@ -65,14 +63,13 @@ func GetTFLatest(mirrorURL string) (string, error) { return trimstr, nil } } - return "", nil } -// GetTFLatestImplicit : Get the latest implicit terraform version given the hashicorp url -func GetTFLatestImplicit(mirrorURL string, preRelease bool, version string) (string, error) { +// 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 + //TODO: use getTFList() instead of getTFURLBody versions, error := getTFURLBody(mirrorURL) if error != nil { return "", error @@ -92,7 +89,7 @@ func GetTFLatestImplicit(mirrorURL string, preRelease bool, version string) (str } } else if preRelease == false { listAll := false - tflist, _ := GetTFList(mirrorURL, listAll) //get list of versions + tflist, _ := getTFList(mirrorURL, listAll) //get list of versions version = fmt.Sprintf("~> %v", version) semv, err := SemVerParser(&version, tflist) if err != nil { @@ -132,9 +129,8 @@ func getTFURLBody(mirrorURL string) ([]string, error) { return result, nil } -// VersionExist : check if requested version exist -func VersionExist(val interface{}, array interface{}) (exists bool) { - +// versionExist : check if requested version exist +func versionExist(val interface{}, array interface{}) (exists bool) { exists = false switch reflect.TypeOf(array).Kind() { case reflect.Slice: @@ -146,13 +142,14 @@ func VersionExist(val interface{}, array interface{}) (exists bool) { return exists } } + default: + panic("unhandled default case") } - return exists } -// RemoveDuplicateVersions : remove duplicate version -func RemoveDuplicateVersions(elements []string) []string { +// removeDuplicateVersions : remove duplicate version +func removeDuplicateVersions(elements []string) []string { // Use map to record duplicates as we find them. encountered := map[string]bool{} result := []string{} @@ -172,20 +169,19 @@ func RemoveDuplicateVersions(elements []string) []string { return result } -// ValidVersionFormat : returns valid version format +// validVersionFormat : returns valid version format /* For example: 0.1.2 = valid // For example: 0.1.2-beta1 = valid // For example: 0.1.2-alpha = valid // For example: a.1.2 = invalid // For example: 0.1. 2 = invalid */ -func ValidVersionFormat(version string) bool { +func validVersionFormat(version string) bool { // Getting versions from body; should return match /X.X.X-@/ where X is a number,@ is a word character between a-z or A-Z // Follow https://semver.org/spec/v1.0.0-beta.html // Check regular expression at https://rubular.com/r/ju3PxbaSBALpJB semverRegex := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-[a-zA-z]+\d*)?$`) - return semverRegex.MatchString(version) } @@ -194,10 +190,31 @@ func ValidVersionFormat(version string) bool { // For example: a.1.2 = invalid // For example: 0.1.2 = invalid */ -func ValidMinorVersionFormat(version string) bool { +func validMinorVersionFormat(version string) bool { // Getting versions from body; should return match /X.X./ where X is a number semverRegex := regexp.MustCompile(`^(\d+\.\d+)$`) return semverRegex.MatchString(version) } + +// ShowLatestVersion show install latest stable tf version +func ShowLatestVersion(mirrorURL string) { + tfversion, _ := getTFLatest(mirrorURL) + logger.Infof("%s", tfversion) +} + +// ShowLatestImplicitVersion show latest - argument (version) must be provided +func ShowLatestImplicitVersion(requestedVersion, mirrorURL string, preRelease bool) { + if validMinorVersionFormat(requestedVersion) { + tfversion, _ := getTFLatestImplicit(mirrorURL, preRelease, requestedVersion) + if len(tfversion) > 0 { + logger.Infof("%s", tfversion) + } else { + logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") + os.Exit(1) + } + } else { + PrintInvalidMinorTFVersion() + } +} diff --git a/lib/list_versions_test.go b/lib/list_versions_test.go index f23f24bd..d83291d6 100644 --- a/lib/list_versions_test.go +++ b/lib/list_versions_test.go @@ -12,7 +12,7 @@ const ( // TestGetTFList : Get list from hashicorp func TestGetTFList(t *testing.T) { - list, _ := GetTFList(hashiURL, true) + list, _ := getTFList(hashiURL, true) val := "0.1.0" var exists bool @@ -41,7 +41,7 @@ func TestRemoveDuplicateVersions(t *testing.T) { testArray := []string{"0.0.1", "0.0.2", "0.0.3", "0.0.1", "0.12.0-beta1", "0.12.0-beta1"} - list := RemoveDuplicateVersions(testArray) + list := removeDuplicateVersions(testArray) if len(list) == len(testArray) { t.Errorf("Not able to remove duplicate: %s\n", testArray) @@ -57,7 +57,7 @@ func TestValidVersionFormat(t *testing.T) { var version string version = "0.11.8" - valid := ValidVersionFormat(version) + valid := validVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) @@ -67,7 +67,7 @@ func TestValidVersionFormat(t *testing.T) { version = "1.11.9" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) @@ -77,7 +77,7 @@ func TestValidVersionFormat(t *testing.T) { version = "1.11.a" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) @@ -87,7 +87,7 @@ func TestValidVersionFormat(t *testing.T) { version = "22323" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) @@ -97,7 +97,7 @@ func TestValidVersionFormat(t *testing.T) { version = "@^&*!)!" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) @@ -107,7 +107,7 @@ func TestValidVersionFormat(t *testing.T) { version = "1.11.9-beta1" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) @@ -117,7 +117,7 @@ func TestValidVersionFormat(t *testing.T) { version = "0.12.0-rc2" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) @@ -127,7 +127,7 @@ func TestValidVersionFormat(t *testing.T) { version = "1.11.4-boom" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == true { t.Logf("Valid version format : %s (expected)", version) @@ -137,7 +137,7 @@ func TestValidVersionFormat(t *testing.T) { version = "1.11.4-1" - valid = ValidVersionFormat(version) + valid = validVersionFormat(version) if valid == false { t.Logf("Invalid version format : %s (expected)", version) diff --git a/lib/logging.go b/lib/logging.go index 2771b4b7..f3827b89 100644 --- a/lib/logging.go +++ b/lib/logging.go @@ -18,7 +18,6 @@ func InitLogger(logLevel string) *slog.Logger { formatter.SetTemplate(loggingTemplate) var h *handler.ConsoleHandler - //params := param_parsing.GetParameters() if logLevel == "TRACE" { h = handler.NewConsoleHandler(TraceLogging) } else if logLevel == "DEBUG" { diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 927f26ad..7889486e 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -1,11 +1,9 @@ package param_parsing import ( - "fmt" "github.com/gookit/slog" "github.com/pborman/getopt" "github.com/warrensbox/terraform-switcher/lib" - "os" ) type Params struct { @@ -41,7 +39,7 @@ func GetParameters() Params { getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") getopt.BoolVarLong(¶ms.ListAllFlag, "list-all", 'l', "List all versions of terraform - including beta and rc") getopt.StringVarLong(¶ms.LogLevel, "log-level", 'g', "Set loglevel for tfswitch. One of (INFO, NOTICE, DEBUG, TRACE)") - getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "Install from a remote API other than the default. Default: "+lib.DefaultMirror) + getopt.StringVarLong(¶ms.MirrorURL, "mirror", 'm', "install from a remote API other than the default. Default: "+lib.DefaultMirror) getopt.BoolVarLong(¶ms.ShowLatestFlag, "show-latest", 'U', "Show latest stable version") getopt.StringVarLong(¶ms.ShowLatestPre, "show-latest-pre", 'P', "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.ShowLatestStable, "show-latest-stable", 'S', "Show latest implicit version. Ex: tfswitch --show-latest-stable 0.13 prints 0.13.7 (latest)") @@ -94,9 +92,3 @@ func initParams(params Params) Params { params.VersionFlag = false return params } - -func UsageMessage() { - fmt.Print("\n\n") - getopt.PrintUsage(os.Stderr) - fmt.Println("Supply the terraform version as an argument, or choose from a menu") -} diff --git a/lib/semver.go b/lib/semver.go index 002dc166..ad4ee6fa 100644 --- a/lib/semver.go +++ b/lib/semver.go @@ -10,7 +10,7 @@ import ( // GetSemver : returns version that will be installed based on server constraint provided func GetSemver(tfconstraint string, mirrorURL string) (string, error) { listAll := true - tflist, _ := GetTFList(mirrorURL, listAll) //get list of versions + tflist, _ := getTFList(mirrorURL, listAll) //get list of versions 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) { if constraints.Check(element) { // Validate a version against a constraint tfversion = element.String() logger.Infof("Matched version: %q", tfversion) - if ValidVersionFormat(tfversion) { //check if version format is correct + if validVersionFormat(tfversion) { //check if version format is correct return tfversion, nil } } diff --git a/lib/symlink.go b/lib/symlink.go index 19e48350..91bd9052 100644 --- a/lib/symlink.go +++ b/lib/symlink.go @@ -91,8 +91,8 @@ func CheckSymlink(symlinkPath string) bool { // ChangeSymlink : move symlink to existing binary func ChangeSymlink(binVersionPath string, binPath string) { - //installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file - binPath = InstallableBinLocation(binPath) + //installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file + binPath = installableBinLocation(binPath) /* remove current symlink if exist*/ symlinkExist := CheckSymlink(binPath) diff --git a/lib/utils.go b/lib/utils.go index cd33f0c0..f024430f 100644 --- a/lib/utils.go +++ b/lib/utils.go @@ -1,6 +1,8 @@ package lib import ( + "fmt" + "github.com/pborman/getopt" "os" ) @@ -19,3 +21,9 @@ func closeFileHandlers(handlers []*os.File) { _ = handler.Close() } } + +func UsageMessage() { + fmt.Print("\n\n") + getopt.PrintUsage(os.Stderr) + fmt.Println("Supply the terraform version as an argument, or choose from a menu") +} diff --git a/main.go b/main.go index 6a477328..3d69004c 100644 --- a/main.go +++ b/main.go @@ -19,14 +19,9 @@ package main import ( "fmt" + lib "github.com/warrensbox/terraform-switcher/lib" "github.com/warrensbox/terraform-switcher/lib/param_parsing" "os" - "path/filepath" - "strings" - - semver "github.com/hashicorp/go-version" - "github.com/manifoldco/promptui" - lib "github.com/warrensbox/terraform-switcher/lib" ) var parameters = param_parsing.GetParameters() @@ -44,150 +39,36 @@ func main() { } os.Exit(0) case parameters.HelpFlag: - param_parsing.UsageMessage() + lib.UsageMessage() os.Exit(0) case parameters.ListAllFlag: /* show all terraform version including betas and RCs*/ - installOption(true, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallOption(true, parameters.CustomBinaryPath, parameters.MirrorURL) case parameters.LatestPre != "": /* latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ - installLatestImplicitVersion(parameters.LatestPre, parameters.CustomBinaryPath, parameters.MirrorURL, true) + lib.InstallLatestImplicitVersion(parameters.LatestPre, parameters.CustomBinaryPath, parameters.MirrorURL, true) case parameters.ShowLatestPre != "": /* show latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ - showLatestImplicitVersion(parameters.ShowLatestPre, parameters.MirrorURL, true) + lib.ShowLatestImplicitVersion(parameters.ShowLatestPre, parameters.MirrorURL, true) case parameters.LatestStable != "": /* latest implicit version. Ex: tfswitch --latest-stable 0.13 downloads 0.13.5 (latest) */ - installLatestImplicitVersion(parameters.LatestStable, parameters.CustomBinaryPath, parameters.MirrorURL, false) + lib.InstallLatestImplicitVersion(parameters.LatestStable, parameters.CustomBinaryPath, parameters.MirrorURL, false) case parameters.ShowLatestStable != "": /* show latest implicit stable version. Ex: tfswitch --show-latest-stable 0.13 downloads 0.13.5 (latest) */ - showLatestImplicitVersion(parameters.ShowLatestStable, parameters.MirrorURL, false) + lib.ShowLatestImplicitVersion(parameters.ShowLatestStable, parameters.MirrorURL, false) case parameters.LatestFlag: /* latest stable version */ - installLatestVersion(parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallLatestVersion(parameters.CustomBinaryPath, parameters.MirrorURL) case parameters.ShowLatestFlag: /* show latest stable version */ - showLatestVersion(parameters.MirrorURL) + lib.ShowLatestVersion(parameters.MirrorURL) case parameters.Version != "": - installVersion(parameters.Version, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallVersion(parameters.Version, parameters.CustomBinaryPath, parameters.MirrorURL) case parameters.DefaultVersion != "": /* if default version is provided - Pick this instead of going for prompt */ - installVersion(parameters.DefaultVersion, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallVersion(parameters.DefaultVersion, parameters.CustomBinaryPath, parameters.MirrorURL) default: // Set list all false - only official release will be displayed - installOption(false, parameters.CustomBinaryPath, parameters.MirrorURL) - } -} - -// install latest stable tf version -func installLatestVersion(customBinaryPath, mirrorURL string) { - tfversion, _ := lib.GetTFLatest(mirrorURL) - lib.Install(tfversion, customBinaryPath, mirrorURL) -} - -// show install latest stable tf version -func showLatestVersion(mirrorURL string) { - tfversion, _ := lib.GetTFLatest(mirrorURL) - logger.Infof("%s", tfversion) -} - -// install latest - argument (version) must be provided -func installLatestImplicitVersion(requestedVersion, customBinaryPath, mirrorURL string, preRelease bool) { - _, err := semver.NewConstraint(requestedVersion) - if err != nil { - 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, customBinaryPath, mirrorURL) - } - logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) - lib.PrintInvalidMinorTFVersion() -} - -// show latest - argument (version) must be provided -func showLatestImplicitVersion(requestedVersion, mirrorURL string, preRelease bool) { - if lib.ValidMinorVersionFormat(requestedVersion) { - tfversion, _ := lib.GetTFLatestImplicit(mirrorURL, preRelease, requestedVersion) - if len(tfversion) > 0 { - logger.Infof("%s", tfversion) - } else { - logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") - os.Exit(1) - } - } else { - lib.PrintInvalidMinorTFVersion() - } -} - -// install with provided version as argument -func installVersion(arg, customBinaryPath, mirrorURL string) { - if lib.ValidVersionFormat(arg) { - requestedVersion := arg - - //check to see if the requested version has been downloaded before - installLocation := lib.GetInstallLocation() - installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(installLocation, lib.VersionPrefix+requestedVersion)) - recentDownloadFile := lib.CheckFileExist(installFileVersionPath) - if recentDownloadFile { - lib.ChangeSymlink(installFileVersionPath, customBinaryPath) - logger.Infof("Switched terraform to version %q", requestedVersion) - lib.AddRecent(requestedVersion) //add to recent file for faster lookup - os.Exit(0) - } - - // If the requested version had not been downloaded before - // Set list all true - all versions including beta and rc will be displayed - tflist, _ := lib.GetTFList(mirrorURL, true) // Get list of versions - exist := lib.VersionExist(requestedVersion, tflist) // Check if version exists before downloading it - - if exist { - lib.Install(requestedVersion, customBinaryPath, mirrorURL) - } else { - logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") - os.Exit(1) - } - - } else { - lib.PrintInvalidTFVersion() - logger.Error("Args must be a valid terraform version") - param_parsing.UsageMessage() - os.Exit(1) + lib.InstallOption(false, parameters.CustomBinaryPath, parameters.MirrorURL) } } - -/* installOption : displays & installs tf version */ -/* listAll = true - all versions including beta and rc will be displayed */ -/* listAll = false - only official stable release are displayed */ -func installOption(listAll bool, customBinaryPath, mirrorURL string) { - tflist, _ := lib.GetTFList(mirrorURL, listAll) // Get list of versions - recentVersions, _ := lib.GetRecentVersions() // Get recent versions from RECENT file - tflist = append(recentVersions, tflist...) // Append recent versions to the top of the list - tflist = lib.RemoveDuplicateVersions(tflist) // Remove duplicate version - - if len(tflist) == 0 { - logger.Fatalf("Terraform version list is empty: %s", mirrorURL) - os.Exit(1) - } - - /* prompt user to select version of terraform */ - prompt := promptui.Select{ - Label: "Select Terraform version", - Items: tflist, - } - - _, tfversion, errPrompt := prompt.Run() - tfversion = strings.Trim(tfversion, " *recent") //trim versions with the string " *recent" appended - - if errPrompt != nil { - if errPrompt.Error() == "^C" { - // Cancel execution - os.Exit(1) - } else { - logger.Fatalf("Prompt failed %v", errPrompt) - } - } - - lib.Install(tfversion, customBinaryPath, mirrorURL) - os.Exit(0) -} diff --git a/main_test.go b/main_test.go deleted file mode 100644 index f4156d6e..00000000 --- a/main_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "os/user" - "testing" - - "github.com/mitchellh/go-homedir" -) - -// TestMain : check to see if user exist -func TestMain(t *testing.T) { - - t.Run("User should exist", - func(t *testing.T) { - _, errCurr := user.Current() - if errCurr != nil { - t.Errorf("Unable to get user %v [unexpected]", errCurr) - } - _, errCurr = homedir.Dir() - if errCurr != nil { - t.Errorf("Unable to get user home directory: %v [unexpected]", errCurr) - } - }, - ) -} From dee1bd62eab317eb224956209457e8842f761491 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 11 Apr 2024 12:59:49 +0200 Subject: [PATCH 34/49] - added log-level to toml file --- lib/param_parsing/toml.go | 11 +++++++++-- lib/param_parsing/toml_test.go | 11 +++++++++++ test-data/test_tfswitchtoml/.tfswitch.toml | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 3b2b5d43..60cc7995 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -23,8 +23,15 @@ func getParamsTOML(params Params) Params { logger.Fatalf("Could not to read %q: %v", tomlPath, errs) } - params.Version = viperParser.GetString("version") // Attempt to get the version if it's provided in the toml - params.CustomBinaryPath = viperParser.GetString("bin") + if viperParser.Get("version") != nil { + params.Version = viperParser.GetString("version") + } + if viperParser.Get("bin") != nil { + params.CustomBinaryPath = viperParser.GetString("bin") + } + if viperParser.Get("log-level") != nil { + params.LogLevel = viperParser.GetString("log-level") + } } return params } diff --git a/lib/param_parsing/toml_test.go b/lib/param_parsing/toml_test.go index 679be62b..1bbf4405 100644 --- a/lib/param_parsing/toml_test.go +++ b/lib/param_parsing/toml_test.go @@ -1,12 +1,14 @@ package param_parsing import ( + "github.com/warrensbox/terraform-switcher/lib" "testing" ) func prepare() Params { var params Params params.ChDirPath = "../../test-data/test_tfswitchtoml" + logger = lib.InitLogger("DEBUG") return params } @@ -27,3 +29,12 @@ func TestGetParamsTOML_Version(t *testing.T) { t.Errorf("Version not matching. Got %v, expected %v", params.Version, expected) } } + +func TestGetParamsTOML_log_level(t *testing.T) { + expected := "NOTICE" + params := prepare() + params = getParamsTOML(params) + if params.LogLevel != expected { + t.Errorf("Version not matching. Got %v, expected %v", params.LogLevel, expected) + } +} diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/test_tfswitchtoml/.tfswitch.toml index dd8d5095..1089c0b4 100644 --- a/test-data/test_tfswitchtoml/.tfswitch.toml +++ b/test-data/test_tfswitchtoml/.tfswitch.toml @@ -1,2 +1,3 @@ bin = "/usr/local/bin/terraform_from_toml" version = "0.11.4" +log-level = "NOTICE" From 3c75651a17b71d20667f271a83e8a54d14ffb3a2 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Thu, 11 Apr 2024 13:30:59 +0200 Subject: [PATCH 35/49] - sort if block alphabetically --- lib/param_parsing/toml.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index 60cc7995..a8668644 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -23,15 +23,15 @@ func getParamsTOML(params Params) Params { logger.Fatalf("Could not to read %q: %v", tomlPath, errs) } - if viperParser.Get("version") != nil { - params.Version = viperParser.GetString("version") - } if viperParser.Get("bin") != nil { params.CustomBinaryPath = viperParser.GetString("bin") } if viperParser.Get("log-level") != nil { params.LogLevel = viperParser.GetString("log-level") } + if viperParser.Get("version") != nil { + params.Version = viperParser.GetString("version") + } } return params } From 8286b200e42742e778ba8ee83a7a64e27bf90475 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 09:41:20 +0200 Subject: [PATCH 36/49] - added test for defect terragrunt decalaration - added test for non existing file for terragrunt and .terraform-version file --- lib/param_parsing/parameters.go | 8 +++-- lib/param_parsing/terraform_version.go | 7 +++-- lib/param_parsing/terraform_version_test.go | 11 ++++++- lib/param_parsing/terragrunt.go | 12 ++++---- lib/param_parsing/terragrunt_test.go | 30 ++++++++++++++++++- test-data/test_no_file/dummy_file | 0 .../test_terragrunt_error_hcl/terragrunt.hcl | 1 + 7 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 test-data/test_no_file/dummy_file create mode 100644 test-data/test_terragrunt_error_hcl/terragrunt.hcl diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 7889486e..f2df0c06 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -49,20 +49,24 @@ func GetParameters() Params { getopt.Parse() logger = lib.InitLogger(params.LogLevel) + var err error // Read configuration files if tomlFileExists(params) { params = getParamsTOML(params) } else if tfSwitchFileExists(params) { params = GetParamsFromTfSwitch(params) } else if terraformVersionFileExists(params) { - params = GetParamsFromTerraformVersion(params) + params, err = GetParamsFromTerraformVersion(params) } else if isTerraformModule(params) { params = GetVersionFromVersionsTF(params) } else if terraGruntFileExists(params) { - params = GetVersionFromTerragrunt(params) + params, err = GetVersionFromTerragrunt(params) } else { params = GetParamsFromEnvironment(params) } + if err != nil { + logger.Fatalf("Error parsing configuration file: %q", err) + } // Parse again to overwrite anything that might by defined on the cli AND in any config file (CLI always wins) getopt.Parse() diff --git a/lib/param_parsing/terraform_version.go b/lib/param_parsing/terraform_version.go index 0e38e4d6..dda3737c 100644 --- a/lib/param_parsing/terraform_version.go +++ b/lib/param_parsing/terraform_version.go @@ -8,17 +8,18 @@ import ( const terraformVersionFileName = ".terraform-version" -func GetParamsFromTerraformVersion(params Params) Params { +func GetParamsFromTerraformVersion(params Params) (Params, error) { filePath := params.ChDirPath + "/" + terraformVersionFileName if lib.CheckFileExist(filePath) { logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) if err != nil { - logger.Fatalf("Could not read file content at %q: %v", filePath, err) + logger.Errorf("Could not read file content at %q: %v", filePath, err) + return params, err } params.Version = strings.TrimSpace(string(content)) } - return params + return params, nil } func terraformVersionFileExists(params Params) bool { diff --git a/lib/param_parsing/terraform_version_test.go b/lib/param_parsing/terraform_version_test.go index 883ce29f..78324d74 100644 --- a/lib/param_parsing/terraform_version_test.go +++ b/lib/param_parsing/terraform_version_test.go @@ -7,9 +7,18 @@ import ( func TestGetParamsFromTerraformVersion(t *testing.T) { var params Params params.ChDirPath = "../../test-data/test_terraform-version" - params = GetParamsFromTerraformVersion(params) + params, _ = GetParamsFromTerraformVersion(params) expected := "0.11.0" if params.Version != expected { t.Errorf("Version from .terraform-version not read correctly. Got: %v, Expect: %v", params.Version, expected) } } + +func TestGetParamsFromTerraformVersion_no_file(t *testing.T) { + var params Params + params.ChDirPath = "../../test-data/test_no_file" + params, _ = GetParamsFromTerraformVersion(params) + if params.Version != "" { + t.Errorf("Expected emtpy version string. Got: %v", params.Version) + } +} diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index b4e1c440..9273e08d 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -1,6 +1,7 @@ package param_parsing import ( + "fmt" "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/hclparse" "github.com/warrensbox/terraform-switcher/lib" @@ -12,27 +13,28 @@ type terragruntVersionConstraints struct { TerraformVersionConstraint string `hcl:"terraform_version_constraint"` } -func GetVersionFromTerragrunt(params Params) Params { +func GetVersionFromTerragrunt(params Params) (Params, error) { filePath := params.ChDirPath + "/" + terraGruntFileName if lib.CheckFileExist(filePath) { logger.Infof("Reading configuration from %q", filePath) parser := hclparse.NewParser() hclFile, diagnostics := parser.ParseHCLFile(filePath) if diagnostics.HasErrors() { - logger.Fatalf("Unable to parse HCL file %q", filePath) + return params, fmt.Errorf("unable to parse HCL file %q", filePath) + //logger.Fatalf("Unable to parse HCL file %q", filePath) } var versionFromTerragrunt terragruntVersionConstraints diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) if diagnostics.HasErrors() { - logger.Fatalf("Could not decode body of HCL file %q", filePath) + return params, fmt.Errorf("could not decode body of HCL file %q", filePath) } version, err := lib.GetSemver(versionFromTerragrunt.TerraformVersionConstraint, params.MirrorURL) if err != nil { - logger.Fatalf("No version found matching %q", versionFromTerragrunt.TerraformVersionConstraint) + return params, fmt.Errorf("no version found matching %q", versionFromTerragrunt.TerraformVersionConstraint) } params.Version = version } - return params + return params, nil } func terraGruntFileExists(params Params) bool { diff --git a/lib/param_parsing/terragrunt_test.go b/lib/param_parsing/terragrunt_test.go index c0452678..ddebb5b5 100644 --- a/lib/param_parsing/terragrunt_test.go +++ b/lib/param_parsing/terragrunt_test.go @@ -2,6 +2,7 @@ package param_parsing import ( "github.com/hashicorp/go-version" + "github.com/warrensbox/terraform-switcher/lib" "testing" ) @@ -9,7 +10,7 @@ func TestGetVersionFromTerragrunt(t *testing.T) { var params Params params = initParams(params) params.ChDirPath = "../../test-data/test_terragrunt_hcl" - params = GetVersionFromTerragrunt(params) + params, _ = GetVersionFromTerragrunt(params) v1, _ := version.NewVersion("0.13") v2, _ := version.NewVersion("0.14") actualVersion, _ := version.NewVersion(params.Version) @@ -17,3 +18,30 @@ func TestGetVersionFromTerragrunt(t *testing.T) { t.Error("Determined version is not between 0.13 and 0.14") } } + +func TestGetVersionTerragrunt_with_no_terragrunt_file(t *testing.T) { + var params Params + logger = lib.InitLogger("DEBUG") + params = initParams(params) + params.ChDirPath = "../../test-data/test_no_file" + params, _ = GetVersionFromTerragrunt(params) + if params.Version != "" { + t.Error("Version should be empty") + } +} + +func TestGetVersionFromTerragrunt_erroneous_file(t *testing.T) { + var params Params + logger = lib.InitLogger("DEBUG") + params = initParams(params) + params.ChDirPath = "../../test-data/test_terragrunt_error_hcl" + params, err := GetVersionFromTerragrunt(params) + if err == nil { + t.Error("Expected error but got none.") + } else { + expectedError := "could not decode body of HCL file \"../../test-data/test_terragrunt_error_hcl/terragrunt.hcl\"" + if err.Error() != expectedError { + t.Errorf("Expected error to be '%q', got '%q'", expectedError, err) + } + } +} diff --git a/test-data/test_no_file/dummy_file b/test-data/test_no_file/dummy_file new file mode 100644 index 00000000..e69de29b diff --git a/test-data/test_terragrunt_error_hcl/terragrunt.hcl b/test-data/test_terragrunt_error_hcl/terragrunt.hcl new file mode 100644 index 00000000..ab8ebe77 --- /dev/null +++ b/test-data/test_terragrunt_error_hcl/terragrunt.hcl @@ -0,0 +1 @@ +terraform_vers_agrtz_ion_constraint = ">= 0.13, < 0.14" From cb390113fb40efb1216d973edd411ed10f274175 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 09:42:55 +0200 Subject: [PATCH 37/49] - added test for non existing file for .tfswitchrc file --- lib/param_parsing/parameters.go | 2 +- lib/param_parsing/tfswitch.go | 7 ++++--- lib/param_parsing/tfswitch_test.go | 11 ++++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index f2df0c06..d0e3158d 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -54,7 +54,7 @@ func GetParameters() Params { if tomlFileExists(params) { params = getParamsTOML(params) } else if tfSwitchFileExists(params) { - params = GetParamsFromTfSwitch(params) + params, err = GetParamsFromTfSwitch(params) } else if terraformVersionFileExists(params) { params, err = GetParamsFromTerraformVersion(params) } else if isTerraformModule(params) { diff --git a/lib/param_parsing/tfswitch.go b/lib/param_parsing/tfswitch.go index 4744d686..580eb658 100644 --- a/lib/param_parsing/tfswitch.go +++ b/lib/param_parsing/tfswitch.go @@ -8,17 +8,18 @@ import ( const tfSwitchFileName = ".tfswitchrc" -func GetParamsFromTfSwitch(params Params) Params { +func GetParamsFromTfSwitch(params Params) (Params, error) { filePath := params.ChDirPath + "/" + tfSwitchFileName if lib.CheckFileExist(filePath) { logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) if err != nil { - logger.Fatalf("Could not read file content from %q: %v", filePath, err) + logger.Errorf("Could not read file content from %q: %v", filePath, err) + return params, err } params.Version = strings.TrimSpace(string(content)) } - return params + return params, nil } func tfSwitchFileExists(params Params) bool { diff --git a/lib/param_parsing/tfswitch_test.go b/lib/param_parsing/tfswitch_test.go index 12261c47..5cea7065 100644 --- a/lib/param_parsing/tfswitch_test.go +++ b/lib/param_parsing/tfswitch_test.go @@ -7,9 +7,18 @@ import ( func TestGetParamsFromTfSwitch(t *testing.T) { var params Params params.ChDirPath = "../../test-data/test_tfswitchrc" - params = GetParamsFromTfSwitch(params) + params, _ = GetParamsFromTfSwitch(params) expected := "0.10.5" if params.Version != expected { t.Error("Version from tfswitchrc not read correctly. Actual: " + params.Version + ", Expected: " + expected) } } + +func TestGetParamsFromTfSwitch_no_file(t *testing.T) { + var params Params + params.ChDirPath = "../../test-data/test_no_file" + params, _ = GetParamsFromTfSwitch(params) + if params.Version != "" { + t.Errorf("Expected emtpy version string. Got: %v", params.Version) + } +} From bc11354442e8da9c0a467e2f479c68369b621c84 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 09:48:26 +0200 Subject: [PATCH 38/49] - added test for non existing and erroneous file for tfswitch.toml file --- lib/param_parsing/parameters.go | 2 +- lib/param_parsing/toml.go | 7 +++--- lib/param_parsing/toml_test.go | 25 ++++++++++++++++--- .../test_tfswitchtoml_error/.tfswitch.toml | 3 +++ 4 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 test-data/test_tfswitchtoml_error/.tfswitch.toml diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index d0e3158d..784147e6 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -52,7 +52,7 @@ func GetParameters() Params { var err error // Read configuration files if tomlFileExists(params) { - params = getParamsTOML(params) + params, err = getParamsTOML(params) } else if tfSwitchFileExists(params) { params, err = GetParamsFromTfSwitch(params) } else if terraformVersionFileExists(params) { diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index a8668644..ae06c9f0 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -8,7 +8,7 @@ import ( const tfSwitchTOMLFileName = ".tfswitch.toml" // getParamsTOML parses everything in the toml file, return required version and bin path -func getParamsTOML(params Params) Params { +func getParamsTOML(params Params) (Params, error) { tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName if tomlFileExists(params) { logger.Infof("Reading configuration from %q", tomlPath) @@ -20,7 +20,8 @@ func getParamsTOML(params Params) Params { errs := viperParser.ReadInConfig() // Find and read the config file if errs != nil { - logger.Fatalf("Could not to read %q: %v", tomlPath, errs) + logger.Errorf("Could not to read %q: %v", tomlPath, errs) + return params, errs } if viperParser.Get("bin") != nil { @@ -33,7 +34,7 @@ func getParamsTOML(params Params) Params { params.Version = viperParser.GetString("version") } } - return params + return params, nil } func tomlFileExists(params Params) bool { diff --git a/lib/param_parsing/toml_test.go b/lib/param_parsing/toml_test.go index 1bbf4405..258e774e 100644 --- a/lib/param_parsing/toml_test.go +++ b/lib/param_parsing/toml_test.go @@ -15,7 +15,7 @@ func prepare() Params { func TestGetParamsTOML_BinaryPath(t *testing.T) { expected := "/usr/local/bin/terraform_from_toml" params := prepare() - params = getParamsTOML(params) + params, _ = getParamsTOML(params) if params.CustomBinaryPath != expected { t.Errorf("BinaryPath not matching. Got %v, expected %v", params.CustomBinaryPath, expected) } @@ -24,7 +24,7 @@ func TestGetParamsTOML_BinaryPath(t *testing.T) { func TestGetParamsTOML_Version(t *testing.T) { expected := "0.11.4" params := prepare() - params = getParamsTOML(params) + params, _ = getParamsTOML(params) if params.Version != expected { t.Errorf("Version not matching. Got %v, expected %v", params.Version, expected) } @@ -33,8 +33,27 @@ func TestGetParamsTOML_Version(t *testing.T) { func TestGetParamsTOML_log_level(t *testing.T) { expected := "NOTICE" params := prepare() - params = getParamsTOML(params) + params, _ = getParamsTOML(params) if params.LogLevel != expected { t.Errorf("Version not matching. Got %v, expected %v", params.LogLevel, expected) } } + +func TestGetParamsTOML_no_file(t *testing.T) { + var params Params + params.ChDirPath = "../../test-data/test_no_file" + params, _ = getParamsTOML(params) + if params.Version != "" { + t.Errorf("Expected emtpy version string. Got: %v", params.Version) + } +} + +func TestGetParamsTOML_error_in_file(t *testing.T) { + logger = lib.InitLogger("DEBUG") + var params Params + params.ChDirPath = "../../test-data/test_tfswitchtoml_error" + params, err := getParamsTOML(params) + if err == nil { + t.Errorf("Expected error for reading erroneous toml file. Got nil") + } +} diff --git a/test-data/test_tfswitchtoml_error/.tfswitch.toml b/test-data/test_tfswitchtoml_error/.tfswitch.toml new file mode 100644 index 00000000..1ad6ffa2 --- /dev/null +++ b/test-data/test_tfswitchtoml_error/.tfswitch.toml @@ -0,0 +1,3 @@ +bin sdf= "/usr/local/bin/terraform_from_toml" +version =sdfh "0.11.4" +log-level =w35 "NOTICE" From 5f7b62782cea84b8a421bd968ab45ddf6998f1d9 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 10:09:05 +0200 Subject: [PATCH 39/49] - added test for non existing, erroneous terraform module file - added test for non existent version in terraform --- lib/param_parsing/parameters.go | 2 +- lib/param_parsing/versiontf.go | 14 ++++--- lib/param_parsing/versiontf_test.go | 37 ++++++++++++++++++- lib/semver.go | 8 ++-- test-data/test_versiontf_error/version.tf | 8 ++++ .../test_versiontf_non_existent/version.tf | 8 ++++ 6 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 test-data/test_versiontf_error/version.tf create mode 100644 test-data/test_versiontf_non_existent/version.tf diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 784147e6..e211f922 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -58,7 +58,7 @@ func GetParameters() Params { } else if terraformVersionFileExists(params) { params, err = GetParamsFromTerraformVersion(params) } else if isTerraformModule(params) { - params = GetVersionFromVersionsTF(params) + params, _ = GetVersionFromVersionsTF(params) } else if terraGruntFileExists(params) { params, err = GetVersionFromTerragrunt(params) } else { diff --git a/lib/param_parsing/versiontf.go b/lib/param_parsing/versiontf.go index 0e9c1a2e..38852c4f 100644 --- a/lib/param_parsing/versiontf.go +++ b/lib/param_parsing/versiontf.go @@ -5,19 +5,21 @@ import ( "github.com/warrensbox/terraform-switcher/lib" ) -func GetVersionFromVersionsTF(params Params) Params { +func GetVersionFromVersionsTF(params Params) (Params, error) { logger.Infof("Reading version from terraform module at %q", params.ChDirPath) module, err := tfconfig.LoadModule(params.ChDirPath) if err != nil { - logger.Fatalf("Could not load terraform module at %q", params.ChDirPath) + logger.Errorf("Could not load terraform module at %q", params.ChDirPath) + return params, err.Err() } - tfconstraint := module.RequiredCore[0] - version, err2 := lib.GetSemver(tfconstraint, params.MirrorURL) + tfConstraint := module.RequiredCore[0] + version, err2 := lib.GetSemver(tfConstraint, params.MirrorURL) if err2 != nil { - logger.Fatalf("No version found matching %q", tfconstraint) + logger.Errorf("No version found matching %q", tfConstraint) + return params, err2 } params.Version = version - return params + return params, nil } func isTerraformModule(params Params) bool { diff --git a/lib/param_parsing/versiontf_test.go b/lib/param_parsing/versiontf_test.go index 345fa96f..137fe30d 100644 --- a/lib/param_parsing/versiontf_test.go +++ b/lib/param_parsing/versiontf_test.go @@ -1,15 +1,18 @@ package param_parsing import ( + "fmt" "github.com/hashicorp/go-version" + "github.com/warrensbox/terraform-switcher/lib" "testing" ) func TestGetVersionFromVersionsTF(t *testing.T) { + logger = lib.InitLogger("DEBUG") var params Params params = initParams(params) params.ChDirPath = "../../test-data/test_versiontf" - params = GetVersionFromVersionsTF(params) + params, _ = GetVersionFromVersionsTF(params) v1, _ := version.NewVersion("1.0.0") v2, _ := version.NewVersion("2.0.0") actualVersion, _ := version.NewVersion(params.Version) @@ -17,3 +20,35 @@ func TestGetVersionFromVersionsTF(t *testing.T) { t.Error("Determined version is not between 1.0.0 and 2.0.0") } } + +func TestGetVersionFromVersionsTF_erroneous_file(t *testing.T) { + logger = lib.InitLogger("DEBUG") + var params Params + params = initParams(params) + params.ChDirPath = "../../test-data/test_versiontf_error" + params, err := GetVersionFromVersionsTF(params) + if err == nil { + t.Error("Expected error got nil") + } else { + expected := "error parsing constraint: Malformed constraint: ~527> 1.0.0" + if fmt.Sprint(err) != expected { + t.Errorf("Expected error %q, got %q", expected, err) + } + } +} + +func TestGetVersionFromVersionsTF_non_existent_constraint(t *testing.T) { + logger = lib.InitLogger("DEBUG") + var params Params + params = initParams(params) + params.ChDirPath = "../../test-data/test_versiontf_non_existent" + params, err := GetVersionFromVersionsTF(params) + if err == nil { + t.Error("Expected error got nil") + } else { + expected := "did not find version matching constraint: > 99999.0.0" + if fmt.Sprint(err) != expected { + t.Errorf("Expected error %q, got %q", expected, err) + } + } +} diff --git a/lib/semver.go b/lib/semver.go index ad4ee6fa..fa8f138a 100644 --- a/lib/semver.go +++ b/lib/semver.go @@ -38,15 +38,15 @@ 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() - logger.Infof("Matched version: %q", tfversion) if validVersionFormat(tfversion) { //check if version format is correct + logger.Infof("Matched version: %q", tfversion) return tfversion, nil + } else { + PrintInvalidTFVersion() } } } - - PrintInvalidTFVersion() - return "", fmt.Errorf("error parsing constraint: %s", *tfconstraint) + return "", fmt.Errorf("did not find version matching constraint: %s", *tfconstraint) } // PrintInvalidTFVersion Print invalid TF version diff --git a/test-data/test_versiontf_error/version.tf b/test-data/test_versiontf_error/version.tf new file mode 100644 index 00000000..8c37904d --- /dev/null +++ b/test-data/test_versiontf_error/version.tf @@ -0,0 +1,8 @@ +terraform { + required_version = "~527> 1.0.0" + + required_providers { + aws = ">325= 2.52.0" + kubernetes = ">32= 1.11.1" + } +} diff --git a/test-data/test_versiontf_non_existent/version.tf b/test-data/test_versiontf_non_existent/version.tf new file mode 100644 index 00000000..8b8612f8 --- /dev/null +++ b/test-data/test_versiontf_non_existent/version.tf @@ -0,0 +1,8 @@ +terraform { + required_version = "> 99999.0.0" + + required_providers { + aws = ">= 2.52.0" + kubernetes = ">= 1.11.1" + } +} From 7dfa3c9c4542f5f0d6172531c4be5b3f5b543248 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 10:09:41 +0200 Subject: [PATCH 40/49] - fixed comment counter - deferred files closures --- lib/files.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/files.go b/lib/files.go index 0c0f227f..e8992364 100644 --- a/lib/files.go +++ b/lib/files.go @@ -207,13 +207,13 @@ func GetCurrentDirectory() string { func unzipFile(f *zip.File, destination string, wg *sync.WaitGroup) error { defer wg.Done() - // 4. Check if file paths are not vulnerable to Zip Slip + // 1. Check if file paths are not vulnerable to Zip Slip filePath := filepath.Join(destination, f.Name) if !strings.HasPrefix(filePath, filepath.Clean(destination)+string(os.PathSeparator)) { return fmt.Errorf("Invalid file path: %q", filePath) } - // 5. Create directory tree + // 2. Create directory tree if f.FileInfo().IsDir() { logger.Debugf("Extracting directory %q", filePath) if err := os.MkdirAll(filePath, os.ModePerm); err != nil { @@ -226,14 +226,20 @@ func unzipFile(f *zip.File, destination string, wg *sync.WaitGroup) error { return err } - // 6. Create a destination file for unzipped content + // 3. Create a destination file for unzipped content destinationFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + defer func(destinationFile *os.File) { + _ = destinationFile.Close() + }(destinationFile) if err != nil { return err } - // 7. Unzip the content of a file and copy it to the destination file + // 4. Unzip the content of a file and copy it to the destination file zippedFile, err := f.Open() + defer func(zippedFile io.ReadCloser) { + _ = zippedFile.Close() + }(zippedFile) if err != nil { return err } From f3ba257189a1440ff8932fcbcfb2b60f310fafea Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 10:38:22 +0200 Subject: [PATCH 41/49] - added an exception for integration tests as an empty or an erroneous file would lead to showing the dropdown list which cannot be handled in an integration test, thus the test runs infinitely --- .github/workflows/build.yml | 2 +- lib/param_parsing/parameters_test.go | 6 +++--- lib/param_parsing/terraform_version_test.go | 4 ++-- lib/param_parsing/terragrunt_test.go | 8 ++++---- lib/param_parsing/tfswitch_test.go | 4 ++-- lib/param_parsing/toml_test.go | 6 +++--- lib/param_parsing/versiontf_test.go | 6 +++--- .../test_precedence/.terraform-version | 0 .../test_precedence/.tfswitch.toml | 0 .../{ => integration-tests}/test_precedence/.tfswitchrc | 0 .../test_precedence/terragrunt.hcl | 0 .../test_terraform-version/.terraform-version | 0 .../test_terragrunt_hcl/terragrunt.hcl | 0 .../{ => integration-tests}/test_tfswitchrc/.tfswitchrc | 0 .../test_tfswitchtoml/.tfswitch.toml | 0 .../{ => integration-tests}/test_versiontf/version.tf | 0 .../{ => skip-integration-tests}/test_no_file/dummy_file | 0 .../test_terragrunt_error_hcl/terragrunt.hcl | 0 .../test_tfswitchtoml_error/.tfswitch.toml | 0 .../test_versiontf_error/version.tf | 0 .../test_versiontf_non_existent/version.tf | 0 21 files changed, 18 insertions(+), 18 deletions(-) rename test-data/{ => integration-tests}/test_precedence/.terraform-version (100%) rename test-data/{ => integration-tests}/test_precedence/.tfswitch.toml (100%) rename test-data/{ => integration-tests}/test_precedence/.tfswitchrc (100%) rename test-data/{ => integration-tests}/test_precedence/terragrunt.hcl (100%) rename test-data/{ => integration-tests}/test_terraform-version/.terraform-version (100%) rename test-data/{ => integration-tests}/test_terragrunt_hcl/terragrunt.hcl (100%) rename test-data/{ => integration-tests}/test_tfswitchrc/.tfswitchrc (100%) rename test-data/{ => integration-tests}/test_tfswitchtoml/.tfswitch.toml (100%) rename test-data/{ => integration-tests}/test_versiontf/version.tf (100%) rename test-data/{ => skip-integration-tests}/test_no_file/dummy_file (100%) rename test-data/{ => skip-integration-tests}/test_terragrunt_error_hcl/terragrunt.hcl (100%) rename test-data/{ => skip-integration-tests}/test_tfswitchtoml_error/.tfswitch.toml (100%) rename test-data/{ => skip-integration-tests}/test_versiontf_error/version.tf (100%) rename test-data/{ => skip-integration-tests}/test_versiontf_non_existent/version.tf (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ae7594e7..0cf242d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,7 +67,7 @@ jobs: mkdir -p build go build -v -o build/tfswitch mkdir `pwd`/bin/ - find ./test-data/* -type d -print0 | while read -r -d $'\0' TEST_PATH; do + find ./test-data/integration-tests/* -type d -print0 | while read -r -d $'\0' TEST_PATH; do ./build/tfswitch -c "${TEST_PATH}" -b `pwd`/bin/terraform || exit 1 done diff --git a/lib/param_parsing/parameters_test.go b/lib/param_parsing/parameters_test.go index f0a7b2d4..b36cdf06 100644 --- a/lib/param_parsing/parameters_test.go +++ b/lib/param_parsing/parameters_test.go @@ -23,7 +23,7 @@ func TestGetParameters_params_are_overridden_by_toml_file(t *testing.T) { t.Cleanup(func() { getopt.CommandLine = getopt.New() }) - expected := "../../test-data/test_tfswitchtoml" + expected := "../../test-data/integration-tests/test_tfswitchtoml" os.Args = []string{"cmd", "--chdir=" + expected} params := GetParameters() actual := params.ChDirPath @@ -46,7 +46,7 @@ func TestGetParameters_toml_params_are_overridden_by_cli(t *testing.T) { t.Cleanup(func() { getopt.CommandLine = getopt.New() }) - expected := "../../test-data/test_tfswitchtoml" + expected := "../../test-data/integration-tests/test_tfswitchtoml" os.Args = []string{"cmd", "--chdir=" + expected, "--bin=/usr/test/bin"} params := GetParameters() actual := params.ChDirPath @@ -70,7 +70,7 @@ func TestGetParameters_check_config_precedence(t *testing.T) { t.Cleanup(func() { getopt.CommandLine = getopt.New() }) - os.Args = []string{"cmd", "--chdir=../../test-data/test_precedence"} + os.Args = []string{"cmd", "--chdir=../../test-data/integration-tests/test_precedence"} parameters := prepare() parameters = GetParameters() expected := "0.11.3" diff --git a/lib/param_parsing/terraform_version_test.go b/lib/param_parsing/terraform_version_test.go index 78324d74..9e4ac4ba 100644 --- a/lib/param_parsing/terraform_version_test.go +++ b/lib/param_parsing/terraform_version_test.go @@ -6,7 +6,7 @@ import ( func TestGetParamsFromTerraformVersion(t *testing.T) { var params Params - params.ChDirPath = "../../test-data/test_terraform-version" + params.ChDirPath = "../../test-data/integration-tests/test_terraform-version" params, _ = GetParamsFromTerraformVersion(params) expected := "0.11.0" if params.Version != expected { @@ -16,7 +16,7 @@ func TestGetParamsFromTerraformVersion(t *testing.T) { func TestGetParamsFromTerraformVersion_no_file(t *testing.T) { var params Params - params.ChDirPath = "../../test-data/test_no_file" + params.ChDirPath = "../../test-data/skip-integration-tests/test_no_file" params, _ = GetParamsFromTerraformVersion(params) if params.Version != "" { t.Errorf("Expected emtpy version string. Got: %v", params.Version) diff --git a/lib/param_parsing/terragrunt_test.go b/lib/param_parsing/terragrunt_test.go index ddebb5b5..46796d3f 100644 --- a/lib/param_parsing/terragrunt_test.go +++ b/lib/param_parsing/terragrunt_test.go @@ -9,7 +9,7 @@ import ( func TestGetVersionFromTerragrunt(t *testing.T) { var params Params params = initParams(params) - params.ChDirPath = "../../test-data/test_terragrunt_hcl" + params.ChDirPath = "../../test-data/integration-tests/test_terragrunt_hcl" params, _ = GetVersionFromTerragrunt(params) v1, _ := version.NewVersion("0.13") v2, _ := version.NewVersion("0.14") @@ -23,7 +23,7 @@ func TestGetVersionTerragrunt_with_no_terragrunt_file(t *testing.T) { var params Params logger = lib.InitLogger("DEBUG") params = initParams(params) - params.ChDirPath = "../../test-data/test_no_file" + params.ChDirPath = "../../test-data/skip-integration-tests/test_no_file" params, _ = GetVersionFromTerragrunt(params) if params.Version != "" { t.Error("Version should be empty") @@ -34,12 +34,12 @@ func TestGetVersionFromTerragrunt_erroneous_file(t *testing.T) { var params Params logger = lib.InitLogger("DEBUG") params = initParams(params) - params.ChDirPath = "../../test-data/test_terragrunt_error_hcl" + params.ChDirPath = "../../test-data/skip-integration-tests/test_terragrunt_error_hcl" params, err := GetVersionFromTerragrunt(params) if err == nil { t.Error("Expected error but got none.") } else { - expectedError := "could not decode body of HCL file \"../../test-data/test_terragrunt_error_hcl/terragrunt.hcl\"" + expectedError := "could not decode body of HCL file \"../../test-data/skip-integration-tests/test_terragrunt_error_hcl/terragrunt.hcl\"" if err.Error() != expectedError { t.Errorf("Expected error to be '%q', got '%q'", expectedError, err) } diff --git a/lib/param_parsing/tfswitch_test.go b/lib/param_parsing/tfswitch_test.go index 5cea7065..8d5b39df 100644 --- a/lib/param_parsing/tfswitch_test.go +++ b/lib/param_parsing/tfswitch_test.go @@ -6,7 +6,7 @@ import ( func TestGetParamsFromTfSwitch(t *testing.T) { var params Params - params.ChDirPath = "../../test-data/test_tfswitchrc" + params.ChDirPath = "../../test-data/integration-tests/test_tfswitchrc" params, _ = GetParamsFromTfSwitch(params) expected := "0.10.5" if params.Version != expected { @@ -16,7 +16,7 @@ func TestGetParamsFromTfSwitch(t *testing.T) { func TestGetParamsFromTfSwitch_no_file(t *testing.T) { var params Params - params.ChDirPath = "../../test-data/test_no_file" + params.ChDirPath = "../../test-data/skip-integration-tests/test_no_file" params, _ = GetParamsFromTfSwitch(params) if params.Version != "" { t.Errorf("Expected emtpy version string. Got: %v", params.Version) diff --git a/lib/param_parsing/toml_test.go b/lib/param_parsing/toml_test.go index 258e774e..063f757e 100644 --- a/lib/param_parsing/toml_test.go +++ b/lib/param_parsing/toml_test.go @@ -7,7 +7,7 @@ import ( func prepare() Params { var params Params - params.ChDirPath = "../../test-data/test_tfswitchtoml" + params.ChDirPath = "../../test-data/integration-tests/test_tfswitchtoml" logger = lib.InitLogger("DEBUG") return params } @@ -41,7 +41,7 @@ func TestGetParamsTOML_log_level(t *testing.T) { func TestGetParamsTOML_no_file(t *testing.T) { var params Params - params.ChDirPath = "../../test-data/test_no_file" + params.ChDirPath = "../../test-data/skip-integration-tests/test_no_file" params, _ = getParamsTOML(params) if params.Version != "" { t.Errorf("Expected emtpy version string. Got: %v", params.Version) @@ -51,7 +51,7 @@ func TestGetParamsTOML_no_file(t *testing.T) { func TestGetParamsTOML_error_in_file(t *testing.T) { logger = lib.InitLogger("DEBUG") var params Params - params.ChDirPath = "../../test-data/test_tfswitchtoml_error" + params.ChDirPath = "../../test-data/skip-integration-tests/test_tfswitchtoml_error" params, err := getParamsTOML(params) if err == nil { t.Errorf("Expected error for reading erroneous toml file. Got nil") diff --git a/lib/param_parsing/versiontf_test.go b/lib/param_parsing/versiontf_test.go index 137fe30d..245f9ec5 100644 --- a/lib/param_parsing/versiontf_test.go +++ b/lib/param_parsing/versiontf_test.go @@ -11,7 +11,7 @@ func TestGetVersionFromVersionsTF(t *testing.T) { logger = lib.InitLogger("DEBUG") var params Params params = initParams(params) - params.ChDirPath = "../../test-data/test_versiontf" + params.ChDirPath = "../../test-data/integration-tests/test_versiontf" params, _ = GetVersionFromVersionsTF(params) v1, _ := version.NewVersion("1.0.0") v2, _ := version.NewVersion("2.0.0") @@ -25,7 +25,7 @@ func TestGetVersionFromVersionsTF_erroneous_file(t *testing.T) { logger = lib.InitLogger("DEBUG") var params Params params = initParams(params) - params.ChDirPath = "../../test-data/test_versiontf_error" + params.ChDirPath = "../../test-data/skip-integration-tests/test_versiontf_error" params, err := GetVersionFromVersionsTF(params) if err == nil { t.Error("Expected error got nil") @@ -41,7 +41,7 @@ func TestGetVersionFromVersionsTF_non_existent_constraint(t *testing.T) { logger = lib.InitLogger("DEBUG") var params Params params = initParams(params) - params.ChDirPath = "../../test-data/test_versiontf_non_existent" + params.ChDirPath = "../../test-data/skip-integration-tests/test_versiontf_non_existent" params, err := GetVersionFromVersionsTF(params) if err == nil { t.Error("Expected error got nil") diff --git a/test-data/test_precedence/.terraform-version b/test-data/integration-tests/test_precedence/.terraform-version similarity index 100% rename from test-data/test_precedence/.terraform-version rename to test-data/integration-tests/test_precedence/.terraform-version diff --git a/test-data/test_precedence/.tfswitch.toml b/test-data/integration-tests/test_precedence/.tfswitch.toml similarity index 100% rename from test-data/test_precedence/.tfswitch.toml rename to test-data/integration-tests/test_precedence/.tfswitch.toml diff --git a/test-data/test_precedence/.tfswitchrc b/test-data/integration-tests/test_precedence/.tfswitchrc similarity index 100% rename from test-data/test_precedence/.tfswitchrc rename to test-data/integration-tests/test_precedence/.tfswitchrc diff --git a/test-data/test_precedence/terragrunt.hcl b/test-data/integration-tests/test_precedence/terragrunt.hcl similarity index 100% rename from test-data/test_precedence/terragrunt.hcl rename to test-data/integration-tests/test_precedence/terragrunt.hcl diff --git a/test-data/test_terraform-version/.terraform-version b/test-data/integration-tests/test_terraform-version/.terraform-version similarity index 100% rename from test-data/test_terraform-version/.terraform-version rename to test-data/integration-tests/test_terraform-version/.terraform-version diff --git a/test-data/test_terragrunt_hcl/terragrunt.hcl b/test-data/integration-tests/test_terragrunt_hcl/terragrunt.hcl similarity index 100% rename from test-data/test_terragrunt_hcl/terragrunt.hcl rename to test-data/integration-tests/test_terragrunt_hcl/terragrunt.hcl diff --git a/test-data/test_tfswitchrc/.tfswitchrc b/test-data/integration-tests/test_tfswitchrc/.tfswitchrc similarity index 100% rename from test-data/test_tfswitchrc/.tfswitchrc rename to test-data/integration-tests/test_tfswitchrc/.tfswitchrc diff --git a/test-data/test_tfswitchtoml/.tfswitch.toml b/test-data/integration-tests/test_tfswitchtoml/.tfswitch.toml similarity index 100% rename from test-data/test_tfswitchtoml/.tfswitch.toml rename to test-data/integration-tests/test_tfswitchtoml/.tfswitch.toml diff --git a/test-data/test_versiontf/version.tf b/test-data/integration-tests/test_versiontf/version.tf similarity index 100% rename from test-data/test_versiontf/version.tf rename to test-data/integration-tests/test_versiontf/version.tf diff --git a/test-data/test_no_file/dummy_file b/test-data/skip-integration-tests/test_no_file/dummy_file similarity index 100% rename from test-data/test_no_file/dummy_file rename to test-data/skip-integration-tests/test_no_file/dummy_file diff --git a/test-data/test_terragrunt_error_hcl/terragrunt.hcl b/test-data/skip-integration-tests/test_terragrunt_error_hcl/terragrunt.hcl similarity index 100% rename from test-data/test_terragrunt_error_hcl/terragrunt.hcl rename to test-data/skip-integration-tests/test_terragrunt_error_hcl/terragrunt.hcl diff --git a/test-data/test_tfswitchtoml_error/.tfswitch.toml b/test-data/skip-integration-tests/test_tfswitchtoml_error/.tfswitch.toml similarity index 100% rename from test-data/test_tfswitchtoml_error/.tfswitch.toml rename to test-data/skip-integration-tests/test_tfswitchtoml_error/.tfswitch.toml diff --git a/test-data/test_versiontf_error/version.tf b/test-data/skip-integration-tests/test_versiontf_error/version.tf similarity index 100% rename from test-data/test_versiontf_error/version.tf rename to test-data/skip-integration-tests/test_versiontf_error/version.tf diff --git a/test-data/test_versiontf_non_existent/version.tf b/test-data/skip-integration-tests/test_versiontf_non_existent/version.tf similarity index 100% rename from test-data/test_versiontf_non_existent/version.tf rename to test-data/skip-integration-tests/test_versiontf_non_existent/version.tf From d039a6789dbe156729a322eff27459dcf56c49bc Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 10:56:16 +0200 Subject: [PATCH 42/49] - added integration tests for windows --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0cf242d5..afdeaf4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,3 +90,10 @@ jobs: - name: Running unit tests run: | go test -v ./... + + - name: Running integration tests + run: | + mkdir build + mkdir bin + go build -v -o build/tfswitch + for /D %%s in (.\integration-tests\*) do ( .\build\tfswitch -c "%%s" -b .\bin\terraform ) From 30710fca0452297c382e72ca134413406930e2ca Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Tue, 16 Apr 2024 11:10:55 +0200 Subject: [PATCH 43/49] Revert "- added integration tests for windows" This reverts commit 32dc75cd0592339f15ed187c89d9a89f8b4514b4. --- .github/workflows/build.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index afdeaf4f..0cf242d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,10 +90,3 @@ jobs: - name: Running unit tests run: | go test -v ./... - - - name: Running integration tests - run: | - mkdir build - mkdir bin - go build -v -o build/tfswitch - for /D %%s in (.\integration-tests\*) do ( .\build\tfswitch -c "%%s" -b .\bin\terraform ) From 12ef46d14d85c6055c28a77811fb2bb47b032182 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 19 Apr 2024 09:20:41 +0200 Subject: [PATCH 44/49] - use filepath.Join instead of concatenating strings --- lib/param_parsing/terraform_version.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/param_parsing/terraform_version.go b/lib/param_parsing/terraform_version.go index dda3737c..eed498ef 100644 --- a/lib/param_parsing/terraform_version.go +++ b/lib/param_parsing/terraform_version.go @@ -3,13 +3,14 @@ package param_parsing import ( "github.com/warrensbox/terraform-switcher/lib" "os" + "path/filepath" "strings" ) const terraformVersionFileName = ".terraform-version" func GetParamsFromTerraformVersion(params Params) (Params, error) { - filePath := params.ChDirPath + "/" + terraformVersionFileName + filePath := filepath.Join(params.ChDirPath, terraformVersionFileName) if lib.CheckFileExist(filePath) { logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) @@ -23,6 +24,6 @@ func GetParamsFromTerraformVersion(params Params) (Params, error) { } func terraformVersionFileExists(params Params) bool { - filePath := params.ChDirPath + "/" + terraformVersionFileName + filePath := filepath.Join(params.ChDirPath, terraformVersionFileName) return lib.CheckFileExist(filePath) } From 34e13d891060f8bf56c8d96b6fcf4eb3a28e3ac2 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 19 Apr 2024 09:29:04 +0200 Subject: [PATCH 45/49] - use filepath.Join instead of concatenating strings --- lib/param_parsing/terragrunt.go | 5 +++-- lib/param_parsing/tfswitch.go | 5 +++-- lib/param_parsing/toml.go | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index 9273e08d..db716d71 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/hclparse" "github.com/warrensbox/terraform-switcher/lib" + "path/filepath" ) const terraGruntFileName = "terragrunt.hcl" @@ -14,7 +15,7 @@ type terragruntVersionConstraints struct { } func GetVersionFromTerragrunt(params Params) (Params, error) { - filePath := params.ChDirPath + "/" + terraGruntFileName + filePath := filepath.Join(params.ChDirPath, terraGruntFileName) if lib.CheckFileExist(filePath) { logger.Infof("Reading configuration from %q", filePath) parser := hclparse.NewParser() @@ -38,6 +39,6 @@ func GetVersionFromTerragrunt(params Params) (Params, error) { } func terraGruntFileExists(params Params) bool { - filePath := params.ChDirPath + "/" + terraGruntFileName + filePath := filepath.Join(params.ChDirPath, terraGruntFileName) return lib.CheckFileExist(filePath) } diff --git a/lib/param_parsing/tfswitch.go b/lib/param_parsing/tfswitch.go index 580eb658..89e78a24 100644 --- a/lib/param_parsing/tfswitch.go +++ b/lib/param_parsing/tfswitch.go @@ -3,13 +3,14 @@ package param_parsing import ( "github.com/warrensbox/terraform-switcher/lib" "os" + "path/filepath" "strings" ) const tfSwitchFileName = ".tfswitchrc" func GetParamsFromTfSwitch(params Params) (Params, error) { - filePath := params.ChDirPath + "/" + tfSwitchFileName + filePath := filepath.Join(params.ChDirPath, tfSwitchFileName) if lib.CheckFileExist(filePath) { logger.Infof("Reading configuration from %q", filePath) content, err := os.ReadFile(filePath) @@ -23,6 +24,6 @@ func GetParamsFromTfSwitch(params Params) (Params, error) { } func tfSwitchFileExists(params Params) bool { - filePath := params.ChDirPath + "/" + tfSwitchFileName + filePath := filepath.Join(params.ChDirPath, tfSwitchFileName) return lib.CheckFileExist(filePath) } diff --git a/lib/param_parsing/toml.go b/lib/param_parsing/toml.go index ae06c9f0..e1748c73 100644 --- a/lib/param_parsing/toml.go +++ b/lib/param_parsing/toml.go @@ -3,13 +3,14 @@ package param_parsing import ( "github.com/spf13/viper" "github.com/warrensbox/terraform-switcher/lib" + "path/filepath" ) const tfSwitchTOMLFileName = ".tfswitch.toml" // getParamsTOML parses everything in the toml file, return required version and bin path func getParamsTOML(params Params) (Params, error) { - tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName + tomlPath := filepath.Join(params.ChDirPath, tfSwitchTOMLFileName) if tomlFileExists(params) { logger.Infof("Reading configuration from %q", tomlPath) configfileName := lib.GetFileName(tfSwitchTOMLFileName) @@ -38,6 +39,6 @@ func getParamsTOML(params Params) (Params, error) { } func tomlFileExists(params Params) bool { - tomlPath := params.ChDirPath + "/" + tfSwitchTOMLFileName + tomlPath := filepath.Join(params.ChDirPath, tfSwitchTOMLFileName) return lib.CheckFileExist(tomlPath) } From 48b744bf506f5378ca6b13abd5e23361b95e523e Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 19 Apr 2024 09:39:24 +0200 Subject: [PATCH 46/49] - use filepath.Join instead of concatenating strings --- lib/param_parsing/terragrunt_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/param_parsing/terragrunt_test.go b/lib/param_parsing/terragrunt_test.go index 46796d3f..118baaf8 100644 --- a/lib/param_parsing/terragrunt_test.go +++ b/lib/param_parsing/terragrunt_test.go @@ -3,6 +3,7 @@ package param_parsing import ( "github.com/hashicorp/go-version" "github.com/warrensbox/terraform-switcher/lib" + "strings" "testing" ) @@ -39,9 +40,9 @@ func TestGetVersionFromTerragrunt_erroneous_file(t *testing.T) { if err == nil { t.Error("Expected error but got none.") } else { - expectedError := "could not decode body of HCL file \"../../test-data/skip-integration-tests/test_terragrunt_error_hcl/terragrunt.hcl\"" - if err.Error() != expectedError { - t.Errorf("Expected error to be '%q', got '%q'", expectedError, err) + expectedError := "could not decode body of HCL file" + if !strings.Contains(err.Error(), expectedError) { + t.Errorf("Expected error to contain '%q', got '%q'", expectedError, err) } } } From 7d4d411d60e64f7b9be528a86bdb1d0760371b93 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Fri, 19 Apr 2024 10:34:59 +0200 Subject: [PATCH 47/49] - replaced if else with switch statement --- lib/logging.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/logging.go b/lib/logging.go index f3827b89..d09796ee 100644 --- a/lib/logging.go +++ b/lib/logging.go @@ -8,7 +8,13 @@ import ( const loggingTemplate = "{{datetime}} {{level}} [{{caller}}] {{message}} {{data}} {{extra}}\n" -var logger *slog.Logger +var ( + logger *slog.Logger + NormalLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel} + NoticeLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel} + DebugLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel} + TraceLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel, slog.TraceLevel} +) func InitLogger(logLevel string) *slog.Logger { formatter := slog.NewTextFormatter() @@ -18,13 +24,17 @@ func InitLogger(logLevel string) *slog.Logger { formatter.SetTemplate(loggingTemplate) var h *handler.ConsoleHandler - if logLevel == "TRACE" { + switch logLevel { + case "TRACE": h = handler.NewConsoleHandler(TraceLogging) - } else if logLevel == "DEBUG" { + break + case "DEBUG": h = handler.NewConsoleHandler(DebugLogging) - } else if logLevel == "NOTICE" { + break + case "NOTICE": h = handler.NewConsoleHandler(NoticeLogging) - } else { + break + default: h = handler.NewConsoleHandler(NormalLogging) } @@ -34,10 +44,3 @@ func InitLogger(logLevel string) *slog.Logger { logger = newLogger return newLogger } - -var ( - NormalLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel} - NoticeLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel} - DebugLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel} - TraceLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel, slog.TraceLevel} -) From a08c5eeb4bab8d03a3d4b97bcb8dcc5560cbb521 Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Sun, 21 Apr 2024 10:16:16 +0200 Subject: [PATCH 48/49] - remove commented lines --- lib/install.go | 1 - lib/param_parsing/terragrunt.go | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/install.go b/lib/install.go index 6d5ecd18..e23098b7 100644 --- a/lib/install.go +++ b/lib/install.go @@ -299,7 +299,6 @@ func InstallLatestImplicitVersion(requestedVersion, customBinaryPath, mirrorURL if err != nil { logger.Errorf("Error parsing constraint %q: %v", requestedVersion, err) } - //if lib.ValidMinorVersionFormat(requestedVersion) { tfversion, err := getTFLatestImplicit(mirrorURL, preRelease, requestedVersion) if err == nil && tfversion != "" { install(tfversion, customBinaryPath, mirrorURL) diff --git a/lib/param_parsing/terragrunt.go b/lib/param_parsing/terragrunt.go index db716d71..ff50c9fe 100644 --- a/lib/param_parsing/terragrunt.go +++ b/lib/param_parsing/terragrunt.go @@ -22,7 +22,6 @@ func GetVersionFromTerragrunt(params Params) (Params, error) { hclFile, diagnostics := parser.ParseHCLFile(filePath) if diagnostics.HasErrors() { return params, fmt.Errorf("unable to parse HCL file %q", filePath) - //logger.Fatalf("Unable to parse HCL file %q", filePath) } var versionFromTerragrunt terragruntVersionConstraints diagnostics = gohcl.DecodeBody(hclFile.Body, nil, &versionFromTerragrunt) From a3168858f011555a56773fafccccd1b528122f4a Mon Sep 17 00:00:00 2001 From: Johannes Brunswicker Date: Sun, 21 Apr 2024 10:18:28 +0200 Subject: [PATCH 49/49] - show caller only if not info logging level --- lib/logging.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/logging.go b/lib/logging.go index d09796ee..cc7466a0 100644 --- a/lib/logging.go +++ b/lib/logging.go @@ -6,14 +6,14 @@ import ( "os" ) -const loggingTemplate = "{{datetime}} {{level}} [{{caller}}] {{message}} {{data}} {{extra}}\n" - var ( - logger *slog.Logger - NormalLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel} - NoticeLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel} - DebugLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel} - TraceLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel, slog.TraceLevel} + loggingTemplateDebug = "{{datetime}} {{level}} [{{caller}}] {{message}} {{data}} {{extra}}\n" + loggingTemplate = "{{datetime}} {{level}} {{message}} {{data}} {{extra}}\n" + logger *slog.Logger + NormalLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel} + NoticeLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel} + DebugLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel} + TraceLogging = slog.Levels{slog.PanicLevel, slog.FatalLevel, slog.ErrorLevel, slog.WarnLevel, slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel, slog.TraceLevel} ) func InitLogger(logLevel string) *slog.Logger { @@ -21,21 +21,24 @@ func InitLogger(logLevel string) *slog.Logger { formatter.EnableColor = true formatter.ColorTheme = slog.ColorTheme formatter.TimeFormat = "15:04:05.000" - formatter.SetTemplate(loggingTemplate) var h *handler.ConsoleHandler switch logLevel { case "TRACE": h = handler.NewConsoleHandler(TraceLogging) + formatter.SetTemplate(loggingTemplateDebug) break case "DEBUG": h = handler.NewConsoleHandler(DebugLogging) + formatter.SetTemplate(loggingTemplateDebug) break case "NOTICE": h = handler.NewConsoleHandler(NoticeLogging) + formatter.SetTemplate(loggingTemplateDebug) break default: h = handler.NewConsoleHandler(NormalLogging) + formatter.SetTemplate(loggingTemplate) } h.SetFormatter(formatter)