diff --git a/backend/local/backend.go b/backend/local/backend.go index 7c715d67a..f5eb4ed61 100644 --- a/backend/local/backend.go +++ b/backend/local/backend.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "sort" - "strings" "sync" "github.com/hashicorp/terraform/backend" @@ -391,22 +390,3 @@ func (b *Local) stateEnvDir() string { return DefaultEnvDir } - -// currentStateName returns the name of the current named state as set in the -// configuration files. -// If there are no configured environments, currentStateName returns "default" -func (b *Local) currentStateName() (string, error) { - contents, err := ioutil.ReadFile(filepath.Join(DefaultDataDir, DefaultEnvFile)) - if os.IsNotExist(err) { - return backend.DefaultStateName, nil - } - if err != nil { - return "", err - } - - if fromFile := strings.TrimSpace(string(contents)); fromFile != "" { - return fromFile, nil - } - - return backend.DefaultStateName, nil -} diff --git a/command/env_command.go b/command/env_command.go index f29c9456f..f32e1cb20 100644 --- a/command/env_command.go +++ b/command/env_command.go @@ -96,5 +96,28 @@ to another environment and try again. envInvalidName = ` The environment name %q is not allowed. The name must contain only URL safe characters, and no path separators. +` + + envIsOverriddenNote = ` + +The active environment is being overridden using the TF_ENVIRONMENT environment +variable. +` + + envIsOverriddenSelectError = ` +The environment is currently overridden using the TF_ENVIRONMENT environment +variable. + +To select a new environment, either update this environment variable or unset +it and then run this command again. +` + + envIsOverriddenNewError = ` +The environment is currently overridden using the TF_ENVIRONMENT environment +variable. You cannot create a different environment when using this setting. + +To create a new environment, either unset this environment variable or update it +to match the environment name you are trying to create, and then run this command +again. ` ) diff --git a/command/env_list.go b/command/env_list.go index 56d448d29..793afe9ba 100644 --- a/command/env_list.go +++ b/command/env_list.go @@ -48,7 +48,7 @@ func (c *EnvListCommand) Run(args []string) int { return 1 } - env := c.Env() + env, isOverridden := c.EnvOverridden() var out bytes.Buffer for _, s := range states { @@ -61,6 +61,11 @@ func (c *EnvListCommand) Run(args []string) int { } c.Ui.Output(out.String()) + + if isOverridden { + c.Ui.Output(envIsOverriddenNote) + } + return 0 } diff --git a/command/env_new.go b/command/env_new.go index 1b2c13a67..6c6f9cdd8 100644 --- a/command/env_new.go +++ b/command/env_new.go @@ -40,6 +40,13 @@ func (c *EnvNewCommand) Run(args []string) int { return 1 } + // You can't ask to create an environment when you're overriding the + // environment name to be something different. + if current, isOverridden := c.EnvOverridden(); current != newEnv && isOverridden { + c.Ui.Error(envIsOverriddenNewError) + return 1 + } + configPath, err := ModulePath(args[1:]) if err != nil { c.Ui.Error(err.Error()) diff --git a/command/env_select.go b/command/env_select.go index d65660fb8..c2f69dc18 100644 --- a/command/env_select.go +++ b/command/env_select.go @@ -34,6 +34,11 @@ func (c *EnvSelectCommand) Run(args []string) int { conf, err := c.Config(configPath) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err)) + } + + current, isOverridden := c.EnvOverridden() + if isOverridden { + c.Ui.Error(envIsOverriddenSelectError) return 1 } @@ -59,7 +64,7 @@ func (c *EnvSelectCommand) Run(args []string) int { return 1 } - if name == c.Env() { + if name == current { // already using this env return 0 } diff --git a/command/meta.go b/command/meta.go index dc581d4a3..acf37e516 100644 --- a/command/meta.go +++ b/command/meta.go @@ -454,9 +454,28 @@ func (m *Meta) outputShadowError(err error, output bool) bool { return true } +// EnvironmentNameEnvVar is the name of the environment variable (ie, the POSIX +// feature) that can be used to set the name of the Terraform environment +// (overriding the environment chosen by `terraform env select`). Note that +// this environment variable is ignored by `terraform env new` and `terraform +// env delete`. +const EnvironmentNameEnvVar = "TF_ENVIRONMENT" + // Env returns the name of the currently configured environment, corresponding // to the desired named state. func (m *Meta) Env() string { + current, _ := m.EnvOverridden() + return current +} + +// EnvOverridden returns the name of the currently configured environment, +// corresponding to the desired named state, as well as a bool saying whether +// this was set via the TF_ENVIRONMENT environment variable. +func (m *Meta) EnvOverridden() (string, bool) { + if envVar := os.Getenv(EnvironmentNameEnvVar); envVar != "" { + return envVar, true + } + dataDir := m.dataDir if m.dataDir == "" { dataDir = DefaultDataDir @@ -473,7 +492,7 @@ func (m *Meta) Env() string { log.Printf("[ERROR] failed to read current environment: %s", err) } - return current + return current, false } // SetEnv saves the named environment to the local filesystem.