Skip to content

Commit

Permalink
Merge pull request warrensbox#97 from warrensbox/feature/skip-github-api
Browse files Browse the repository at this point in the history
Feature/skip GitHub api
  • Loading branch information
warrensbox authored Nov 15, 2021
2 parents d1b0575 + 4edeaf4 commit f42e05c
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 555 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 12 additions & 0 deletions lib/dir_perm.go
Original file line number Diff line number Diff line change
@@ -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
}
211 changes: 132 additions & 79 deletions lib/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"log"
"os"
"os/user"
"path/filepath"
"regexp"
"runtime"

"github.com/warrensbox/tgswitch/modal"
"strings"
)

const (
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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
}
}
Loading

0 comments on commit f42e05c

Please sign in to comment.