Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements #4

Merged
merged 4 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func checkFileExist(file string) bool {

func createFile(path string) {
// detect if file exists
var _, err = os.Stat(path)
_, err := os.Stat(path)

// create file if not exists
if os.IsNotExist(err) {
Expand All @@ -32,7 +32,7 @@ func createFile(path string) {
func createDirIfNotExist(dir string) {
if _, err := os.Stat(dir); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v", dir)
err = os.MkdirAll(dir, 0755)
err = os.MkdirAll(dir, 0o755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v", dir)
panic(err)
Expand Down
4 changes: 2 additions & 2 deletions lib/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func DownloadFromURL(installLocation string, url string) (string, error) {
defer response.Body.Close()

if response.StatusCode != 200 {
//Sometimes hashicorp terraform file names are not consistent
//For example 0.12.0-alpha4 naming convention in the release repo is not consistent
// Sometimes hashicorp terraform file names are not consistent
// For example 0.12.0-alpha4 naming convention in the release repo is not consistent
return "", fmt.Errorf("[Error] : Unable to download from %s", url)
}

Expand Down
12 changes: 4 additions & 8 deletions lib/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

// TestDownloadFromURL_FileNameMatch : Check expected filename exist when downloaded
func TestDownloadFromURL_FileNameMatch(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"
installVersion := "terraform_"
installPath := getInstallLocation(".terraform.versions_test")
Expand All @@ -32,7 +31,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {
// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v", installLocation)
err = os.MkdirAll(installLocation, 0755)
err = os.MkdirAll(installLocation, 0o755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v", installLocation)
panic(err)
Expand Down Expand Up @@ -88,7 +87,6 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {

// TestDownloadFromURL_FileExist : Check expected file exist when downloaded
func TestDownloadFromURL_FileExist(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"
installVersion := "terraform_"
installPath := getInstallLocation(".terraform.versions_test")
Expand All @@ -106,7 +104,7 @@ func TestDownloadFromURL_FileExist(t *testing.T) {
// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v", installLocation)
err = os.MkdirAll(installLocation, 0755)
err = os.MkdirAll(installLocation, 0o755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v", installLocation)
panic(err)
Expand Down Expand Up @@ -162,7 +160,6 @@ func TestDownloadFromURL_FileExist(t *testing.T) {

// TestInvalidURL : Invalid url should throw an error
func TestInvalidURL(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"
installVersion := "terraform_"
installPath := getInstallLocation(".terraform.versions_test")
Expand All @@ -181,15 +178,15 @@ func TestInvalidURL(t *testing.T) {
// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v\n", installLocation)
err = os.MkdirAll(installLocation, 0755)
err = os.MkdirAll(installLocation, 0o755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v\n", installLocation)
panic(err)
}
}

url := hashiURL + invalidVersion + "/" + installVersion + invalidVersion + macOS
//expectedFile :=filepath.Join(usr.HomeDir, installPath, installVersion + invalidVersion + macOS)
// expectedFile :=filepath.Join(usr.HomeDir, installPath, installVersion + invalidVersion + macOS)
_, errDownload := lib.DownloadFromURL(installLocation, url)

if errDownload != nil {
Expand All @@ -202,7 +199,6 @@ func TestInvalidURL(t *testing.T) {

// TestDownloadFromURL_Valid : Test if https://releases.hashicorp.com/terraform/ is still valid
func TestDownloadFromURL_Valid(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"

url, err := url.ParseRequestURI(hashiURL)
Expand Down
26 changes: 9 additions & 17 deletions lib/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import (

// RenameFile : rename file name
func RenameFile(src string, dest string) {
err := os.Rename(src, dest)
if err != nil {
if err := os.Rename(src, dest); err != nil {
fmt.Println(err)
return
}
Expand All @@ -21,7 +20,6 @@ func RenameFile(src string, dest string) {
func RemoveFiles(src string) {
files, err := filepath.Glob(src)
if err != nil {

panic(err)
}
for _, f := range files {
Expand All @@ -40,17 +38,15 @@ func CheckFileExist(file string) bool {
// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, dest string) ([]string, error) {

var filenames []string

r, err := zip.OpenReader(src)
if err != nil {
return filenames, err
return []string{}, err
}
defer r.Close()

for _, f := range r.File {
filenames := make([]string, 0, len(r.File))

for _, f := range r.File {
rc, err := f.Open()
if err != nil {
return filenames, err
Expand All @@ -62,15 +58,12 @@ func Unzip(src string, dest string) ([]string, error) {
filenames = append(filenames, fpath)

if f.FileInfo().IsDir() {

// Make Folder
err := os.MkdirAll(fpath, os.ModePerm)
if err != nil {
return []string{}, err
}

} else {

// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
Expand All @@ -89,27 +82,26 @@ func Unzip(src string, dest string) ([]string, error) {
if err != nil {
return filenames, err
}

}
}
return filenames, nil
}

//CreateDirIfNotExist : create directory if directory does not exist
// CreateDirIfNotExist : create directory if directory does not exist
func CreateDirIfNotExist(dir string) {
if _, err := os.Stat(dir); os.IsNotExist(err) {
fmt.Printf("Creating directory for terraform binary at: %v\n", dir)
err = os.MkdirAll(dir, 0755)
err = os.MkdirAll(dir, 0o755)
if err != nil {
fmt.Printf("Unable to create directory for terraform binary at: %v", dir)
panic(err)
}
}
}

//CheckDirExist : check if directory exist
//dir=path to file
//return bool
// CheckDirExist : check if directory exist
// dir=path to file
// return bool
func CheckDirExist(dir string) bool {
if _, err := os.Stat(dir); os.IsNotExist(err) {
return false
Expand Down
35 changes: 11 additions & 24 deletions lib/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ const (
lockFilePath = "/tmp/simple-tfswitch.lock"
)

var (
installLocation = "/tmp"
)

// getInstallLocation : get location where the terraform binary will be installed,
// will create a directory in the home location if it does not exist
func getInstallLocation() string {
Expand All @@ -42,28 +38,26 @@ func getInstallLocation() string {
}

/* set installation location */
installLocation = filepath.Join(userCommon, installPath)
installLocation := filepath.Join(userCommon, installPath)

/* Create local installation directory if it does not exist */
CreateDirIfNotExist(installLocation)

return installLocation

}

func WaitForLockFile() (unlock func()) {
m := lockedfile.MutexAt(lockFilePath)
unlock, err := m.Lock()
if err != nil {
fmt.Printf("there was a problem while trying to aquire lockfile %v", lockFilePath)
fmt.Printf("there was a problem while trying to acquire lockfile %v", lockFilePath)
os.Exit(1)
}
return unlock
}

//Install : Install the provided version in the argument
func Install(tfversion string, mirrorURL string) string {

// Install : Install the provided version in the argument
func Install(tfversion string, mirrorURL string) (string, error) {
if !ValidVersionFormat(tfversion) {
fmt.Printf("The provided terraform version format does not exist - %s. Try `tfswitch -l` to see all available versions.\n", tfversion)
os.Exit(1)
Expand All @@ -73,26 +67,21 @@ func Install(tfversion string, mirrorURL string) string {
unlock := WaitForLockFile()
defer unlock()

installLocation = getInstallLocation() //get installation location - this is where we will put our terraform binary file
installLocation := getInstallLocation() // get installation location - this is where we will put our terraform binary file

goarch := runtime.GOARCH
goos := runtime.GOOS

// TODO: Workaround for macos arm64 since terraform doesn't have a binary for it yet
if goos == "darwin" && goarch == "arm64" {
goarch = "amd64"
}

/* check if selected version already downloaded */
installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, installVersion+tfversion))
fileExist := CheckFileExist(installFileVersionPath)

/* if selected version already exist, */
if fileExist {
return installFileVersionPath
return installFileVersionPath, nil
}

//if does not have slash - append slash
// if does not have slash - append slash
hasSlash := strings.HasSuffix(mirrorURL, "/")
if !hasSlash {
mirrorURL = fmt.Sprintf("%s/", mirrorURL)
Expand All @@ -105,16 +94,14 @@ func Install(tfversion string, mirrorURL string) string {

/* If unable to download file from url, exit(1) immediately */
if errDownload != nil {
fmt.Println(errDownload)
os.Exit(1)
return "", errDownload
}

/* unzip the downloaded zipfile */
_, errUnzip := Unzip(zipFile, installLocation)
if errUnzip != nil {
fmt.Println("[Error] : Unable to unzip downloaded zip file")
log.Fatal(errUnzip)
os.Exit(1)
return "", errUnzip
}

/* rename unzipped file to terraform version name - terraform_x.x.x */
Expand All @@ -124,10 +111,10 @@ func Install(tfversion string, mirrorURL string) string {
/* remove zipped file to clear clutter */
RemoveFiles(zipFile)

return installFileVersionPath
return installFileVersionPath, nil
}

//ConvertExecutableExt : convert excutable with local OS extension
// ConvertExecutableExt : convert excutable with local OS extension
func ConvertExecutableExt(fpath string) string {
switch runtime.GOOS {
case "windows":
Expand Down
1 change: 0 additions & 1 deletion lib/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ func getInstallLocation(installPath string) string {
}

func TestInstall(t *testing.T) {

t.Run("User should exist",
func(t *testing.T) {
usr, errCurr := user.Current()
Expand Down
21 changes: 8 additions & 13 deletions lib/list_versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ type tfVersionList struct {
tflist []string
}

//GetTFList : Get the list of available terraform version given the hashicorp url
// GetTFList : Get the list of available terraform version given the hashicorp url
func GetTFList(mirrorURL string, preRelease bool) ([]string, error) {

result, error := GetTFURLBody(mirrorURL)
if error != nil {
return nil, error
result, err := GetTFURLBody(mirrorURL)
if err != nil {
return nil, err
}

var tfVersionList tfVersionList
Expand All @@ -35,7 +34,7 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) {
for i := range result {
if r.MatchString(result[i]) {
str := r.FindString(result[i])
trimstr := strings.Trim(str, "/") //remove "/" from /X.X.X/
trimstr := strings.Trim(str, "/") // remove "/" from /X.X.X/
tfVersionList.tflist = append(tfVersionList.tflist, trimstr)
}
}
Expand All @@ -45,14 +44,12 @@ func GetTFList(mirrorURL string, preRelease bool) ([]string, error) {
}

return tfVersionList.tflist, nil

}

//GetTFURLBody : Get list of terraform versions from hashicorp releases
// GetTFURLBody : Get list of terraform versions from hashicorp releases
func GetTFURLBody(mirrorURL string) ([]string, error) {

hasSlash := strings.HasSuffix(mirrorURL, "/")
if !hasSlash { //if does not have slash - append slash
if !hasSlash { // if does not have slash - append slash
mirrorURL = fmt.Sprintf("%s/", mirrorURL)
}
resp, errURL := http.Get(mirrorURL)
Expand All @@ -65,13 +62,12 @@ func GetTFURLBody(mirrorURL string) ([]string, error) {

if resp.StatusCode != 200 {
log.Printf("[Error] : Retrieving contents from url: %s", mirrorURL)
os.Exit(1)
return nil, fmt.Errorf("[Error] : Retrieving contents from url: %s", mirrorURL)
}

body, errBody := ioutil.ReadAll(resp.Body)
if errBody != nil {
log.Printf("[Error] : reading body: %v", errBody)
os.Exit(1)
return nil, errBody
}

Expand All @@ -89,7 +85,6 @@ func GetTFURLBody(mirrorURL string) ([]string, error) {
// For example: 0.1. 2 = invalid
*/
func ValidVersionFormat(version string) bool {

// Getting versions from body; should return match /X.X.X-@/ where X is a number,@ is a word character between a-z or A-Z
// Follow https://semver.org/spec/v1.0.0-beta.html
// Check regular expression at https://rubular.com/r/ju3PxbaSBALpJB
Expand Down
6 changes: 1 addition & 5 deletions lib/list_versions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const (

// TestGetTFList : Get list from hashicorp
func TestGetTFList(t *testing.T) {

listAll := true
list, _ := lib.GetTFList(hashiURL, listAll)

Expand All @@ -37,13 +36,11 @@ func TestGetTFList(t *testing.T) {
} else {
t.Log("Write versions exist (expected)")
}

}

//TestValidVersionFormat : test if func returns valid version format
// TestValidVersionFormat : test if func returns valid version format
// more regex testing at https://rubular.com/r/UvWXui7EU2icSb
func TestValidVersionFormat(t *testing.T) {

var version string
version = "0.11.8"

Expand Down Expand Up @@ -134,5 +131,4 @@ func TestValidVersionFormat(t *testing.T) {
} else {
log.Fatalf("Failed to verify version format: %s\n", version)
}

}
Loading