diff --git a/lib/install.go b/lib/install.go index e71741c..14e6a8e 100644 --- a/lib/install.go +++ b/lib/install.go @@ -185,7 +185,7 @@ func Install(tgversion string, usrBinPath string, mirrorURL string) string { /* check if selected version already downloaded */ installFileVersionPath := ConvertExecutableExt(filepath.Join(installLocation, installVersion+tgversion)) - fileExist := CheckFileExist(installLocation + installVersion + tgversion) + fileExist := CheckFileExist(installFileVersionPath) /* if selected version already exist, */ if fileExist { @@ -212,8 +212,11 @@ func Install(tgversion string, usrBinPath string, mirrorURL string) string { /* if selected version already exist, */ /* proceed to download it from the hashicorp release page */ + fmt.Println("MirrorURL: " + mirrorURL) url := mirrorURL + "v" + tgversion + "/" + "terragrunt" + "_" + goos + "_" + goarch - + if goos == "windows" { + url = url + ".exe" + } downloadedFile, errDownload := DownloadFromURL(installLocation, url) /* If unable to download file from url, exit(1) immediately */ @@ -259,10 +262,8 @@ func InstallableBinLocation(userBinPath string) string { if binPathExist == true { //if bin path exist - check if we can write to to it - binPathWritable := false //assume bin path is not writable - if runtime.GOOS != "windows" { - binPathWritable = CheckDirWritable(binDir) //check if is writable on ( only works on LINUX) - } + binPathWritable := false //assume bin path is not writable + binPathWritable = CheckDirWritable(binDir) //check if is writable on ( only works on LINUX) // IF: "/usr/local/bin" or `custom bin path` provided by user is non-writable, (binPathWritable == false), we will attempt to install terragrunt at the ~/bin location. See ELSE if binPathWritable == false { diff --git a/lib/symlink.go b/lib/symlink.go index 5598181..40149f2 100644 --- a/lib/symlink.go +++ b/lib/symlink.go @@ -1,3 +1,5 @@ +//go:build !windows + package lib import ( diff --git a/lib/symlink_windows.go b/lib/symlink_windows.go new file mode 100644 index 0000000..4627a4e --- /dev/null +++ b/lib/symlink_windows.go @@ -0,0 +1,104 @@ +package lib + +import ( + "io" + "log" + "os" +) + +func Copy(src, dst string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + return out.Close() +} + +//CreateSymlink : create symlink +func CreateSymlink(cwd string, dir string) { + + err := Copy(cwd, dir) + if err != nil { + log.Fatalf(` + Unable to create new symlink. + Maybe symlink already exist. Try removing existing symlink manually. + Try running "unlink %s" to remove existing symlink. + If error persist, you may not have the permission to create a symlink at %s. + Error: %s + `, dir, dir, err) + os.Exit(1) + } +} + +//RemoveSymlink : remove symlink +func RemoveSymlink(symlinkPath string) { + + _, err := os.Lstat(symlinkPath) + if err != nil { + log.Fatalf(` + Unable to stat symlink. + Maybe symlink already exist. Try removing existing symlink manually. + Try running "unlink %s" to remove existing symlink. + If error persist, you may not have the permission to create a symlink at %s. + Error: %s + `, symlinkPath, symlinkPath, err) + os.Exit(1) + } else { + errRemove := os.Remove(symlinkPath) + + if errRemove != nil { + log.Fatalf(` + Unable to remove symlink. + Maybe symlink already exist. Try removing existing symlink manually. + Try running "unlink %s" to remove existing symlink. + If error persist, you may not have the permission to create a symlink at %s. + Error: %s + `, symlinkPath, symlinkPath, errRemove) + os.Exit(1) + } + } +} + +// CheckSymlink : check file is symlink +func CheckSymlink(symlinkPath string) bool { + + fi, err := os.Lstat(symlinkPath) + if err != nil { + return false + } + + if fi.Mode()&os.ModeSymlink != 0 { + return true + } + + return false +} + +// ChangeSymlink : move symlink to existing binary +func ChangeSymlink(binVersionPath string, binPath string) { + + //installLocation = GetInstallLocation() //get installation location - this is where we will put our terraform binary file + binPath = InstallableBinLocation(binPath) + + /* remove current symlink if exist*/ + symlinkExist := CheckSymlink(binPath) + if symlinkExist { + RemoveSymlink(binPath) + } + + /* set symlink to desired version */ + CreateSymlink(binVersionPath, binPath) + +} diff --git a/main.go b/main.go index 9413610..93cf509 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ import ( "log" "os" "path/filepath" + "runtime" "strings" "github.com/hashicorp/hcl2/gohcl" @@ -32,7 +33,6 @@ import ( const ( terragruntURL = "https://github.com/gruntwork-io/terragrunt/releases/download/" - defaultBin = "/usr/local/bin/terragrunt" //default bin installation dir rcFilename = ".tgswitchrc" tgvFilename = ".terragrunt-version" versionPrefix = "terragrunt_" @@ -41,6 +41,8 @@ const ( tgHclFilename = "terragrunt.hcl" ) +var defaultBin = getOSDefaultBin() + var version = "0.5.0\n" func main() { @@ -118,7 +120,7 @@ func main() { installVersion(tgversion, &binPath) /* if terragrunt.hcl file found (IN ADDITION TO A TOML FILE) */ case lib.FileExists(TGHACLFile) && checkVersionDefinedHCL(&TGHACLFile) && len(args) == 0: - installTGHclFile(&TGHACLFile, binPath, proxyUrl) + installTGHclFile(&TGHACLFile, binPath, terragruntURL) /* if terragrunt Version environment variable is set (IN ADDITION TO A TOML FILE)*/ case checkTGEnvExist() && len(args) == 0 && version == "": tgversion := os.Getenv("TG_VERSION") @@ -158,7 +160,7 @@ func main() { installVersion(tgversion, custBinPath) /* if terragrunt.hcl file found */ case lib.FileExists(TGHACLFile) && checkVersionDefinedHCL(&TGHACLFile) && len(args) == 0: - installTGHclFile(&TGHACLFile, *custBinPath, proxyUrl) + installTGHclFile(&TGHACLFile, *custBinPath, terragruntURL) /* if terragrunt Version environment variable is set*/ case checkTGEnvExist() && len(args) == 0: tgversion := os.Getenv("TG_VERSION") @@ -276,7 +278,7 @@ func checkTGEnvExist() bool { // install using a version constraint func installFromConstraint(tgconstraint *string, custBinPath, mirrorURL string) { - tgversion, err := lib.GetSemver(tgconstraint, mirrorURL) + tgversion, err := lib.GetSemver(tgconstraint, proxyUrl) if err == nil { lib.Install(tgversion, custBinPath, mirrorURL) } @@ -329,3 +331,17 @@ func checkVersionDefinedHCL(tgFile *string) bool { type terragruntVersionConstraints struct { TerragruntVersionConstraint string `hcl:"terragrunt_version_constraint"` } + +func getOSDefaultBin() string { + // + const goos = runtime.GOOS + var homedir = lib.GetHomeDirectory() + + if goos == "darwin" { + return homedir + "/bin/terragrunt" + } + if goos == "windows" { + return homedir + "/bin/terragrunt.exe" + } + return "/usr/local/bin/terragrunt" +}