diff --git a/internal/command/cliconfig/config_unix.go b/internal/command/cliconfig/config_unix.go index 6dc1450b2364..9399eefb74cc 100644 --- a/internal/command/cliconfig/config_unix.go +++ b/internal/command/cliconfig/config_unix.go @@ -11,7 +11,12 @@ import ( ) func configFile() (string, error) { - dir, err := homeDir() + tfHomeDir, err := tfHomeDir() + if err != nil { + return filepath.Join(tfHomeDir, "terraformrc"), nil + } + + dir, err := userHomeDir() if err != nil { return "", err } @@ -20,7 +25,12 @@ func configFile() (string, error) { } func configDir() (string, error) { - dir, err := homeDir() + tfHomeDir, err := tfHomeDir() + if err != nil { + return tfHomeDir, nil + } + + dir, err := userHomeDir() if err != nil { return "", err } @@ -28,10 +38,17 @@ func configDir() (string, error) { return filepath.Join(dir, ".terraform.d"), nil } -func homeDir() (string, error) { +func tfHomeDir() (string, error) { + if tfHome := os.Getenv("TF_HOME_DIR"); tfHome != "" { + return tfHome, nil + } + return "", errors.New("TF_HOME_DIR is not set") +} + +func userHomeDir() (string, error) { // First prefer the HOME environmental variable if home := os.Getenv("HOME"); home != "" { - // FIXME: homeDir gets called from globalPluginDirs during init, before + // FIXME: userHomeDir gets called from globalPluginDirs during init, before // the logging is set up. We should move meta initializtion outside of // init, but in the meantime we just need to silence this output. //log.Printf("[DEBUG] Detected home directory from env var: %s", home) diff --git a/internal/command/cliconfig/config_windows.go b/internal/command/cliconfig/config_windows.go index 8f232fd5b65e..0fb58578beb2 100644 --- a/internal/command/cliconfig/config_windows.go +++ b/internal/command/cliconfig/config_windows.go @@ -17,7 +17,7 @@ var ( const CSIDL_APPDATA = 26 func configFile() (string, error) { - dir, err := homeDir() + dir, err := userHomeDir() if err != nil { return "", err } @@ -26,7 +26,7 @@ func configFile() (string, error) { } func configDir() (string, error) { - dir, err := homeDir() + dir, err := userHomeDir() if err != nil { return "", err } @@ -34,7 +34,7 @@ func configDir() (string, error) { return filepath.Join(dir, "terraform.d"), nil } -func homeDir() (string, error) { +func userHomeDir() (string, error) { b := make([]uint16, syscall.MAX_PATH) // See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx diff --git a/plugins.go b/plugins.go index be576e81ac51..263d51e22b14 100644 --- a/plugins.go +++ b/plugins.go @@ -17,7 +17,7 @@ import ( // older versions where both satisfy the provider version constraints. func globalPluginDirs() []string { var ret []string - // Look in ~/.terraform.d/plugins/ , or its equivalent on non-UNIX + // Look in "${TF_HOME_DIR:-~/.terraform.d}/plugins/" , or its equivalent on non-UNIX dir, err := cliconfig.ConfigDir() if err != nil { log.Printf("[ERROR] Error finding global config directory: %s", err) diff --git a/provider_source.go b/provider_source.go index f27ca54b2a79..1f0490152e5b 100644 --- a/provider_source.go +++ b/provider_source.go @@ -93,7 +93,7 @@ func implicitProviderSource(services *disco.Disco) getproviders.Source { // way to include them in bundles uploaded to Terraform Cloud, where // there has historically otherwise been no way to use custom providers. // - The "plugins" subdirectory of the CLI config search directory. - // (thats ~/.terraform.d/plugins on Unix systems, equivalents elsewhere) + // (thats "${TF_HOME_DIR:-~/.terraform.d}/plugins" on Unix systems, equivalents elsewhere) // - The "plugins" subdirectory of any platform-specific search paths, // following e.g. the XDG base directory specification on Unix systems, // Apple's guidelines on OS X, and "known folders" on Windows. diff --git a/website/docs/cli/config/config-file.mdx b/website/docs/cli/config/config-file.mdx index accdc465fc13..9bae43d69975 100644 --- a/website/docs/cli/config/config-file.mdx +++ b/website/docs/cli/config/config-file.mdx @@ -42,7 +42,7 @@ general syntax; see the following section for information on the meaning of each of these settings: ```hcl -plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" +plugin_cache_dir = "${TF_HOME_DIR:-$HOME/.terraform.d}/plugin-cache" disable_checkpoint = true ``` @@ -298,10 +298,10 @@ The set of directories Terraform can select as filesystem mirrors depends on the operating system where you are running Terraform: * **Windows:** `%APPDATA%/terraform.d/plugins` and `%APPDATA%/HashiCorp/Terraform/plugins` -* **Mac OS X:** `$HOME/.terraform.d/plugins`, +* **Mac OS X:** `${TF_HOME_DIR:-$HOME/.terraform.d}/plugins`, `~/Library/Application Support/io.terraform/plugins`, and `/Library/Application Support/io.terraform/plugins` -* **Linux and other Unix-like systems**:`$HOME/.terraform.d/plugins` and +* **Linux and other Unix-like systems**:`${TF_HOME_DIR:-$HOME/.terraform.d}/plugins` and `terraform/plugins` located within a valid [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) data directory such as `$XDG_DATA_HOME/terraform/plugins`. @@ -343,7 +343,7 @@ To enable the plugin cache, use the `plugin_cache_dir` setting in the CLI configuration file. For example: ```hcl -plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" +plugin_cache_dir = "${TF_HOME_DIR:-$HOME/.terraform.d}/plugin-cache" ``` This directory must already exist before Terraform will cache plugins; @@ -359,7 +359,7 @@ variable can be used to enable caching or to override an existing cache directory within a particular shell session: ```bash -export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" +export TF_PLUGIN_CACHE_DIR="${TF_HOME_DIR:-$HOME/.terraform.d}/plugin-cache" ``` When a plugin cache directory is enabled, the `terraform init` command will diff --git a/website/docs/language/resources/provisioners/syntax.mdx b/website/docs/language/resources/provisioners/syntax.mdx index c05221f1143a..14679da9b3b7 100644 --- a/website/docs/language/resources/provisioners/syntax.mdx +++ b/website/docs/language/resources/provisioners/syntax.mdx @@ -166,7 +166,7 @@ provisioners must connect to the remote system using SSH or WinRM. You must include [a `connection` block](/terraform/language/resources/provisioners/connection) so that Terraform knows how to communicate with the server. Terraform includes several built-in provisioners. You can also use third-party provisioners as plugins, by placing them -in `%APPDATA%\terraform.d\plugins`, `~/.terraform.d/plugins`, or the same +in `%APPDATA%\terraform.d\plugins`, `${TF_HOME_DIR:-~/.terraform.d}/plugins`, or the same directory where the Terraform binary is installed. However, we do not recommend using any provisioners except the built-in `file`, `local-exec`, and `remote-exec` provisioners.