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)
-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`