core: allow overriding environment name via env var
This allows you to run multiple concurrent terraform operations against different environments from the same source directory. Fixes #14447. Also removes some dead code which appears to do the same thing as the function I modified.
This commit is contained in:
parent
73139ba6aa
commit
c25d848ffb
|
@ -8,7 +8,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
|
@ -391,22 +390,3 @@ func (b *Local) stateEnvDir() string {
|
||||||
|
|
||||||
return DefaultEnvDir
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -96,5 +96,28 @@ to another environment and try again.
|
||||||
envInvalidName = `
|
envInvalidName = `
|
||||||
The environment name %q is not allowed. The name must contain only URL safe
|
The environment name %q is not allowed. The name must contain only URL safe
|
||||||
characters, and no path separators.
|
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.
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
|
@ -48,7 +48,7 @@ func (c *EnvListCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
env := c.Env()
|
env, isOverridden := c.EnvOverridden()
|
||||||
|
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
for _, s := range states {
|
for _, s := range states {
|
||||||
|
@ -61,6 +61,11 @@ func (c *EnvListCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Ui.Output(out.String())
|
c.Ui.Output(out.String())
|
||||||
|
|
||||||
|
if isOverridden {
|
||||||
|
c.Ui.Output(envIsOverriddenNote)
|
||||||
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,13 @@ func (c *EnvNewCommand) Run(args []string) int {
|
||||||
return 1
|
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:])
|
configPath, err := ModulePath(args[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(err.Error())
|
c.Ui.Error(err.Error())
|
||||||
|
|
|
@ -34,6 +34,11 @@ func (c *EnvSelectCommand) Run(args []string) int {
|
||||||
conf, err := c.Config(configPath)
|
conf, err := c.Config(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +64,7 @@ func (c *EnvSelectCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == c.Env() {
|
if name == current {
|
||||||
// already using this env
|
// already using this env
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,9 +454,28 @@ func (m *Meta) outputShadowError(err error, output bool) bool {
|
||||||
return true
|
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
|
// Env returns the name of the currently configured environment, corresponding
|
||||||
// to the desired named state.
|
// to the desired named state.
|
||||||
func (m *Meta) Env() string {
|
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
|
dataDir := m.dataDir
|
||||||
if m.dataDir == "" {
|
if m.dataDir == "" {
|
||||||
dataDir = DefaultDataDir
|
dataDir = DefaultDataDir
|
||||||
|
@ -473,7 +492,7 @@ func (m *Meta) Env() string {
|
||||||
log.Printf("[ERROR] failed to read current environment: %s", err)
|
log.Printf("[ERROR] failed to read current environment: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return current
|
return current, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEnv saves the named environment to the local filesystem.
|
// SetEnv saves the named environment to the local filesystem.
|
||||||
|
|
Loading…
Reference in New Issue