From 68a9e500c67b4c9141cbc90035a5e0ae749f2ab8 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 1/3] 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/common.go | 5 +- lib/defaults.go | 11 +---- lib/files.go | 17 +++++-- lib/install.go | 82 ++++++++++++++------------------- lib/list_versions.go | 12 ++--- lib/param_parsing/parameters.go | 3 ++ lib/symlink.go | 1 - main.go | 17 +++---- www/docs/usage/commandline.md | 39 +++++++++++++--- 10 files changed, 119 insertions(+), 91 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 %v", version) @@ -137,7 +137,7 @@ func versionExist(val interface{}, array interface{}) (exists bool) { s := reflect.ValueOf(array) for i := 0; i < s.Len(); i++ { - if reflect.DeepEqual(val, s.Index(i).Interface()) == true { + if reflect.DeepEqual(val, s.Index(i).Interface()) { exists = true return exists } @@ -156,7 +156,7 @@ func removeDuplicateVersions(elements []string) []string { for _, val := range elements { versionOnly := strings.Trim(val, " *recent") - if encountered[versionOnly] == true { + if encountered[versionOnly] { // Do not add duplicate. } else { // Record this element as an encountered element. diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index e211f922..9c534eac 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -11,6 +11,7 @@ type Params struct { CustomBinaryPath string DefaultVersion string HelpFlag bool + InstallPath string LatestFlag bool LatestPre string LatestStable string @@ -34,6 +35,7 @@ func GetParameters() Params { getopt.StringVarLong(¶ms.CustomBinaryPath, "bin", 'b', "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") getopt.BoolVarLong(¶ms.HelpFlag, "help", 'h', "Displays help message") + getopt.StringVarLong(¶ms.InstallPath, "install", 'i', "Custom install path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username")) getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") @@ -83,6 +85,7 @@ func initParams(params Params) Params { params.CustomBinaryPath = lib.ConvertExecutableExt(lib.GetDefaultBin()) params.DefaultVersion = lib.DefaultLatest params.HelpFlag = false + params.InstallPath = lib.GetHomeDirectory() params.LatestFlag = false params.LatestPre = lib.DefaultLatest params.LatestStable = lib.DefaultLatest diff --git a/lib/symlink.go b/lib/symlink.go index 91bd9052..88d7b99e 100644 --- a/lib/symlink.go +++ b/lib/symlink.go @@ -91,7 +91,6 @@ func CheckSymlink(symlinkPath string) bool { // 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*/ diff --git a/main.go b/main.go index 3d69004c..fd004d23 100644 --- a/main.go +++ b/main.go @@ -19,9 +19,10 @@ package main import ( "fmt" + "os" + lib "github.com/warrensbox/terraform-switcher/lib" "github.com/warrensbox/terraform-switcher/lib/param_parsing" - "os" ) var parameters = param_parsing.GetParameters() @@ -43,32 +44,32 @@ func main() { os.Exit(0) case parameters.ListAllFlag: /* show all terraform version including betas and RCs*/ - lib.InstallOption(true, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallOption(true, parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL) case parameters.LatestPre != "": /* latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ - lib.InstallLatestImplicitVersion(parameters.LatestPre, parameters.CustomBinaryPath, parameters.MirrorURL, true) + lib.InstallLatestImplicitVersion(parameters.LatestPre, parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL, true) case parameters.ShowLatestPre != "": /* show latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest) */ lib.ShowLatestImplicitVersion(parameters.ShowLatestPre, parameters.MirrorURL, true) case parameters.LatestStable != "": /* latest implicit version. Ex: tfswitch --latest-stable 0.13 downloads 0.13.5 (latest) */ - lib.InstallLatestImplicitVersion(parameters.LatestStable, parameters.CustomBinaryPath, parameters.MirrorURL, false) + lib.InstallLatestImplicitVersion(parameters.LatestStable, parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL, false) case parameters.ShowLatestStable != "": /* show latest implicit stable version. Ex: tfswitch --show-latest-stable 0.13 downloads 0.13.5 (latest) */ lib.ShowLatestImplicitVersion(parameters.ShowLatestStable, parameters.MirrorURL, false) case parameters.LatestFlag: /* latest stable version */ - lib.InstallLatestVersion(parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallLatestVersion(parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL) case parameters.ShowLatestFlag: /* show latest stable version */ lib.ShowLatestVersion(parameters.MirrorURL) case parameters.Version != "": - lib.InstallVersion(parameters.Version, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallVersion(parameters.Version, parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL) case parameters.DefaultVersion != "": /* if default version is provided - Pick this instead of going for prompt */ - lib.InstallVersion(parameters.DefaultVersion, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallVersion(parameters.DefaultVersion, parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL) default: // Set list all false - only official release will be displayed - lib.InstallOption(false, parameters.CustomBinaryPath, parameters.MirrorURL) + lib.InstallOption(false, parameters.CustomBinaryPath, parameters.InstallPath, parameters.MirrorURL) } } diff --git a/www/docs/usage/commandline.md b/www/docs/usage/commandline.md index 664a9619..dc6de05f 100644 --- a/www/docs/usage/commandline.md +++ b/www/docs/usage/commandline.md @@ -17,47 +17,74 @@ 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 ``` + ## Install latest version only + 1. Install the latest stable version only. 2. Run `tfswitch -u` or `tfswitch --latest`. 3. Hit **Enter** to install. ## Install latest implicit version for stable releases + 1. Install the latest implicit stable version. 2. Ex: `tfswitch -s 0.13` or `tfswitch --latest-stable 0.13` downloads 0.13.6 (latest) version. 3. Hit **Enter** to install. ## Install latest implicit version for beta, alpha and release candidates(rc) + 1. Install the latest implicit pre-release version. 2. Ex: `tfswitch -p 0.13` or `tfswitch --latest-pre 0.13` downloads 0.13.0-rc1 (latest) version. 3. Hit **Enter** to install. ## Show latest version only + 1. Just show what the latest version is. 2. Run `tfswitch -U` or `tfswitch --show-latest` 3. Hit **Enter** to show. ## Show latest implicit version for stable releases + 1. Show the latest implicit stable version. 2. Ex: `tfswitch -S 0.13` or `tfswitch --show-latest-stable 0.13` shows 0.13.6 (latest) version. 3. Hit **Enter** to show. ## Show latest implicit version for beta, alpha and release candidates(rc) + 1. Show the latest implicit pre-release version. 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. -Ex: `tfswitch --mirror https://example.jfrog.io/artifactory/hashicorp` +## Use custom mirror + +To install from a remote mirror other than the default(https://releases.hashicorp.com/terraform). Use the `-m` or `--mirror` parameter. + +```bash +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` From b460ffc4a040e157d437e572a008916afd1f95f6 Mon Sep 17 00:00:00 2001 From: ArronaxKP <1584972+ArronaxKP@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:22:13 +0100 Subject: [PATCH 2/3] Fix docs and help strings --- lib/defaults.go | 2 +- lib/install.go | 2 +- lib/param_parsing/parameters.go | 2 +- www/docs/usage/ci-cd.md | 4 ++++ www/docs/usage/commandline.md | 5 ++--- www/docs/usage/config-files.md | 27 +++++++++++++++++++-------- www/docs/usage/general.md | 2 +- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/defaults.go b/lib/defaults.go index 1f754ebc..093e0c3b 100644 --- a/lib/defaults.go +++ b/lib/defaults.go @@ -28,7 +28,7 @@ const ( DefaultMirror = "https://releases.hashicorp.com/terraform" DefaultLatest = "" installFile = "terraform" - installDir = ".terraform.versions" + InstallDir = ".terraform.versions" recentFile = "RECENT" tfDarwinArm64StartVersion = "1.0.2" VersionPrefix = "terraform_" diff --git a/lib/install.go b/lib/install.go index 1b1e156e..76daa2d3 100644 --- a/lib/install.go +++ b/lib/install.go @@ -41,7 +41,7 @@ func initialize(binPath string) { // will create the installDir if it does not exist func getInstallLocation(installPath string) string { /* set installation location */ - installLocation = filepath.Join(installPath, installDir) + installLocation = filepath.Join(installPath, InstallDir) /* Create local installation directory if it does not exist */ createDirIfNotExist(installLocation) diff --git a/lib/param_parsing/parameters.go b/lib/param_parsing/parameters.go index 9c534eac..c196d647 100644 --- a/lib/param_parsing/parameters.go +++ b/lib/param_parsing/parameters.go @@ -35,7 +35,7 @@ func GetParameters() Params { getopt.StringVarLong(¶ms.CustomBinaryPath, "bin", 'b', "Custom binary path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username/bin/terraform")) getopt.StringVarLong(¶ms.DefaultVersion, "default", 'd', "Default to this version in case no other versions could be detected. Ex: tfswitch --default 1.2.4") getopt.BoolVarLong(¶ms.HelpFlag, "help", 'h', "Displays help message") - getopt.StringVarLong(¶ms.InstallPath, "install", 'i', "Custom install path. Ex: tfswitch -b "+lib.ConvertExecutableExt("/Users/username")) + getopt.StringVarLong(¶ms.InstallPath, "install", 'i', "Custom install path. Ex: tfswitch -i /Users/username. The binaries will be in the sub installDir directory e.g. /Users/username/"+lib.InstallDir) getopt.BoolVarLong(¶ms.LatestFlag, "latest", 'u', "Get latest stable version") getopt.StringVarLong(¶ms.LatestPre, "latest-pre", 'p', "Latest pre-release implicit version. Ex: tfswitch --latest-pre 0.13 downloads 0.13.0-rc1 (latest)") getopt.StringVarLong(¶ms.LatestStable, "latest-stable", 's', "Latest implicit version based on a constraint. Ex: tfswitch --latest-stable 0.13.0 downloads 0.13.7 and 0.13 downloads 0.15.5 (latest)") diff --git a/www/docs/usage/ci-cd.md b/www/docs/usage/ci-cd.md index ce2423c6..de5ec885 100644 --- a/www/docs/usage/ci-cd.md +++ b/www/docs/usage/ci-cd.md @@ -1,4 +1,5 @@ ## Set a default TF version for CI/CD pipeline + 1. When using a CI/CD pipeline, you may want a default or fallback version to avoid the pipeline from hanging. 2. Ex: `tfswitch -d 1.2.3` or `tfswitch --default 1.2.3` installs version `1.2.3` when no other versions could be detected. [Also, see CICD example](../continuous-integration) @@ -34,12 +35,14 @@ load-tfswitch() { add-zsh-hook chpwd load-tfswitch load-tfswitch ``` + > NOTE: if you see an error like this: `command not found: add-zsh-hook`, then you might be on an older version of zsh (see below), or you simply need to load `add-zsh-hook` by adding this to your `.zshrc`: > ``` > autoload -U add-zsh-hook > ``` ### Older version of zsh + ```sh cd(){ builtin cd "$@"; @@ -49,6 +52,7 @@ cd(){ fi } ``` + ## Automatically switch with fish shell Add the following to the end of your `~/.config/fish/config.fish` file: diff --git a/www/docs/usage/commandline.md b/www/docs/usage/commandline.md index dc6de05f..426ad618 100644 --- a/www/docs/usage/commandline.md +++ b/www/docs/usage/commandline.md @@ -23,8 +23,7 @@ The most recently selected versions are presented at the top of the dropdown. ## 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 @@ -77,7 +76,7 @@ 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` +By default `tfswitch` will download the Terraform binary to the user home directory under this path: `$HOME/.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. diff --git a/www/docs/usage/config-files.md b/www/docs/usage/config-files.md index 9f34ea30..97d909c5 100644 --- a/www/docs/usage/config-files.md +++ b/www/docs/usage/config-files.md @@ -1,13 +1,17 @@ ## Get the version from a subdirectory -While using the file configuration it might be necessary to change the working directory. You can do that with the `--chdir` or `-c` parameter. + +While using the file configuration it might be necessary to change the working directory. You can do that with the `--chdir` or `-c` parameter. + ```bash tfswitch --chdir terraform_dir tfswitch -c terraform_dir ``` ## Use version.tf file + If a .tf file with the terraform constraints is included in the current directory, it should automatically download or switch to that terraform version. For example, the following should automatically switch terraform to the lastest version: + ``` terraform { required_version = ">= 0.12.9" @@ -22,6 +26,7 @@ terraform { ![versiontf](../static/versiontf.gif "Use version.tf") ## Use .tfswitchrc file + ![tfswitchrc](../static/tfswitch-v6.gif) 1. Create a `.tfswitchrc` file containing the desired version @@ -31,23 +36,27 @@ terraform { *Instead of a `.tfswitchrc` file, a `.terraform-version` file may be used for compatibility with [`tfenv`](https://github.com/tfutils/tfenv#terraform-version-file) and other tools which use it* ## Use .tfswitch.toml file (For non-admin - users with limited privilege on their computers) + This is similiar to using a .tfswitchrc file, but you can specify a custom binary path for your terraform installation ![toml1](../static/tfswitch-v7.gif) ![toml2](../static/tfswitch-v8.gif) -1. Create a custom binary path. Ex: `mkdir /Users/warrenveerasingam/bin` (replace warrenveerasingam with your username) -2. Add the path to your PATH. Ex: `export PATH=$PATH:/Users/warrenveerasingam/bin` (add this to your bash profile or zsh profile) -3. Pass -b or --bin parameter with your custom path to install terraform. Ex: `tfswitch -b /Users/warrenveerasingam/bin/terraform 0.10.8 ` +1. Create a custom binary path. Ex: `mkdir $HOME/bin` +2. Add the path to your PATH. Ex: `export PATH=$PATH:$HOME/bin` (add this to your bash profile or zsh profile) +3. Pass -b or --bin parameter with your custom path to install terraform. Ex: `tfswitch -b $HOME/bin/terraform 0.10.8 ` 4. Optionally, you can create a `.tfswitch.toml` file in your terraform directory(current directory) OR in your home directory(~/.tfswitch.toml). The toml file in the current directory has a higher precedence than toml file in the home directory 5. Your `.tfswitch.toml` file should look like this: + ```ruby -bin = "/Users/warrenveerasingam/bin/terraform" +bin = "$HOME/bin/terraform" version = "0.11.3" ``` -4. Run `tfswitch` and it should automatically install the required terraform version in the specified binary path -**NOTE** +6. Run `tfswitch` and it should automatically install the required terraform version in the specified binary path + +**NOTE** + 1. For linux users that do not have write permission to `/usr/local/bin/`, `tfswitch` will attempt to install terraform at `$HOME/bin`. Run `export PATH=$PATH:$HOME/bin` to append bin to PATH 2. For windows host, `tfswitch` need to be run under `Administrator` mode, and `$HOME/.tfswitch.toml` with `bin` must be defined (with a valid path) as minimum, below is an example for `$HOME/.tfswitch.toml` on windows @@ -56,8 +65,10 @@ bin = "C:\\Users\\<%USRNAME%>\\bin\\terraform.exe" ``` ## Use terragrunt.hcl file + If a terragrunt.hcl file with the terraform constraint is included in the current directory, it should automatically download or switch to that terraform version. -For example, the following should automatically switch terraform to the lastest version 0.13: +For example, the following should automatically switch terraform to the lastest version 0.13: + ```ruby terragrunt_version_constraint = ">= 0.26, < 0.27" terraform_version_constraint = ">= 0.13, < 0.14" diff --git a/www/docs/usage/general.md b/www/docs/usage/general.md index 5fdb972e..62a4d239 100644 --- a/www/docs/usage/general.md +++ b/www/docs/usage/general.md @@ -7,5 +7,5 @@ | 3 | .terraform-version | | 4 | Environment variable | -With 1 being the highest precedence and 4 the lowest +With 1 being the highest precedence and 4 the lowest *(If you disagree with this order of precedence, please open an issue)* From 2aaecda96f9cabce413d9f01720f50f4517cc780 Mon Sep 17 00:00:00 2001 From: Hugh Wells Date: Tue, 23 Apr 2024 11:20:43 +0100 Subject: [PATCH 3/3] Update www/docs/usage/commandline.md --- www/docs/usage/commandline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/usage/commandline.md b/www/docs/usage/commandline.md index 426ad618..d2233961 100644 --- a/www/docs/usage/commandline.md +++ b/www/docs/usage/commandline.md @@ -86,4 +86,4 @@ The Terraform binaries will then be placed in the directory `.terraform.versions tfswitch -i /opt/terraform ``` -**NOTE** - The directory passed in `-i`/`--install` must be created before running `tfswtich` +**NOTE** - The directory passed in `-i`/`--install` must be created before running `tfswitch`