From 98493c8d52c8f7a16676d5c42e67fb442c7d04da Mon Sep 17 00:00:00 2001 From: mitch Date: Wed, 15 Jun 2022 22:52:19 -0400 Subject: [PATCH] Added support for default terraform version Added default behavior for > and >= to not use non-stable release versions Added configuration option of `StableOnly` which defaults to true. Setting this to false will permit the use of -alpha and -beta releases --- README.md | 7 ++++++- SemVersion.go | 11 ++++++++-- cmd/main.go | 9 ++++++++- configManagement.go | 25 +++++++++++++++++++++++ configManagement_test.go | 41 +++++++++++++++++++------------------- fileHandler.go | 6 +++++- fileHandler_test.go | 30 ++++++++++++++++++++++------ versionedTerraform.go | 12 +++++++---- versionedTerraform_test.go | 1 + 9 files changed, 107 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 97d2d03..43086d2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,12 @@ download, and execute that version All arguments are passed through to terraform ``` -## sample usage +## Sample usage `versionedTerraform version` will display the terraform version executed in a folder +## Configuration +A configuration file is created in `~/.versionedTerraform`

+ +`StableOnly` boolean values: true/false
+This value is used to restrict terraform to release versions only defaults to true ## Known Issues diff --git a/SemVersion.go b/SemVersion.go index b322872..6ae8a9d 100644 --- a/SemVersion.go +++ b/SemVersion.go @@ -16,6 +16,7 @@ const ( type SemVersion struct { version string + isStable bool majorVersion int minorVersion int patchVersion int @@ -29,6 +30,7 @@ type SemVersionInterface interface { func NewSemVersion(v string) *SemVersion { s := new(SemVersion) + s.isStable = true s.version = removeSpacesVersion(v) s.setMajorVersion() @@ -52,13 +54,18 @@ func (s *SemVersion) setMinorVersion() { func (s *SemVersion) setPatchVersion() { version := s.version + var err error patchStringSlice := strings.Split(version, ".") if len(patchStringSlice) < 3 { s.patchVersion = 0 return } - s.patchVersion, _ = strconv.Atoi(patchStringSlice[2]) - + s.patchVersion, err = strconv.Atoi(patchStringSlice[2]) + if err != nil { + s.isStable = false + patchStringSlice = strings.Split(patchStringSlice[2], "-") + s.patchVersion, _ = strconv.Atoi(patchStringSlice[0]) + } } func (s *SemVersion) ToString() string { diff --git a/cmd/main.go b/cmd/main.go index 90f5912..c5a739f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -15,6 +15,8 @@ const ( terraformPrefix = "/terraform_" ) +var needsStable = true + func main() { homeDir, _ := os.UserHomeDir() configDirString := homeDir + shortConfigDirString @@ -69,7 +71,12 @@ func main() { vSlice = append(vSlice, v.ToString()) } - ver, err := versionedTerraform.GetVersionFromFile(workingDir, vSlice) + needsStable, err = versionedTerraform.ConfigRequiresStable(configDir, configFileLocation) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to open config file, defaulting to stable versions of terraform only") + } + + ver, err := versionedTerraform.GetVersionFromFile(workingDir, vSlice, needsStable) if err != nil { fmt.Printf("Unable to retrieve terraform version from files: %v", err) } diff --git a/configManagement.go b/configManagement.go index 06431fe..4886235 100644 --- a/configManagement.go +++ b/configManagement.go @@ -12,10 +12,33 @@ import ( ) type configStruct struct { + StableOnly bool LastUpdate int64 AvailableVersions []string } +func ConfigRequiresStable(fileSystem fs.FS, configFile string) (bool, error) { + fileHandle, err := fileSystem.Open(configFile) + if err != nil { + return true, err + } + defer fileHandle.Close() + + fileScanner := bufio.NewScanner(fileHandle) + fileScanner.Split(bufio.ScanLines) + + for fileScanner.Scan() { + _line := fileScanner.Text() + if strings.Contains(_line, "StableOnly: ") { + isStable := strings.SplitAfter(_line, "StableOnly: ")[1] + if strings.EqualFold(isStable, "false") { + return false, nil + } + } + } + return true, nil +} + func NeedToUpdateAvailableVersions(fileSystem fs.FS, availableVersions string) (bool, error) { //todo this is used a lot abstract it? fileHandle, err := fileSystem.Open(availableVersions) @@ -120,6 +143,8 @@ func CreateConfig(directory string, configFile string) error { fileHandler, err := os.Create(configFileName) defer fileHandler.Close() + lineToByte := []byte(fmt.Sprintf("StableOnly: true\n")) + fileHandler.Write(lineToByte) err = UpdateConfig(*fileHandler) return err } diff --git a/configManagement_test.go b/configManagement_test.go index ba1eaf1..e97dca2 100644 --- a/configManagement_test.go +++ b/configManagement_test.go @@ -79,26 +79,27 @@ func TestInstalledVersions(t *testing.T) { } fs := fstest.MapFS{ - "terraform_0.12.31": {Data: []byte("")}, - "terraform_0.12.30": {Data: []byte("")}, - "terraform_0.11.10": {Data: []byte("")}, - "terraform_0.11.15": {Data: []byte("")}, - "terraform_1.0.1": {Data: []byte("")}, - "terraform_1.0.12": {Data: []byte("")}, - "terraform_1.1.1": {Data: []byte("")}, - "terraform_1.1.2": {Data: []byte("")}, - "terraform_1.1.3": {Data: []byte("")}, - "terraform_1.1.4": {Data: []byte("")}, - "terraform_1.1.5": {Data: []byte("")}, - "terraform_1.1.6": {Data: []byte("")}, - "terraform_1.1.7": {Data: []byte("")}, - "terraform_1.1.8": {Data: []byte("")}, - "terraform_1.1.9": {Data: []byte("")}, - "terraform_1.1.10": {Data: []byte("")}, - "terraform_1.1.11": {Data: []byte("")}, - "terraform_0.14.0": {Data: []byte("")}, - "terraform_0.13.1": {Data: []byte("")}, - "terraform_0.13.0": {Data: []byte("")}, + "terraform_0.12.31": {Data: []byte("")}, + "terraform_0.12.30": {Data: []byte("")}, + "terraform_0.11.10": {Data: []byte("")}, + "terraform_0.11.15": {Data: []byte("")}, + "terraform_1.0.1": {Data: []byte("")}, + "terraform_1.0.12": {Data: []byte("")}, + "terraform_1.2.23-alpha": {Data: []byte("")}, + "terraform_1.1.1": {Data: []byte("")}, + "terraform_1.1.2": {Data: []byte("")}, + "terraform_1.1.3": {Data: []byte("")}, + "terraform_1.1.4": {Data: []byte("")}, + "terraform_1.1.5": {Data: []byte("")}, + "terraform_1.1.6": {Data: []byte("")}, + "terraform_1.1.7": {Data: []byte("")}, + "terraform_1.1.8": {Data: []byte("")}, + "terraform_1.1.9": {Data: []byte("")}, + "terraform_1.1.10": {Data: []byte("")}, + "terraform_1.1.11": {Data: []byte("")}, + "terraform_0.14.0": {Data: []byte("")}, + "terraform_0.13.1": {Data: []byte("")}, + "terraform_0.13.0": {Data: []byte("")}, } t.Run("Test installed versions", func(t *testing.T) { diff --git a/fileHandler.go b/fileHandler.go index e60ef6a..4b68bf0 100644 --- a/fileHandler.go +++ b/fileHandler.go @@ -7,9 +7,13 @@ import ( "strings" ) +var needsStable bool + //todo this should be (Version) GetVers... -func GetVersionFromFile(fileSystem fs.FS, versionList []string) (*Version, error) { +func GetVersionFromFile(fileSystem fs.FS, versionList []string, needsStableValue bool) (*Version, error) { + needsStable = needsStableValue var versionFinal Version + versionFinal = *NewVersion(">= 0.0.0", versionList) dir, err := fs.ReadDir(fileSystem, ".") if err != nil { return &versionFinal, err diff --git a/fileHandler_test.go b/fileHandler_test.go index 6319890..5b1f32a 100644 --- a/fileHandler_test.go +++ b/fileHandler_test.go @@ -5,9 +5,8 @@ import ( "testing/fstest" ) -func TestFileHandler(t *testing.T) { - const ( - firstFile = ` +const ( + firstFile = ` resource "aws_mq_broker" "sample" { depends_on = [aws_security_group.mq] broker_name = var.name @@ -21,13 +20,14 @@ resource "aws_mq_broker" "sample" { subnet_ids = ["10.0.0.0/24", "10.0.1.0/24"] } ` - secondFile = ` + secondFile = ` terraform { required_version = "~> 0.12.4" } ` - ) +) +func TestFileHandler(t *testing.T) { want := NewVersion("0.12.31", testVersionList()) fs := fstest.MapFS{ @@ -35,7 +35,25 @@ terraform { "versions.tf": {Data: []byte(secondFile)}, } - version, err := GetVersionFromFile(fs, testVersionList()) + version, err := GetVersionFromFile(fs, testVersionList(), true) + + if err != nil { + t.Fatal(err) + } + + got := *version + + if got.Version != want.Version { + t.Errorf("Expected %v, got %v", want.Version, got.Version) + } +} + +func TestEmptyTerraformVersion(t *testing.T) { + want := NewVersion("1.1.11", testVersionList()) + + fs := fstest.MapFS{"main.tf": {Data: []byte(firstFile)}} + + version, err := GetVersionFromFile(fs, testVersionList(), true) if err != nil { t.Fatal(err) diff --git a/versionedTerraform.go b/versionedTerraform.go index 56075f9..5f7e60d 100644 --- a/versionedTerraform.go +++ b/versionedTerraform.go @@ -40,7 +40,8 @@ func (v *Version) getLatestMajorRelease() { for _, release := range v.availableVersions { if release.majorVersion == v.Version.majorVersion && release.minorVersion == v.Version.minorVersion && - release.patchVersion >= v.Version.patchVersion { + release.patchVersion >= v.Version.patchVersion && + (v.Version.isStable || !needsStable) { v.Version = release } } @@ -73,16 +74,19 @@ func (v *Version) getOneLessRelease() { func (v *Version) getLatestRelease() { //todo clean up for _, release := range v.availableVersions { - if release.majorVersion > v.Version.majorVersion { + if release.majorVersion > v.Version.majorVersion && + (release.isStable || !needsStable) { v.Version = release } if release.majorVersion >= v.Version.majorVersion && - release.minorVersion > v.Version.minorVersion { + release.minorVersion > v.Version.minorVersion && + (release.isStable || !needsStable) { v.Version = release } if release.majorVersion >= v.Version.majorVersion && release.minorVersion >= v.Version.minorVersion && - release.patchVersion >= v.Version.patchVersion { + release.patchVersion >= v.Version.patchVersion && + (release.isStable || !needsStable) { v.Version = release } } diff --git a/versionedTerraform_test.go b/versionedTerraform_test.go index 53321f4..cb1003b 100644 --- a/versionedTerraform_test.go +++ b/versionedTerraform_test.go @@ -6,6 +6,7 @@ import ( func testVersionList() []string { return []string{ + "1.2.23-alpha", "1.1.11", "1.1.10", "1.1.9",