From 7272162f25e22da79200d22809a00b9b029abea6 Mon Sep 17 00:00:00 2001 From: ArronaxKP <1584972+ArronaxKP@users.noreply.github.com> Date: Wed, 17 May 2023 22:28:14 +0100 Subject: [PATCH] Feature: Add flag for install location (optional) Add the ability to pass -i or --install to change the default install location for the Terraform binaries --- README.md | 23 ++++-- lib/install.go | 43 +++++------ lib/symlink.go | 1 - main.go | 131 ++++++++++++++++++---------------- www/docs/usage/commandline.md | 26 +++++-- 5 files changed, 125 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index e79ee487..1f2c5b32 100644 --- a/README.md +++ b/README.md @@ -13,23 +13,28 @@ The installation is minimal and easy. Once installed, simply select the version you require from the dropdown and start using Terraform. ## Documentation + Click [here](https://tfswitch.warrensbox.com) for our extended documentation. ## NOTE + Going forward we will change the version identifier of `tfswitch` to align with the common go package versioning. Please be advised to change any automated implementation you might have that is relying on the `tfswitch` version string. **Old version string:** `0.1.2412` **New version string:** `v1.0.0` Note the `v` that is preceding all version numbers. ## Installation -`tfswitch` is available as a binary and on various package managers (eg. Homebrew). + +`tfswitch` is available as a binary and on various package managers (eg. Homebrew). ## Windows + Download and extract the Windows version of `tfswitch` that is compatible with your system. We are building binaries for 386, amd64, arm6 and arm7 CPU structure. See the [release page](https://github.com/warrensbox/terraform-switcher/releases/latest) for your download. ## Homebrew + For macOS or various Linux distributions, Homebrew offers the simplest installation process. If you do not have homebrew installed, click here. ```ruby @@ -37,6 +42,7 @@ brew install warrensbox/tap/tfswitch ``` ## Linux + Installation for Linux operating systems. ```sh @@ -59,12 +65,12 @@ Alternatively, you can install the binary from the source 0 { @@ -285,18 +288,17 @@ func showLatestImplicitVersion(requestedVersion string, custBinPath, mirrorURL * } // install with provided version as argument -func installVersion(arg string, custBinPath *string, mirrorURL *string) { +func installVersion(arg string, custBinPath *string, installPath *string, mirrorURL *string) { if lib.ValidVersionFormat(arg) { requestedVersion := arg //check to see if the requested version has been downloaded before - installLocation := lib.GetInstallLocation() - installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(installLocation, versionPrefix+requestedVersion)) + installFileVersionPath := lib.ConvertExecutableExt(filepath.Join(*installPath, versionPrefix+requestedVersion)) recentDownloadFile := lib.CheckFileExist(installFileVersionPath) if recentDownloadFile { lib.ChangeSymlink(installFileVersionPath, *custBinPath) logger.Infof("Switched terraform to version %q", requestedVersion) - lib.AddRecent(requestedVersion) //add to recent file for faster lookup + lib.AddRecent(requestedVersion, *installPath) //add to recent file for faster lookup os.Exit(0) } @@ -306,7 +308,7 @@ func installVersion(arg string, custBinPath *string, mirrorURL *string) { exist := lib.VersionExist(requestedVersion, tflist) //check if version exist before downloading it if exist { - lib.Install(requestedVersion, *custBinPath, *mirrorURL) + lib.Install(requestedVersion, *custBinPath, *installPath, *mirrorURL) } else { logger.Fatal("The provided terraform version does not exist.\n Try `tfswitch -l` to see all available versions") os.Exit(1) @@ -357,7 +359,7 @@ func checkTFEnvExist() bool { } /* parses everything in the toml file, return required version and bin path */ -func getParamsTOML(binPath string, dir string) (string, string) { +func getParamsTOML(binPath string, installPath string, dir string) (string, string, string) { path, err := homedir.Dir() if err != nil { @@ -392,7 +394,12 @@ func getParamsTOML(binPath string, dir string) (string, string) { version = "" } - return version.(string), binPath + install := viper.Get("install") //attempt to get the install path if it's provided in the toml + if install != nil { + installPath = os.ExpandEnv(install.(string)) + } + + return version.(string), binPath, installPath } func usageMessage() { @@ -404,11 +411,11 @@ func usageMessage() { /* installOption : displays & installs tf version */ /* listAll = true - all versions including beta and rc will be displayed */ /* listAll = false - only official stable release are displayed */ -func installOption(listAll bool, custBinPath, mirrorURL *string) { - tflist, _ := lib.GetTFList(*mirrorURL, listAll) //get list of versions - recentVersions, _ := lib.GetRecentVersions() //get recent versions from RECENT file - tflist = append(recentVersions, tflist...) //append recent versions to the top of the list - tflist = lib.RemoveDuplicateVersions(tflist) //remove duplicate version +func installOption(listAll bool, custBinPath, installPath, mirrorURL *string) { + tflist, _ := lib.GetTFList(*mirrorURL, listAll) //get list of versions + recentVersions, _ := lib.GetRecentVersions(*installPath) //get recent versions from RECENT file + tflist = append(recentVersions, tflist...) //append recent versions to the top of the list + tflist = lib.RemoveDuplicateVersions(tflist) //remove duplicate version if len(tflist) == 0 { logger.Fatalf("Terraform version list is empty: %s", *mirrorURL) @@ -429,32 +436,32 @@ func installOption(listAll bool, custBinPath, mirrorURL *string) { os.Exit(1) } - lib.Install(tfversion, *custBinPath, *mirrorURL) + lib.Install(tfversion, *custBinPath, *installPath, *mirrorURL) os.Exit(0) } // install when tf file is provided -func installTFProvidedModule(dir string, custBinPath, mirrorURL *string) { +func installTFProvidedModule(dir string, custBinPath, installPath, mirrorURL *string) { logger.Infof("Reading required version from terraform module at %q", dir) module, _ := tfconfig.LoadModule(dir) tfconstraint := module.RequiredCore[0] //we skip duplicated definitions and use only first one - installFromConstraint(&tfconstraint, custBinPath, mirrorURL) + installFromConstraint(&tfconstraint, custBinPath, installPath, mirrorURL) } // install using a version constraint -func installFromConstraint(tfconstraint *string, custBinPath, mirrorURL *string) { +func installFromConstraint(tfconstraint *string, custBinPath, installPath, mirrorURL *string) { tfversion, err := lib.GetSemver(tfconstraint, mirrorURL) if err == nil { - lib.Install(tfversion, *custBinPath, *mirrorURL) + lib.Install(tfversion, *custBinPath, *installPath, *mirrorURL) } logger.Fatalf("No version found to match constraint: %v.\n Follow the README.md instructions for setup: https://github.com/warrensbox/terraform-switcher/blob/master/README.md", err) os.Exit(1) } // Install using version constraint from terragrunt file -func installTGHclFile(tgFile *string, custBinPath, mirrorURL *string) { - logger.Infof("Terragrunt file found: %q", *tgFile) +func installTGHclFile(tgFile *string, custBinPath, installPath, mirrorURL *string) { + fmt.Printf("Terragrunt file found: %s\n", *tgFile) parser := hclparse.NewParser() file, diags := parser.ParseHCLFile(*tgFile) //use hcl parser to parse HCL file if diags.HasErrors() { @@ -463,7 +470,7 @@ func installTGHclFile(tgFile *string, custBinPath, mirrorURL *string) { } var version terragruntVersionConstraints gohcl.DecodeBody(file.Body, nil, &version) - installFromConstraint(&version.TerraformVersionConstraint, custBinPath, mirrorURL) + installFromConstraint(&version.TerraformVersionConstraint, custBinPath, installPath, mirrorURL) } type terragruntVersionConstraints struct { diff --git a/www/docs/usage/commandline.md b/www/docs/usage/commandline.md index 664a9619..fc09c722 100644 --- a/www/docs/usage/commandline.md +++ b/www/docs/usage/commandline.md @@ -17,13 +17,13 @@ The most recently selected versions are presented at the top of the dropdown. ## See all versions including beta, alpha and release candidates(rc) drawing -1. Display all versions including beta, alpha and release candidates(rc). +1. Display all versions including beta, alpha and release candidates(rc). 2. For example, `tfswitch -l` or `tfswitch --list-all` to see all versions. 3. Hit **Enter** to select the desired version. ## Use environment variables -You can also set the `TF_VERSION` environment variable to your desired terraform version. -For example: +You can also set the `TF_VERSION` environment variable to your desired terraform version. +For example: ```bash export TF_VERSION=0.14.4 tfswitch #will automatically switch to terraform version 0.14.4 @@ -58,6 +58,22 @@ tfswitch #will automatically switch to terraform version 0.14.4 2. Ex: `tfswitch -P 0.13` or `tfswitch --show-latest-pre 0.13` shows 0.13.0-rc1 (latest) version. 3. Hit **Enter** to show. -## Use custom mirror -To install from a remote mirror other than the default(https://releases.hashicorp.com/terraform). Use the `-m` or `--mirror` parameter. +## Use custom mirror +To install from a remote mirror other than the default(https://releases.hashicorp.com/terraform). Use the `-m` or `--mirror` parameter. Ex: `tfswitch --mirror https://example.jfrog.io/artifactory/hashicorp` + +## Install to non-default location + +By default `tfswitch` will download the Terraform binary to the user home directory under this path: `/Users/warrenveerasingam/.terraform.versions` + +If you want to install the binaries outside of the home directory then you can provide the `-i` or `--install` to install Terraform binaries to a non-standard path. Useful if you want to install versions of Terraform that can be shared with multiple users. + +The Terraform binaries will then be placed in the directory `.terraform.versions` under the custom install path e.g. `/opt/terraform/.terraform.versions` + +```bash +tfswitch -i /opt/terraform/ +``` + +**NOTE** + +* The directory passed in `-i`/`--install` must be created before running `tfswtich`