commit 8b24af46e190eed2df5a375c306bb64887ff99c0 Author: mitch Date: Wed Feb 23 13:15:12 2022 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c16ff9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,82 @@ +# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig + +# Created by https://www.gitignore.io/api/macos,visualstudiocode,terraform,windows +# Edit at https://www.gitignore.io/?templates=macos,visualstudiocode,terraform,windows + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Crash log files +crash.log + +# Include override files you do wish to add to version control using negated pattern +# +# !example_override.tf + +### VisualStudioCode ### +.vscode/* +#!.vscode/settings.json +#!.vscode/tasks.json +#!.vscode/launch.json +#!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.gitignore.io/api/macos,visualstudiocode,terraform,windows + +# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) +.vscode/* + +.idea \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..277290d --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +#################################################### +# Build +#################################################### +build: + go build -o versionedTerraform ./cmd +#################################################### +# Clean +#################################################### +clean: + rm -f ~/.local/bin/versionedTerraform +#################################################### +# Install +#################################################### +install: + mv versionedTerraform ~/.local/bin/ +#################################################### +# help feature +#################################################### +help: + @echo '' + @echo 'Usage: make [TARGET]' + @echo 'Targets:' + @echo ' build go build -o versionedTerraform ./cmd' + @echo ' clean removes installed versionedTerraform file' + @echo ' install installs versionedTerraform to local user bin folder' + @echo ' all Nothing to do.' + @echo '' \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b8e048 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +#Versioned Terraform +A wrapper for terraform to detect the expected version of terraform, +download, and execute that version + +## Requirements +- go compiler (only tested on go1.17) + +## Install +`make build install` for installation to local user
+`make build` will create an executable file for you to place where you'd like + +## Commands +``` +All arguments are passed through to terraform +``` + +## sample usage +`versionedTerraform version` will display the terraform version executed in a folder + +## Known Issues +Currently, does not support semantic versioning between values
+i.e. `required_version = "~> 0.14", "< 0.14.3"` diff --git a/SemVersion.go b/SemVersion.go new file mode 100644 index 0000000..fd84e49 --- /dev/null +++ b/SemVersion.go @@ -0,0 +1,73 @@ +package versionedTerraform + +import ( + "strconv" + "strings" +) + +const ( + //todo include others if needed + //todo add comparison i.e. >= 0.11.10, < 0.12.0 + latestRelease = ">=" + latestPatch = "~>" +) + +type SemVersion struct { + version string + majorVersion int + minorVersion int + patchVersion int +} + +type SemVersionInterface interface { + setMajorVersion() + setMinorVersion() + setPatchVersion() +} + +func NewSemVersion(v string) *SemVersion { + s := new(SemVersion) + s.version = removeSpacesVersion(v) + + s.setMajorVersion() + s.setMinorVersion() + s.setPatchVersion() + return s +} + +func (s *SemVersion) setMajorVersion() { + version := s.version + majorVersionString := strings.Split(version, ".")[0] + s.majorVersion, _ = strconv.Atoi(majorVersionString) +} + +func (s *SemVersion) setMinorVersion() { + version := s.version + minorVersionString := strings.Split(version, ".")[1] + s.minorVersion, _ = strconv.Atoi(minorVersionString) + +} + +func (s *SemVersion) setPatchVersion() { + version := s.version + patchStringSlice := strings.Split(version, ".") + if len(patchStringSlice) < 3 { + s.patchVersion = 0 + return + } + s.patchVersion, _ = strconv.Atoi(patchStringSlice[2]) + +} + +func (s *SemVersion) ToString() string { + return s.version +} + +func (s *SemVersion) VersionInSlice(sSem []SemVersion) bool { + for _, ver := range sSem { + if ver.ToString() == s.ToString() { + return true + } + } + return false +} diff --git a/cmd/examples/example.tf b/cmd/examples/example.tf new file mode 100644 index 0000000..c76d874 --- /dev/null +++ b/cmd/examples/example.tf @@ -0,0 +1,7 @@ +terraform { + required_version = "~> 0.14" +} + +output "hello" { + value = "world" +} \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..9300ac1 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,76 @@ +package main + +import ( + "flag" + "fmt" + "os" + "os/exec" + "versionedTerraform" +) + +const ( + configFileLocation = "config" + shortConfigDirString = "/.versionedTerraform" + pwd = "." + terraformPrefix = "/terraform_" +) + +func main() { + homeDir, _ := os.UserHomeDir() + configDirString := homeDir + shortConfigDirString + configDir := os.DirFS(configDirString) + workingDir := os.DirFS(pwd) + var versionsFromConfig []versionedTerraform.SemVersion + + flag.Parse() + args := flag.Args() + + needsUpdate, err := versionedTerraform.NeedToUpdateAvailableVersions(configDir, configFileLocation) + if needsUpdate { + fileHandle, _ := os.OpenFile(configDirString+"/"+configFileLocation, os.O_RDWR, 0666) + defer fileHandle.Close() + versionedTerraform.UpdateConfig(*fileHandle) + } + versionsFromConfig, err = versionedTerraform.LoadVersionsFromConfig(configDir, configFileLocation) + if err != nil { + fmt.Printf("Unable to read config: %v", err) + os.Exit(1) + } + + installedVersions, err := versionedTerraform.LoadInstalledVersions(configDir) + if err != nil { + fmt.Printf("Unable to verify installed verisons: %v", err) + os.Exit(1) + } + + var vSlice []string + for _, v := range versionsFromConfig { + vSlice = append(vSlice, v.ToString()) + } + + ver, err := versionedTerraform.GetVersionFromFile(workingDir, vSlice) + if err != nil { + fmt.Printf("Unable to retrieve terraform version from files: %v", err) + } + + if !ver.Version.VersionInSlice(installedVersions) { + fmt.Printf("Installing terraform version %s\n\n", ver.Version.ToString()) + err = ver.InstallTerraformVersion() + if err != nil { + fmt.Printf("Unable to install terraform version: %v", err) + } + } + + terraformFile := configDirString + terraformPrefix + ver.VersionToString() + argsForTerraform := append([]string{""}, args...) + cmd := exec.Cmd{ + Path: terraformFile, + Args: argsForTerraform, + Env: os.Environ(), + Dir: pwd, + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, + } + cmd.Run() +} diff --git a/configManagement.go b/configManagement.go new file mode 100644 index 0000000..5650937 --- /dev/null +++ b/configManagement.go @@ -0,0 +1,111 @@ +package versionedTerraform + +import ( + "bufio" + "fmt" + "io/fs" + "os" + "regexp" + "strconv" + "strings" + "time" +) + +type configStruct struct { + LastUpdate int64 + AvailableVersions []string +} + +func NeedToUpdateAvailableVersions(fileSystem fs.FS, availableVersions string) (bool, error) { + //todo this is used a lot abstract it? + fileHandle, err := fileSystem.Open(availableVersions) + oneDayAgo := time.Now().AddDate(0, 0, -1).Unix() + if err != nil { + return false, err + } + defer fileHandle.Close() + + fileScanner := bufio.NewScanner(fileHandle) + fileScanner.Split(bufio.ScanLines) + + for fileScanner.Scan() { + _line := fileScanner.Text() + if strings.Contains(_line, "LastUpdate: ") { + lastUpdateTimeString := strings.SplitAfter(_line, "LastUpdate: ")[1] + lastUpdateTimeString = strings.TrimSpace(lastUpdateTimeString) + lastUpdateTime, err := strconv.ParseInt(lastUpdateTimeString, 10, 64) + if err != nil { + return false, err + } + if lastUpdateTime <= oneDayAgo { + return true, nil + } + } + } + return false, nil +} + +func LoadVersionsFromConfig(fileSystem fs.FS, configFile string) ([]SemVersion, error) { + fileHandle, err := fileSystem.Open(configFile) + removeOpenBracket := regexp.MustCompile("\\[") + removeCloseBracket := regexp.MustCompile("]") + if err != nil { + return nil, err + } + defer fileHandle.Close() + + fileScanner := bufio.NewScanner(fileHandle) + fileScanner.Split(bufio.ScanLines) + + for fileScanner.Scan() { + _line := fileScanner.Text() + if strings.Contains(_line, "AvailableVersions: ") { + var versionList []SemVersion + _line = strings.SplitAfter(_line, "AvailableVersions: ")[1] + _line = removeOpenBracket.ReplaceAllString(_line, "") + _line = removeCloseBracket.ReplaceAllString(_line, "") + versions := strings.Split(_line, " ") + for _, version := range versions { + versionList = append(versionList, *NewSemVersion(version)) + } + return versionList, nil + } + } + return nil, nil +} + +func LoadInstalledVersions(fileSystem fs.FS) ([]SemVersion, error) { + dir, err := fs.ReadDir(fileSystem, ".") + var installedTerraformVersions []SemVersion + terraformRegex := regexp.MustCompile(terraformPrefix) + if err != nil { + return nil, err + } + + for _, f := range dir { + terraformFileName := f.Name() + if strings.Contains(terraformFileName, terraformPrefix) { + terraformVersionString := terraformRegex.ReplaceAllString(terraformFileName, "") + installedTerraformVersions = append(installedTerraformVersions, *NewSemVersion(terraformVersionString)) + } + } + return installedTerraformVersions, nil +} + +func UpdateConfig(File os.File) error { + configValues := new(configStruct) + + configValues.AvailableVersions, _ = GetVersionList() + + timeNow := time.Now() + configValues.LastUpdate = timeNow.Unix() + + File.Truncate(0) + File.Seek(0, 0) + + lineToByte := []byte(fmt.Sprintf("LastUpdate: %d\n", configValues.LastUpdate)) + File.Write(lineToByte) + lineToByte = []byte(fmt.Sprintf("AvailableVersions: %+v\n", configValues.AvailableVersions)) + File.Write(lineToByte) + return nil +} diff --git a/configManagement_test.go b/configManagement_test.go new file mode 100644 index 0000000..a9dbc28 --- /dev/null +++ b/configManagement_test.go @@ -0,0 +1,112 @@ +package versionedTerraform + +import ( + "fmt" + "reflect" + "sort" + "testing" + "testing/fstest" + "time" +) + +func TestUpdateAvailableVersions(t *testing.T) { + timeNow := time.Now() + currentTime := timeNow.Unix() + twoDaysAgoTime := timeNow.AddDate(0, 0, -2).Unix() + + successUpdate := fmt.Sprintf("LastUpdate: %d", currentTime) + needsUpdate := fmt.Sprintf("LastUpdate: %d", twoDaysAgoTime) + + fs := fstest.MapFS{ + "successConfig.conf": {Data: []byte(successUpdate)}, + "failConfig.conf": {Data: []byte(needsUpdate)}, + } + + t.Run("Test success last update time", func(t *testing.T) { + want := true + got, err := NeedToUpdateAvailableVersions(fs, "successConfig.conf") + if err != nil { + t.Fatal(err) + } + + if got != want { + t.Errorf("updateAvailableVersions had incorrect output expected %v got %v", got, want) + } + }) + + t.Run("Test failed last update time", func(t *testing.T) { + want := false + got, err := NeedToUpdateAvailableVersions(fs, "failConfig.conf") + if err != nil { + t.Fatal(err) + } + + if got != want { + t.Errorf("updateAvailableVersions had incorrect output expected %v got %v", got, want) + } + }) +} + +func TestAvailableVersions(t *testing.T) { + availableVersionList := fmt.Sprintf("AvailableVersions: %+v", testVersionList()) + var want []SemVersion + for _, version := range testVersionList() { + want = append(want, *NewSemVersion(version)) + } + + fs := fstest.MapFS{ + "successConfig.conf": {Data: []byte(availableVersionList)}, + } + + t.Run("Test success last update time", func(t *testing.T) { + got, err := LoadVersionsFromConfig(fs, "successConfig.conf") + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(got, want) { + t.Errorf("LoadInstalledVersions had incorrect output expected %+v\n got %+v", want, got) + } + }) +} + +func TestInstalledVersions(t *testing.T) { + var want []SemVersion + testVersionList := testVersionList() + sort.Strings(testVersionList) + for _, version := range testVersionList { + want = append(want, *NewSemVersion(version)) + } + + 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("")}, + } + + t.Run("Test installed versions", func(t *testing.T) { + got, err := LoadInstalledVersions(fs) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(got, want) { + t.Errorf("LoadInstalledVersions had incorrect output expected\n %+v\n got %+v", want, got) + } + }) + +} diff --git a/fileHandler.go b/fileHandler.go new file mode 100644 index 0000000..e60ef6a --- /dev/null +++ b/fileHandler.go @@ -0,0 +1,56 @@ +package versionedTerraform + +import ( + "bufio" + "io/fs" + "regexp" + "strings" +) + +//todo this should be (Version) GetVers... +func GetVersionFromFile(fileSystem fs.FS, versionList []string) (*Version, error) { + var versionFinal Version + dir, err := fs.ReadDir(fileSystem, ".") + if err != nil { + return &versionFinal, err + } + + for _, f := range dir { + version, isFinished, err := parseVersionFromFile(fileSystem, f.Name(), versionList) + if err != nil { + return &versionFinal, err + } + if isFinished { + versionFinal = *version + break + } + } + return &versionFinal, nil +} + +//todo same here +func parseVersionFromFile(f fs.FS, fileName string, versionList []string) (*Version, bool, error) { + fileHandle, err := f.Open(fileName) + regex := regexp.MustCompile("required_version\\s+?=") + isComment := "^\\s?#" + removeQuotes := regexp.MustCompile("\"") + if err != nil { + return &Version{}, false, err + } + defer fileHandle.Close() + + fileScanner := bufio.NewScanner(fileHandle) + fileScanner.Split(bufio.ScanLines) + + for fileScanner.Scan() { + _line := fileScanner.Text() + isComment, _ := regexp.MatchString(isComment, _line) + if strings.Contains(_line, "required_version") && !isComment { + _line = regex.ReplaceAllString(_line, "") + _line = removeQuotes.ReplaceAllString(_line, "") + return NewVersion(_line, versionList), true, nil + } + } + + return &Version{}, false, nil +} diff --git a/fileHandler_test.go b/fileHandler_test.go new file mode 100644 index 0000000..6319890 --- /dev/null +++ b/fileHandler_test.go @@ -0,0 +1,49 @@ +package versionedTerraform + +import ( + "testing" + "testing/fstest" +) + +func TestFileHandler(t *testing.T) { + const ( + firstFile = ` +resource "aws_mq_broker" "sample" { + depends_on = [aws_security_group.mq] + broker_name = var.name + engine_type = "ActiveMQ" + engine_version = var.mqEngineVersion + host_instance_type = var.hostInstanceType + security_groups = [aws_security_groups.mq.id] + apply_immediately = "true" + deployment_mode = "ACTIVE_STANDBY_MULTI_AZ" + auto_minor_version_upgrade = "true" + subnet_ids = ["10.0.0.0/24", "10.0.1.0/24"] +} +` + secondFile = ` +terraform { + required_version = "~> 0.12.4" +} +` + ) + + want := NewVersion("0.12.31", testVersionList()) + + fs := fstest.MapFS{ + "main.tf": {Data: []byte(firstFile)}, + "versions.tf": {Data: []byte(secondFile)}, + } + + version, err := GetVersionFromFile(fs, testVersionList()) + + if err != nil { + t.Fatal(err) + } + + got := *version + + if got.Version != want.Version { + t.Errorf("Expected %v, got %v", want.Version, got.Version) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..afd3e22 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module versionedTerraform + +go 1.17 + +require github.com/blang/semver/v4 v4.0.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..eae0817 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= diff --git a/versionedTerraform.go b/versionedTerraform.go new file mode 100644 index 0000000..bb4ad71 --- /dev/null +++ b/versionedTerraform.go @@ -0,0 +1,194 @@ +package versionedTerraform + +import ( + "archive/zip" + "bufio" + "bytes" + "errors" + "io" + "io/ioutil" + "net/http" + "os" + "strings" +) + +func (*Version) latestMajorVersion() { +} + +func (*Version) latestMinorVersion() { +} + +func (*Version) latestPatchVersion() { +} + +type Version struct { + Version SemVersion + availableVersions []SemVersion + installedVersions []SemVersion +} + +const ( + hashicorpUrl = "https://releases.hashicorp.com/terraform/" + terraformPrefix = "terraform_" + fileSuffix = "_linux_amd64.zip" + versionedTerraformFolder = "/.versionedTerraform" +) + +//getLatestMajorRelease() returns the latest major release from Version +func (v *Version) getLatestMajorRelease() { + //todo clean up + for _, release := range v.availableVersions { + if release.majorVersion == v.Version.majorVersion && + release.minorVersion == v.Version.minorVersion && + release.patchVersion >= v.Version.patchVersion { + v.Version = release + } + } +} + +//getLatestRelease returns the latest release from Version +func (v *Version) getLatestRelease() { + //todo clean up + for _, release := range v.availableVersions { + if release.majorVersion > v.Version.majorVersion { + v.Version = release + } + if release.majorVersion >= v.Version.majorVersion && + release.minorVersion > v.Version.minorVersion { + v.Version = release + } + if release.majorVersion >= v.Version.majorVersion && + release.minorVersion >= v.Version.minorVersion && + release.patchVersion >= v.Version.patchVersion { + v.Version = release + } + } +} + +//InstallTerraformVersion installs the defined terraform Version in the application +//configuration directory +func (v *Version) InstallTerraformVersion() error { + homeDir, _ := os.UserHomeDir() + resp, err := http.Get(hashicorpUrl + + v.Version.ToString() + + "/" + terraformPrefix + + v.Version.ToString() + + fileSuffix) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) + if err != nil { + return err + } + versionedFileName := homeDir + versionedTerraformFolder + "/" + terraformPrefix + v.Version.ToString() + versionedFile, err := os.OpenFile(versionedFileName, os.O_WRONLY, 0755) + if os.IsNotExist(err) { + //_, err = os.Create(versionedFileName) + //if err != nil { + // return err + //} + versionedFile, err = os.OpenFile(versionedFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) + if err != nil { + return err + } + } + if err != nil { + return err + } + defer versionedFile.Close() + + for _, zipFIle := range zipReader.File { + zr, err := zipFIle.Open() + if err != nil { + return err + } + unzippedFileBytes, _ := ioutil.ReadAll(zr) + + _, err = versionedFile.Write(unzippedFileBytes) + if err != nil { + return err + } + zr.Close() + } + return nil +} + +//NewVersion creates a new Version using sem versioning for determining the +//latest release +func NewVersion(_version string, _vList []string) *Version { + v := new(Version) + v.Version = *NewSemVersion(_version) + + for _, release := range _vList { + v.availableVersions = append(v.availableVersions, *NewSemVersion(release)) + } + + switch { + case strings.Contains(v.Version.ToString(), latestRelease): + release := strings.Split(v.Version.ToString(), latestRelease)[1] + v.Version = *NewSemVersion(release) + v.getLatestRelease() + case strings.Contains(v.Version.ToString(), latestPatch): + release := strings.Split(v.Version.ToString(), latestPatch)[1] + v.Version = *NewSemVersion(release) + v.getLatestMajorRelease() + } + + return v +} + +//GetVersionList returns a list of available versions from hashicorp's release page +func GetVersionList() ([]string, error) { + var versionList []string + resp, err := http.Get(hashicorpUrl) + if err != nil { + return versionList, err + } + + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return versionList, errors.New("invalid response code") + } + + body, err := io.ReadAll(resp.Body) + + //todo maybe change this like GetVersionFromFile and consolidate + bodyText := string(body) + scanner := bufio.NewScanner(strings.NewReader(bodyText)) + for scanner.Scan() { + _line := scanner.Text() + if strings.Contains(_line, "a href") { + _lineSplice := strings.Split(_line, terraformPrefix) + if len(_lineSplice) == 2 { + _line = _lineSplice[1] + _line = strings.Split(_line, " 0.12.30", "0.12.31"}, + {testVersionList(), "~>0.12.30", "0.12.31"}, + {testVersionList(), "~>0.12.4", "0.12.31"}, + {testVersionList(), ">= 0.11.15", "1.1.11"}, + {testVersionList(), ">= 0.12.0", "1.1.11"}, + {testVersionList(), "~> 0.12", "0.12.31"}, + } + + for _, c := range cases { + t.Run("test Version check with various conditions: "+c.version, func(t *testing.T) { + //t.Parallel() + got := NewVersion(c.version, c.available) + if got.Version.version != c.expected { + t.Errorf("got %q, want %q", got.Version.version, c.expected) + } + }) + } +} + +func TestRemoveSpacesVersion(t *testing.T) { + cases := []struct { + tesValue, want string + }{ + {"test", "test"}, + {"test ", "test"}, + {" test", "test"}, + {" test ", "test"}, + {" test test ", "testtest"}, + } + + for _, c := range cases { + t.Run("test remove space in various conditions: "+c.tesValue, func(t *testing.T) { + t.Parallel() + got := removeSpacesVersion(c.tesValue) + if got != c.want { + t.Errorf("got %q, want %q", got, c.want) + } + }) + } +} + +func TestGetVersionList(t *testing.T) { + //todo write test for this + //response, _ := getVersionList() + //for _, Version := range response { + // t.Errorf("%v", Version) + //} + //t.Errorf("%v", response) +} + +func TestInstallTerraformVersion(t *testing.T) { + //todo write test for this + //Version := NewVersion("0.12.31", testVersionList()) + //response := Version.InstallTerraformVersion() + //t.Errorf("%v", response) +}