diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0dd2dbe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.5.0] - 2021-11-14 +### Context +- In the past, `tgswitch` uses github's API to get the list of releases. +- `tgswitch` uses client autorization key to access the terragrunt releases, however, github limits the number of api calls `tgswitch` can make. +- As a result, user cannot immediately download the version of terragrunt they want. They had to wait. + +### Added +- `tgswitch` will now get th list of releases from [terragrunt list page maintined by warrensbox](https://warrensbox.github.io/terragunt-versions-list/) +- `tgswitch` will directly download from the [terragrunt release page](https://github.com/gruntwork-io/terragrunt/releases) + +### Removed +- removed all functions that would make API github calls diff --git a/README.md b/README.md index 2d0ceaa..6689fed 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ Once installed, simply select the version you require from the dropdown and star See installation guide here: [tgswitch installation](https://warrensbox.github.io/tgswitch/) +***Important** +Please see upcoming changes [Version 0.5](CHANGELOG.md) + ## Installation `tgswitch` is available for MacOS and Linux based operating systems. diff --git a/lib/dir_perm.go b/lib/dir_perm.go new file mode 100644 index 0000000..0a833cb --- /dev/null +++ b/lib/dir_perm.go @@ -0,0 +1,12 @@ +// +build !windows + +package lib + +import "golang.org/x/sys/unix" + +//Check if user has permission to directory : +//dir=path to file +//return bool +func CheckDirWritable(dir string) bool { + return unix.Access(dir, unix.W_OK) == nil +} diff --git a/lib/install.go b/lib/install.go index 774813f..656a19f 100644 --- a/lib/install.go +++ b/lib/install.go @@ -5,10 +5,10 @@ import ( "log" "os" "os/user" + "path/filepath" "regexp" "runtime" - - "github.com/warrensbox/tgswitch/modal" + "strings" ) const ( @@ -64,84 +64,8 @@ func GetInstallLocation() string { return installLocation } -//Install : Install the provided version in the argument -func Install(url string, appversion string, assests []modal.Repo, installedBinPath string) string { - - initialize() - installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file - - /* If user provided bin path use user one instead of default */ - // if userBinPath != nil { - // installedBinPath = *userBinPath - // } - - pathDir := Path(installedBinPath) //get path directory from binary path - binDirExist := CheckDirExist(pathDir) //check bin path exist - - if !binDirExist { - fmt.Printf("Binary path does not exist: %s\n", pathDir) - fmt.Printf("Please create binary path: %s for terragrunt installation\n", pathDir) - os.Exit(1) - } - - /* check if selected version already downloaded */ - fileExist := CheckFileExist(installLocation + installVersion + appversion) - if fileExist { - installLocation := ChangeSymlink(installedBinPath, appversion) - return installLocation - } - - /* remove current symlink if exist*/ - symlinkExist := CheckSymlink(installedBinPath) - - if symlinkExist { - RemoveSymlink(installedBinPath) - } - - /* if selected version already exist, */ - /* proceed to download it from the terragrunt release page */ - //url := gruntURL + "v" + tgversion + "/" + "terragrunt" + "_" + goos + "_" + goarch - - goarch := runtime.GOARCH - goos := runtime.GOOS - urlDownload := "" - - for _, v := range assests { - - if v.TagName == "v"+appversion { - if len(v.Assets) > 0 { - for _, b := range v.Assets { - - matchedOS, _ := regexp.MatchString(goos, b.BrowserDownloadURL) - matchedARCH, _ := regexp.MatchString(goarch, b.BrowserDownloadURL) - if matchedOS && matchedARCH { - urlDownload = b.BrowserDownloadURL - break - } - } - } - break - } - } - - fileInstalled, _ := DownloadFromURL(installLocation, urlDownload) - - /* rename file to terragrunt version name - terragrunt_x.x.x */ - RenameFile(fileInstalled, installLocation+installVersion+appversion) - - err := os.Chmod(installLocation+installVersion+appversion, 0755) - if err != nil { - log.Println(err) - } - - /* set symlink to desired version */ - CreateSymlink(installLocation+installVersion+appversion, installedBinPath) - fmt.Printf("Switched terragrunt to version %q \n", appversion) - return installLocation -} - // AddRecent : add to recent file -func AddRecent(requestedVersion string, installLocation string) { +func AddRecent(requestedVersion string) { installLocation = GetInstallLocation() @@ -237,5 +161,134 @@ func ValidVersionFormat(version string) bool { // Check regular expression at https://rubular.com/r/ju3PxbaSBALpJB semverRegex := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-[a-zA-z]+\d*)?$`) + if !semverRegex.MatchString(version) { + fmt.Println("Invalid terragrunt version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") + } + return semverRegex.MatchString(version) } + +//Install : Install the provided version in the argument +func Install(tgversion string, usrBinPath string, mirrorURL string) string { + + if !ValidVersionFormat(tgversion) { + fmt.Printf("The provided terraform version format does not exist - %s. Try `tfswitch -l` to see all available versions.\n", tgversion) + os.Exit(1) + } + + /* 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 dont have permission to default location, therefore tfswitch was installed in $HOME/bin + * Tell users to add $HOME/bin to their path + */ + binPath := InstallableBinLocation(usrBinPath) + + initialize() //initialize path + installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file + + goarch := runtime.GOARCH + goos := runtime.GOOS + + installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, installVersion+tgversion)) + + /* check if selected version already downloaded */ + fileExist := CheckFileExist(installLocation + installVersion + tgversion) + if fileExist { + installLocation := ChangeSymlink(binPath, tgversion) + return installLocation + } + + //if does not have slash - append slash + hasSlash := strings.HasSuffix(mirrorURL, "/") + if !hasSlash { + mirrorURL = fmt.Sprintf("%s/", mirrorURL) + } + + /* if selected version already exist, */ + /* proceed to download it from the hashicorp release page */ + url := mirrorURL + "v" + tgversion + "/" + "terragrunt" + "_" + goos + "_" + goarch + + downloadedFile, errDownload := DownloadFromURL(installLocation, url) + + /* If unable to download file from url, exit(1) immediately */ + if errDownload != nil { + fmt.Println(errDownload) + os.Exit(1) + } + + /* rename unzipped file to terraform version name - terraform_x.x.x */ + RenameFile(downloadedFile, installFileVersionPath) + + err := os.Chmod(installFileVersionPath, 0755) + if err != nil { + log.Println(err) + } + /* remove current symlink if exist*/ + symlinkExist := CheckSymlink(binPath) + + if symlinkExist { + RemoveSymlink(binPath) + } + + /* set symlink to desired version */ + CreateSymlink(installFileVersionPath, binPath) + fmt.Printf("Switched terragrunt to version %q \n", tgversion) + //AddRecent(tgversion) //add to recent file for faster lookup + os.Exit(0) + return "" +} + +//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 +//Return $HOME/bin as install location +func InstallableBinLocation(binLocation string) string { + + usr, errCurr := user.Current() + if errCurr != nil { + log.Fatal(errCurr) + } + pathDir := Path(binLocation) //get path directory from binary path + existDefaultBin := CheckDirExist(pathDir) //the default is /usr/local/bin but users can provide custom bin locations + if existDefaultBin { //if exist - now see if we can write to to it + + writableToDefault := false + if runtime.GOOS != "windows" { + writableToDefault = CheckDirWritable(pathDir) //check if is writable on ( only works on LINUX) + } + + if !writableToDefault { + exisHomeBin := CheckDirExist(filepath.Join(usr.HomeDir, "bin")) + if exisHomeBin { + fmt.Printf("Installing terraform at %s\n", filepath.Join(usr.HomeDir, "bin")) + return filepath.Join(usr.HomeDir, "bin", "terraform") + } + PrintCreateDirStmt(pathDir, filepath.Join(usr.HomeDir, "bin")) + CreateDirIfNotExist(filepath.Join(usr.HomeDir, "bin")) + return filepath.Join(usr.HomeDir, "bin", "terraform") + } + return binLocation + } + fmt.Printf("[Error] : Binary path does not exist: %s\n", binLocation) + fmt.Printf("[Error] : Manually create bin directory at: %s and try again.\n", binLocation) + os.Exit(1) + return "" +} + +func PrintCreateDirStmt(unableDir string, writable string) { + fmt.Printf("Unable to write to: %s\n", unableDir) + fmt.Printf("Creating bin directory at: %s\n", writable) + fmt.Printf("RUN `export PATH=$PATH:%s` to append bin to $PATH\n", writable) +} + +//ConvertExecutableExt : convert excutable with local OS extension +func ConvertExecutableExt(fpath string) string { + switch runtime.GOOS { + case "windows": + if filepath.Ext(fpath) == ".exe" { + return fpath + } + return fpath + ".exe" + default: + return fpath + } +} diff --git a/lib/list_versions.go b/lib/list_versions.go index d9c3401..a8f135e 100644 --- a/lib/list_versions.go +++ b/lib/list_versions.go @@ -1,81 +1,16 @@ package lib import ( - "bytes" "encoding/json" - "errors" "fmt" "io/ioutil" "log" "net/http" - "net/url" - "os" "reflect" - "regexp" - "sort" - "strconv" "strings" - "sync" "time" - - "github.com/warrensbox/tgswitch/modal" ) -type AppVersionList struct { - applist []string - appDown *modal.Assets -} - -var wg = sync.WaitGroup{} - -var numPages = 5 - -//GetAppList : Get the list of available app versions -func GetAppList(appURL string, client *modal.Client) ([]string, []modal.Repo) { - - v := url.Values{} - v.Set("client_id", client.ClientID) - v.Add("client_secret", client.ClientSecret) - - gswitch := http.Client{ - Timeout: time.Second * 10, // Maximum of 10 secs [decresing this seem to fail] - } - - apiURL := appURL + v.Encode() - - req, err := http.NewRequest(http.MethodGet, apiURL, nil) - if err != nil { - log.Fatal("Unable to make request. Please try again.") - } - - req.Header.Set("User-Agent", "App Installer") - - resp, _ := gswitch.Do(req) - links := resp.Header.Get("Link") - link := strings.Split(links, ",") - - for _, pagNum := range link { - if strings.Contains(pagNum, "last") { - strPage := inBetween(pagNum, "page=", ">") - page, err := strconv.Atoi(strPage) - if err != nil { - fmt.Println(err) - os.Exit(2) - } - numPages = page - } - } - - applist, assets := getAppVersion(appURL, numPages, client) - - if len(applist) == 0 { - log.Println("No versions returned") - os.Exit(1) - } - - return applist, assets -} - //VersionExist : check if requested version exist func VersionExist(val interface{}, array interface{}) (exists bool) { @@ -92,6 +27,10 @@ func VersionExist(val interface{}, array interface{}) (exists bool) { } } + if !exists { + fmt.Println("Requested version does not exist") + } + return exists } @@ -116,75 +55,7 @@ func RemoveDuplicateVersions(elements []string) []string { return result } -func inBetween(value string, a string, b string) string { - // Get substring between two strings. - posFirst := strings.Index(value, a) - if posFirst == -1 { - return "" - } - posLast := strings.Index(value, b) - if posLast == -1 { - return "" - } - posFirstAdjusted := posFirst + len(a) - if posFirstAdjusted >= posLast { - return "" - } - return value[posFirstAdjusted:posLast] -} - -func getAppVersion(appURL string, numPages int, client *modal.Client) ([]string, []modal.Repo) { - assets := make([]modal.Repo, 0) - ch := make(chan *[]modal.Repo, 10) - - for i := 1; i <= numPages; i++ { - page := strconv.Itoa(i) - v := url.Values{} - v.Set("page", page) - v.Add("client_id", client.ClientID) - v.Add("client_secret", client.ClientSecret) - - apiURL := appURL + v.Encode() - wg.Add(1) - go getAppBody(apiURL, ch) - } - - go func(ch chan<- *[]modal.Repo) { - defer close(ch) - wg.Wait() - }(ch) - - for i := range ch { - assets = append(assets, *i...) - } - - semvers := []*Version{} - - var sortedVersion []string - - for _, v := range assets { - semverRegex := regexp.MustCompile(`\Av\d+(\.\d+){2}\z`) - if semverRegex.MatchString(v.TagName) { - trimstr := strings.Trim(v.TagName, "v") - sv, err := NewVersion(trimstr) - if err != nil { - fmt.Println(err) - } - semvers = append(semvers, sv) - } - } - - Sort(semvers) - - for _, sv := range semvers { - sortedVersion = append(sortedVersion, sv.String()) - } - - return sortedVersion, assets -} - -func getAppBody(gruntURLPage string, ch chan<- *[]modal.Repo) { - defer wg.Done() +func GetAppList(gruntURLPage string) []string { gswitch := http.Client{ Timeout: time.Second * 10, // Maximum of 10 secs [decresing this seem to fail] @@ -208,316 +79,16 @@ func getAppBody(gruntURLPage string, ch chan<- *[]modal.Repo) { log.Fatal(readErr) } - var repo []modal.Repo + var repo ListVersion jsonErr := json.Unmarshal(body, &repo) if jsonErr != nil { log.Println("Unable to get release from repo ", string(body)) log.Fatal(jsonErr) } - var validRepo []modal.Repo - - for _, num := range repo { - if num.Prerelease == false && num.Draft == false { - semverRegex := regexp.MustCompile(`\Av\d+(\.\d+){2}\z`) - if semverRegex.MatchString(num.TagName) { - validRepo = append(validRepo, num) - } - } - - } - - ch <- &validRepo - - //return &repo -} - -type Version struct { - Major int64 - Minor int64 - Patch int64 - PreRelease PreRelease - Metadata string -} - -type PreRelease string - -func splitOff(input *string, delim string) (val string) { - parts := strings.SplitN(*input, delim, 2) - - if len(parts) == 2 { - *input = parts[0] - val = parts[1] - } - - return val -} - -func New(version string) *Version { - return Must(NewVersion(version)) -} - -func NewVersion(version string) (*Version, error) { - v := Version{} - - if err := v.Set(version); err != nil { - return nil, err - } - - return &v, nil -} - -// Must is a helper for wrapping NewVersion and will panic if err is not nil. -func Must(v *Version, err error) *Version { - if err != nil { - panic(err) - } - return v -} - -// Set parses and updates v from the given version string. Implements flag.Value -func (v *Version) Set(version string) error { - metadata := splitOff(&version, "+") - preRelease := PreRelease(splitOff(&version, "-")) - dotParts := strings.SplitN(version, ".", 3) - - if len(dotParts) != 3 { - return fmt.Errorf("%s is not in dotted-tri format", version) - } - - if err := validateIdentifier(string(preRelease)); err != nil { - return fmt.Errorf("failed to validate pre-release: %v", err) - } - - if err := validateIdentifier(metadata); err != nil { - return fmt.Errorf("failed to validate metadata: %v", err) - } - - parsed := make([]int64, 3, 3) - - for i, v := range dotParts[:3] { - val, err := strconv.ParseInt(v, 10, 64) - parsed[i] = val - if err != nil { - return err - } - } - - v.Metadata = metadata - v.PreRelease = preRelease - v.Major = parsed[0] - v.Minor = parsed[1] - v.Patch = parsed[2] - return nil -} - -func (v Version) String() string { - var buffer bytes.Buffer - - fmt.Fprintf(&buffer, "%d.%d.%d", v.Major, v.Minor, v.Patch) - - if v.PreRelease != "" { - fmt.Fprintf(&buffer, "-%s", v.PreRelease) - } - - if v.Metadata != "" { - fmt.Fprintf(&buffer, "+%s", v.Metadata) - } - - return buffer.String() -} - -func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) error { - var data string - if err := unmarshal(&data); err != nil { - return err - } - return v.Set(data) -} - -func (v Version) MarshalJSON() ([]byte, error) { - return []byte(`"` + v.String() + `"`), nil -} - -func (v *Version) UnmarshalJSON(data []byte) error { - l := len(data) - if l == 0 || string(data) == `""` { - return nil - } - if l < 2 || data[0] != '"' || data[l-1] != '"' { - return errors.New("invalid semver string") - } - return v.Set(string(data[1 : l-1])) -} - -// Compare tests if v is less than, equal to, or greater than versionB, -// returning -1, 0, or +1 respectively. -func (v Version) Compare(versionB Version) int { - if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 { - return cmp - } - return preReleaseCompare(v, versionB) -} - -// Equal tests if v is equal to versionB. -func (v Version) Equal(versionB Version) bool { - return v.Compare(versionB) == 0 -} - -// LessThan tests if v is less than versionB. -func (v Version) LessThan(versionB Version) bool { - return v.Compare(versionB) < 0 -} - -// Slice converts the comparable parts of the semver into a slice of integers. -func (v Version) Slice() []int64 { - return []int64{v.Major, v.Minor, v.Patch} -} - -func (p PreRelease) Slice() []string { - preRelease := string(p) - return strings.Split(preRelease, ".") -} - -func preReleaseCompare(versionA Version, versionB Version) int { - a := versionA.PreRelease - b := versionB.PreRelease - - /* Handle the case where if two versions are otherwise equal it is the - * one without a PreRelease that is greater */ - if len(a) == 0 && (len(b) > 0) { - return 1 - } else if len(b) == 0 && (len(a) > 0) { - return -1 - } - - // If there is a prerelease, check and compare each part. - return recursivePreReleaseCompare(a.Slice(), b.Slice()) -} - -func recursiveCompare(versionA []int64, versionB []int64) int { - if len(versionA) == 0 { - return 0 - } - - a := versionA[0] - b := versionB[0] - - if a > b { - return 1 - } else if a < b { - return -1 - } - - return recursiveCompare(versionA[1:], versionB[1:]) -} - -func recursivePreReleaseCompare(versionA []string, versionB []string) int { - // A larger set of pre-release fields has a higher precedence than a smaller set, - // if all of the preceding identifiers are equal. - if len(versionA) == 0 { - if len(versionB) > 0 { - return -1 - } - return 0 - } else if len(versionB) == 0 { - // We're longer than versionB so return 1. - return 1 - } - - a := versionA[0] - b := versionB[0] - - aInt := false - bInt := false - - aI, err := strconv.Atoi(versionA[0]) - if err == nil { - aInt = true - } - - bI, err := strconv.Atoi(versionB[0]) - if err == nil { - bInt = true - } - - // Numeric identifiers always have lower precedence than non-numeric identifiers. - if aInt && !bInt { - return -1 - } else if !aInt && bInt { - return 1 - } - - // Handle Integer Comparison - if aInt && bInt { - if aI > bI { - return 1 - } else if aI < bI { - return -1 - } - } - - // Handle String Comparison - if a > b { - return 1 - } else if a < b { - return -1 - } - - return recursivePreReleaseCompare(versionA[1:], versionB[1:]) -} - -// BumpMajor increments the Major field by 1 and resets all other fields to their default values -func (v *Version) BumpMajor() { - v.Major += 1 - v.Minor = 0 - v.Patch = 0 - v.PreRelease = PreRelease("") - v.Metadata = "" -} - -// BumpMinor increments the Minor field by 1 and resets all other fields to their default values -func (v *Version) BumpMinor() { - v.Minor += 1 - v.Patch = 0 - v.PreRelease = PreRelease("") - v.Metadata = "" -} - -// BumpPatch increments the Patch field by 1 and resets all other fields to their default values -func (v *Version) BumpPatch() { - v.Patch += 1 - v.PreRelease = PreRelease("") - v.Metadata = "" -} - -// validateIdentifier makes sure the provided identifier satisfies semver spec -func validateIdentifier(id string) error { - if id != "" && !reIdentifier.MatchString(id) { - return fmt.Errorf("%s is not a valid semver identifier", id) - } - return nil -} - -// reIdentifier is a regular expression used to check that pre-release and metadata -// identifiers satisfy the spec requirements -var reIdentifier = regexp.MustCompile(`^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$`) - -type Versions []*Version - -func (s Versions) Len() int { - return len(s) -} - -func (s Versions) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s Versions) Less(i, j int) bool { - return s[i].LessThan(*s[j]) + return repo.Versions } -// Sort sorts the given slice of Version -func Sort(versions []*Version) { - sort.Sort(sort.Reverse(Versions(versions))) +type ListVersion struct { + Versions []string `json:"Versions"` } diff --git a/main.go b/main.go index cafca7c..f22197b 100644 --- a/main.go +++ b/main.go @@ -20,35 +20,26 @@ import ( "io/ioutil" "log" "os" - "regexp" "strings" "github.com/manifoldco/promptui" "github.com/pborman/getopt" lib "github.com/warrensbox/tgswitch/lib" - "github.com/warrensbox/tgswitch/modal" ) const ( - terragruntURL = "https://api.github.com/repos/gruntwork-io/terragrunt/releases?" + terragruntURL = "https://github.com/gruntwork-io/terragrunt/releases/download/" defaultBin = "/usr/local/bin/terragrunt" //default bin installation dir rcFilename = ".tgswitchrc" tgvFilename = ".terragrunt-version" installVersion = "terragrunt_" + proxyUrl = "https://warrensbox.github.io/terragunt-versions-list/index.json" ) -var version = "0.2.0\n" - -var CLIENT_ID = "xxx" -var CLIENT_SECRET = "xxx" +var version = "0.5.0\n" func main() { - var client modal.Client - - client.ClientID = CLIENT_ID - client.ClientSecret = CLIENT_SECRET - custBinPath := getopt.StringLong("bin", 'b', defaultBin, "Custom binary path. For example: /Users/username/bin/terragrunt") versionFlag := getopt.BoolLong("version", 'v', "displays the version of tgswitch") helpFlag := getopt.BoolLong("help", 'h', "displays help message") @@ -87,12 +78,11 @@ func main() { lib.ChangeSymlink(*custBinPath, string(tgversion)) os.Exit(0) } - _, assets := lib.GetAppList(terragruntURL, &client) + listOfVersions := lib.GetAppList(proxyUrl) - if lib.ValidVersionFormat(tgversion) { //check if version is correct - lib.Install(terragruntURL, string(tgversion), assets, *custBinPath) + if lib.ValidVersionFormat(tgversion) && lib.VersionExist(tgversion, listOfVersions) { //check if version format is correct && if version exist + lib.Install(tgversion, *custBinPath, terragruntURL) } else { - fmt.Println("Invalid terragrunt version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") os.Exit(1) } @@ -111,20 +101,18 @@ func main() { lib.ChangeSymlink(*custBinPath, string(tgversion)) os.Exit(0) } - _, assets := lib.GetAppList(terragruntURL, &client) + listOfVersions := lib.GetAppList(proxyUrl) - if lib.ValidVersionFormat(tgversion) { //check if version is correct - lib.Install(terragruntURL, string(tgversion), assets, *custBinPath) + if lib.ValidVersionFormat(tgversion) && lib.VersionExist(tgversion, listOfVersions) { //check if version format is correct && if version exist + lib.Install(tgversion, *custBinPath, terragruntURL) } else { - fmt.Println("Invalid terragrunt version format. Format should be #.#.# or #.#.#-@# where # is numbers and @ is word characters. For example, 0.11.7 and 0.11.9-beta1 are valid versions") os.Exit(1) } } else if len(args) == 1 { + requestedVersion := args[0] - semverRegex := regexp.MustCompile(`\A\d+(\.\d+){2}\z`) - if semverRegex.MatchString(args[0]) { - requestedVersion := args[0] + if lib.ValidVersionFormat(requestedVersion) { fileExist := lib.CheckFileExist(installLocation + installVersion + string(requestedVersion)) if fileExist { @@ -133,33 +121,30 @@ func main() { } //check if version exist before downloading it - tflist, assets := lib.GetAppList(terragruntURL, &client) - exist := lib.VersionExist(requestedVersion, tflist) + listOfVersions := lib.GetAppList(proxyUrl) + exist := lib.VersionExist(requestedVersion, listOfVersions) if exist { - installLocation := lib.Install(terragruntURL, requestedVersion, assets, *custBinPath) - lib.AddRecent(requestedVersion, installLocation) //add to recent file for faster lookup - } else { - fmt.Println("Not a valid terragrunt version") + installLocation := lib.Install(requestedVersion, *custBinPath, terragruntURL) + fmt.Println("remove later - installLocation:", installLocation) } } else { - fmt.Println("Not a valid terragrunt version") fmt.Println("Args must be a valid terragrunt version") usageMessage() } } else if len(args) == 0 { - tglist, assets := lib.GetAppList(terragruntURL, &client) - recentVersions, _ := lib.GetRecentVersions() //get recent versions from RECENT file - tglist = append(recentVersions, tglist...) //append recent versions to the top of the list - tglist = lib.RemoveDuplicateVersions(tglist) //remove duplicate version + listOfVersions := lib.GetAppList(proxyUrl) + recentVersions, _ := lib.GetRecentVersions() //get recent versions from RECENT file + listOfVersions = append(recentVersions, listOfVersions...) //append recent versions to the top of the list + listOfVersions = lib.RemoveDuplicateVersions(listOfVersions) //remove duplicate version /* prompt user to select version of terragrunt */ prompt := promptui.Select{ Label: "Select terragrunt version", - Items: tglist, + Items: listOfVersions, } _, tgversion, errPrompt := prompt.Run() @@ -170,8 +155,7 @@ func main() { os.Exit(1) } - installLocation := lib.Install(terragruntURL, tgversion, assets, *custBinPath) - lib.AddRecent(tgversion, installLocation) //add to recent file for faster lookup + lib.Install(tgversion, *custBinPath, terragruntURL) os.Exit(0) } else { usageMessage() diff --git a/test-data/test_terragrunt-version/.terragrunt-version b/test-data/test_terragrunt-version/.terragrunt-version new file mode 100644 index 0000000..336fb3b --- /dev/null +++ b/test-data/test_terragrunt-version/.terragrunt-version @@ -0,0 +1 @@ +0.34.5 \ No newline at end of file diff --git a/test-data/test_tgswitchrc/.tgswitchrc b/test-data/test_tgswitchrc/.tgswitchrc new file mode 100644 index 0000000..c5b5abf --- /dev/null +++ b/test-data/test_tgswitchrc/.tgswitchrc @@ -0,0 +1 @@ +0.31.11 \ No newline at end of file diff --git a/version b/version index fe3b706..98eace8 100644 --- a/version +++ b/version @@ -1 +1 @@ -RELEASE_VERSION=0.4 \ No newline at end of file +RELEASE_VERSION=0.5 \ No newline at end of file