Skip to content

Commit

Permalink
- extracted defaultBin constant to an extra package as it is reused i…
Browse files Browse the repository at this point in the history
…n main and lib.

- added detection of home directory in case we are using windows.
- updated tests accordingly.
  • Loading branch information
MatrixCrawler committed Mar 14, 2024
1 parent abf37d9 commit 7c21e4b
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 46 deletions.
20 changes: 20 additions & 0 deletions lib/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package lib

import (
"github.com/mitchellh/go-homedir"
"log"
"runtime"
)

// GetDefaultBin Get default binary path
func GetDefaultBin() string {
var defaultBin = "/usr/local/bin/terraform"
if runtime.GOOS == "windows" {
home, err := homedir.Dir()
if err != nil {
log.Fatalf(`Could not detect home directory.`)
}
defaultBin = home + `/bin/terraform.exe`
}
return defaultBin
}
24 changes: 15 additions & 9 deletions lib/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package lib_test

import (
"fmt"
"github.com/mitchellh/go-homedir"
"log"
"net/url"
"os"
"os/user"
"path/filepath"
"runtime"
"testing"

"github.com/warrensbox/terraform-switcher/lib"
Expand All @@ -21,14 +22,19 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {
installPath := fmt.Sprintf(tempDir + string(os.PathSeparator) + ".terraform.versions_test")
macOS := "_darwin_amd64.zip"

// get current user
usr, errCurr := user.Current()
if errCurr != nil {
log.Fatal(errCurr)
home, err := homedir.Dir()
if err != nil {
log.Fatalf(`Could not detect home directory.`)
}

fmt.Printf("Current user: %v \n", usr.HomeDir)
installLocation := filepath.Join(usr.HomeDir, installPath)
fmt.Printf("Current user homedir: %v \n", home)
var installLocation = ""
if runtime.GOOS != "windows" {
installLocation = filepath.Join(home, installPath)
} else {
installLocation = installPath
}
fmt.Printf("Install Location: %v \n", installLocation)

// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
Expand All @@ -44,7 +50,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {
lowestVersion := "0.11.0"

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

if errDownload != nil {
Expand All @@ -63,7 +69,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {
}

//check file name is what is expected
_, err := os.Stat(expectedFile)
_, err = os.Stat(expectedFile)
if err != nil {
t.Logf("Expected file does not exist %v", expectedFile)
}
Expand Down
26 changes: 13 additions & 13 deletions lib/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const (
versionPrefix = "terraform_"
installPath = ".terraform.versions"
recentFile = "RECENT"
defaultBin = "/usr/local/bin/terraform" //default bin installation dir
tfDarwinArm64StartVersion = "1.0.2"
)

Expand All @@ -29,16 +28,17 @@ var (
func initialize() {

/* Step 1 */
/* initilize default binary path for terraform */
/* initialize default binary path for terraform */
/* assumes that terraform is installed here */
/* we will find the terraform path instalation later and replace this variable with the correct installed bin path */
installedBinPath := "/usr/local/bin/terraform"
/* we will find the terraform path installation later and replace this variable with the correct installed bin path */
//installedBinPath := "/usr/local/bin/terraform"
installedBinPath := GetDefaultBin()

/* find terraform binary location if terraform is already installed*/
cmd := NewCommand("terraform")
next := cmd.Find()

/* overrride installation default binary path if terraform is already installed */
/* override installation default binary path if terraform is already installed */
/* find the last bin path */
for path := next(); len(path) > 0; path = next() {
installedBinPath = path
Expand Down Expand Up @@ -75,7 +75,7 @@ func GetInstallLocation() string {

}

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

// if !ValidVersionFormat(tfversion) {
Expand All @@ -85,7 +85,7 @@ func Install(tfversion string, binPath string, mirrorURL string) {

/* 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
* Inform user that they don't have permission to default location, therefore tfswitch was installed in $HOME/bin
* Tell users to add $HOME/bin to their path
*/
binPath = InstallableBinLocation(binPath)
Expand Down Expand Up @@ -232,7 +232,7 @@ func GetRecentVersions() ([]string, error) {

for _, line := range lines {
/* checks if versions in the recent file are valid.
If any version is invalid, it will be consider dirty
If any version is invalid, it will be considered dirty
and the recent file will be removed
*/
if !ValidVersionFormat(line) {
Expand All @@ -252,15 +252,15 @@ func GetRecentVersions() ([]string, error) {
return nil, nil
}

//CreateRecentFile : create a recent file
// CreateRecentFile : create a recent file
func CreateRecentFile(requestedVersion string) {

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

WriteLines([]string{requestedVersion}, filepath.Join(installLocation, recentFile))
}

//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 All @@ -273,8 +273,8 @@ func ConvertExecutableExt(fpath string) string {
}
}

//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 and return $HOME/bin as install location
// 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 and return $HOME/bin as install location
func InstallableBinLocation(userBinPath string) string {

usr, errCurr := user.Current()
Expand All @@ -285,7 +285,7 @@ func InstallableBinLocation(userBinPath string) string {
binDir := Path(userBinPath) //get path directory from binary path
binPathExist := CheckDirExist(binDir) //the default is /usr/local/bin but users can provide custom bin locations

if binPathExist == true { //if bin path exist - check if we can write to to it
if binPathExist == true { //if bin path exist - check if we can write to it

binPathWritable := false //assume bin path is not writable
if runtime.GOOS != "windows" {
Expand Down
60 changes: 42 additions & 18 deletions lib/symlink_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package lib_test

import (
"github.com/mitchellh/go-homedir"
"log"
"os"
"os/user"
"path/filepath"
"runtime"
"testing"

"github.com/warrensbox/terraform-switcher/lib"
Expand All @@ -14,38 +16,60 @@ import (
// create symlink, check if symlink exist, remove symlink
func TestCreateSymlink(t *testing.T) {

testSymlinkDest := "/test-tfswitcher-dest"
testSymlinkSrc := "/test-tfswitcher-src"
if runtime.GOOS == "windows" {
testSymlinkSrc = "/test-tfswitcher-src.exe"
}

testSymlinkDest := "/test-tfswitcher-dest"
home, err := homedir.Dir()
if err != nil {
log.Fatalf(`Could not detect home directory.`)
}
symlinkPathSrc := filepath.Join(home, testSymlinkSrc)
symlinkPathDest := filepath.Join(home, testSymlinkDest)

usr, errCurr := user.Current()
if errCurr != nil {
log.Fatal(errCurr)
// Create file for test as windows does not like no source
create, err := os.Create(symlinkPathDest)
if err != nil {
log.Fatalf(`Could not create test dest file for symlink at %v`, symlinkPathDest)
}
symlinkPathSrc := filepath.Join(usr.HomeDir, testSymlinkSrc)
symlinkPathDest := filepath.Join(usr.HomeDir, testSymlinkDest)
defer create.Close()

ln, _ := os.Readlink(symlinkPathSrc)
if runtime.GOOS != "windows" {
ln, _ := os.Readlink(symlinkPathSrc)

if ln != symlinkPathDest {
t.Logf("Symlink does not exist %v [expected]", ln)
} else {
t.Logf("Symlink exist %v [expected]", ln)
os.Remove(symlinkPathSrc)
t.Logf("Removed existing symlink for testing purposes")
if ln != symlinkPathDest {
t.Logf("Symlink does not exist %v [expected]", ln)
} else {
t.Logf("Symlink exist %v [expected]", ln)
os.Remove(symlinkPathSrc)
t.Logf("Removed existing symlink for testing purposes")
}
}

lib.CreateSymlink(symlinkPathDest, symlinkPathSrc)

lnCheck, _ := os.Readlink(symlinkPathSrc)
if lnCheck == symlinkPathDest {
t.Logf("Symlink exist %v [expected]", lnCheck)
if runtime.GOOS == "windows" {
_, err := os.Stat(symlinkPathSrc + ".exe")
if err != nil {
t.Logf("Could not stat file copy at %v. [unexpected]", symlinkPathSrc)
t.Error("File copy was not created.")
} else {
t.Logf("File copy exists at %v [expected]", symlinkPathSrc)
}
} else {
t.Logf("Symlink does not exist %v [unexpected]", lnCheck)
t.Error("Symlink was not created")
lnCheck, _ := os.Readlink(symlinkPathSrc)
if lnCheck == symlinkPathDest {
t.Logf("Symlink exist %v [expected]", lnCheck)
} else {
t.Logf("Symlink does not exist %v [unexpected]", lnCheck)
t.Error("Symlink was not created")
}
}

os.Remove(symlinkPathSrc)
os.Remove(symlinkPathDest)
}

// TestRemoveSymlink : check if symlink exist-create if does not exist,
Expand Down
11 changes: 5 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package main

/*** OPERATION WORKFLOW ***/
/*
* 1- Create /usr/local/terraform directory if does not exist
* 1- Create /usr/local/terraform directory if it does not exist
* 2- Download zip file from url to /usr/local/terraform
* 3- Unzip the file to /usr/local/terraform
* 4- Rename the file from `terraform` to `terraform_version`
Expand Down Expand Up @@ -39,7 +39,6 @@ import (

const (
defaultMirror = "https://releases.hashicorp.com/terraform"
defaultBin = "/usr/local/bin/terraform" //default bin installation dir
defaultLatest = ""
tfvFilename = ".terraform-version"
rcFilename = ".tfswitchrc"
Expand All @@ -52,7 +51,7 @@ var version = "0.12.0\n"

func main() {
dir := lib.GetCurrentDirectory()
custBinPath := getopt.StringLong("bin", 'b', lib.ConvertExecutableExt(defaultBin), "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform"))
custBinPath := getopt.StringLong("bin", 'b', lib.ConvertExecutableExt(lib.GetDefaultBin()), "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform"))
listAllFlag := getopt.BoolLong("list-all", 'l', "List all versions of terraform - including beta and rc")
latestPre := getopt.StringLong("latest-pre", 'p', defaultLatest, "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)")
showLatestPre := getopt.StringLong("show-latest-pre", 'P', defaultLatest, "Show latest pre-release implicit version. Ex: tfswitch --show-latest-pre 0.13 prints 0.13.0-rc1 (latest)")
Expand Down Expand Up @@ -309,7 +308,7 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) {
}
}

//retrive file content of regular file
// retrive file content of regular file
func retrieveFileContents(file string) string {
fileContents, err := ioutil.ReadFile(file)
if err != nil {
Expand Down Expand Up @@ -376,8 +375,8 @@ func getParamsTOML(binPath string, dir string) (string, string) {
os.Exit(1) // exit immediately if config file provided but it is unable to read it
}

bin := viper.Get("bin") // read custom binary location
if binPath == lib.ConvertExecutableExt(defaultBin) && bin != nil { // if the bin path is the same as the default binary path and if the custom binary is provided in the toml file (use it)
bin := viper.Get("bin") // read custom binary location
if binPath == lib.ConvertExecutableExt(lib.GetDefaultBin()) && bin != nil { // if the bin path is the same as the default binary path and if the custom binary is provided in the toml file (use it)
binPath = os.ExpandEnv(bin.(string))
}
//fmt.Println(binPath) //uncomment this to debug
Expand Down

0 comments on commit 7c21e4b

Please sign in to comment.