-
Notifications
You must be signed in to change notification settings - Fork 137
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- extract params into own struct for better usability
- extracted all parameter parsing into an explicit package and ensured the precedence
- Loading branch information
1 parent
6aaa2c4
commit 8c98f49
Showing
27 changed files
with
522 additions
and
389 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package param_parsing | ||
|
||
import "os" | ||
|
||
func GetParamsFromEnvironment(params Params) Params { | ||
params.Version = os.Getenv("TF_VERSION") | ||
return params | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
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 | ||
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) | ||
|
||
// Parse the command line only parameters | ||
getopt.Parse() | ||
|
||
// Read configuration files in increasing precedence (least precedence first) | ||
params = GetParamsFromEnvironment(params) | ||
params = GetVersionFromTerragrunt(params) | ||
params = GetVersionFromVersionsTF(params) | ||
params = GetParamsFromTerraformVersion(params) | ||
params = GetParamsFromTfSwitch(params) | ||
params = GetParamsTOML(params) | ||
getCommandlineParams(params) | ||
|
||
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.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") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
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_check_config_precedence(t *testing.T) { | ||
t.Cleanup(func() { | ||
getopt.CommandLine = getopt.New() | ||
}) | ||
os.Args = []string{"cmd", "--chdir=../../test-data/test_precedence"} | ||
parameters := GetParameters() | ||
expected := "0.11.3_toml" | ||
if parameters.Version != expected { | ||
t.Error("Version Param was not as expected. Actual: " + parameters.Version + ", Expected: " + expected) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package param_parsing | ||
|
||
import ( | ||
"fmt" | ||
"github.com/warrensbox/terraform-switcher/lib" | ||
"log" | ||
"os" | ||
"strings" | ||
) | ||
|
||
func GetParamsFromTerraformVersion(params Params) Params { | ||
defaults := lib.GetDefaults() | ||
filePath := params.ChDirPath + "/" + defaults.TFVFilename | ||
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.TrimSuffix(string(content), "\n") | ||
} | ||
return params | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package param_parsing | ||
|
||
import ( | ||
"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 { | ||
t.Error("Version from .terraform-version not read correctly. Actual: " + params.Version + ", Expected: " + expected) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package param_parsing | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/hcl2/gohcl" | ||
"github.com/hashicorp/hcl2/hclparse" | ||
"github.com/warrensbox/terraform-switcher/lib" | ||
"log" | ||
) | ||
|
||
type terragruntVersionConstraints struct { | ||
TerraformVersionConstraint string `hcl:"terraform_version_constraint"` | ||
} | ||
|
||
func GetVersionFromTerragrunt(params Params) Params { | ||
defaults := lib.GetDefaults() | ||
filePath := params.ChDirPath + "/" + defaults.TgHclFilename | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package param_parsing | ||
|
||
import ( | ||
"fmt" | ||
"github.com/warrensbox/terraform-switcher/lib" | ||
"log" | ||
"os" | ||
"strings" | ||
) | ||
|
||
func GetParamsFromTfSwitch(params Params) Params { | ||
defaults := lib.GetDefaults() | ||
filePath := params.ChDirPath + "/" + defaults.RcFilename | ||
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.TrimSuffix(string(content), "\n") | ||
} | ||
return params | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package param_parsing | ||
|
||
import ( | ||
"fmt" | ||
"github.com/spf13/viper" | ||
"github.com/warrensbox/terraform-switcher/lib" | ||
"log" | ||
) | ||
|
||
// GetParamsTOML parses everything in the toml file, return required version and bin path | ||
func GetParamsTOML(params Params) Params { | ||
defaults := lib.GetDefaults() | ||
tomlPath := params.ChDirPath + "/" + defaults.TomlFilename | ||
if lib.CheckFileExist(tomlPath) { | ||
fmt.Printf("Reading configuration from %s\n", tomlPath) | ||
configfileName := lib.GetFileName(defaults.TomlFilename) | ||
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 | ||
} |
Oops, something went wrong.