diff --git a/commands.go b/commands.go index eec2f520e..045b783d2 100644 --- a/commands.go +++ b/commands.go @@ -38,6 +38,7 @@ func initCommands(config *Config) { Ui: Ui, RunningInAutomation: inAutomation, + PluginCacheDir: config.PluginCacheDir, } // The command list is included in the terraform -help diff --git a/config.go b/config.go index d9391c3ce..518832e46 100644 --- a/config.go +++ b/config.go @@ -11,6 +11,8 @@ import ( "github.com/hashicorp/terraform/command" ) +const pluginCacheDirEnvVar = "TF_PLUGIN_CACHE_DIR" + // Config is the structure of the configuration for the Terraform CLI. // // This is not the configuration for Terraform itself. That is in the @@ -21,6 +23,10 @@ type Config struct { DisableCheckpoint bool `hcl:"disable_checkpoint"` DisableCheckpointSignature bool `hcl:"disable_checkpoint_signature"` + + // If set, enables local caching of plugins in this directory to + // avoid repeatedly re-downloading over the Internet. + PluginCacheDir string `hcl:"plugin_cache_dir"` } // BuiltinConfig is the built-in defaults for the configuration. These @@ -75,9 +81,31 @@ func LoadConfig(path string) (*Config, error) { result.Provisioners[k] = os.ExpandEnv(v) } + if result.PluginCacheDir != "" { + result.PluginCacheDir = os.ExpandEnv(result.PluginCacheDir) + } + return &result, nil } +// EnvConfig returns a Config populated from environment variables. +// +// Any values specified in this config should override those set in the +// configuration file. +func EnvConfig() *Config { + config := &Config{} + + if envPluginCacheDir := os.Getenv(pluginCacheDirEnvVar); envPluginCacheDir != "" { + // No Expandenv here, because expanding environment variables inside + // an environment variable would be strange and seems unnecessary. + // (User can expand variables into the value while setting it using + // standard shell features.) + config.PluginCacheDir = envPluginCacheDir + } + + return config +} + // Merge merges two configurations and returns a third entirely // new configuration with the two merged. func (c1 *Config) Merge(c2 *Config) *Config { @@ -105,5 +133,10 @@ func (c1 *Config) Merge(c2 *Config) *Config { result.DisableCheckpoint = c1.DisableCheckpoint || c2.DisableCheckpoint result.DisableCheckpointSignature = c1.DisableCheckpointSignature || c2.DisableCheckpointSignature + result.PluginCacheDir = c1.PluginCacheDir + if result.PluginCacheDir == "" { + result.PluginCacheDir = c2.PluginCacheDir + } + return &result } diff --git a/main.go b/main.go index 62e4da603..67c4bfcb6 100644 --- a/main.go +++ b/main.go @@ -138,6 +138,13 @@ func wrappedMain() int { config = *config.Merge(usrcfg) } + if envConfig := EnvConfig(); envConfig != nil { + // envConfig takes precedence + config = *envConfig.Merge(&config) + } + + log.Printf("[DEBUG] CLI Config is %#v", config) + // In tests, Commands may already be set to provide mock commands if Commands == nil { initCommands(&config)