| package cloud |
| |
| import ( |
| "github.com/hashicorp/terraform/internal/configs" |
| legacy "github.com/hashicorp/terraform/internal/legacy/terraform" |
| ) |
| |
| // Most of the logic for migrating into and out of "cloud mode" actually lives |
| // in the "command" package as part of the general backend init mechanisms, |
| // but we have some cloud-specific helper functionality here. |
| |
| // ConfigChangeMode is a rough way to think about different situations that |
| // our backend change and state migration codepaths need to distinguish in |
| // the context of Cloud integration mode. |
| type ConfigChangeMode rune |
| |
| //go:generate go run golang.org/x/tools/cmd/stringer -type ConfigChangeMode |
| |
| const ( |
| // ConfigMigrationIn represents when the configuration calls for using |
| // Cloud mode but the working directory state disagrees. |
| ConfigMigrationIn ConfigChangeMode = '↘' |
| |
| // ConfigMigrationOut represents when the working directory state calls |
| // for using Cloud mode but the working directory state disagrees. |
| ConfigMigrationOut ConfigChangeMode = '↖' |
| |
| // ConfigChangeInPlace represents when both the working directory state |
| // and the config call for using Cloud mode, and so there might be |
| // (but won't necessarily be) cloud settings changing, but we don't |
| // need to do any actual migration. |
| ConfigChangeInPlace ConfigChangeMode = '↻' |
| |
| // ConfigChangeIrrelevant represents when the config and working directory |
| // state disagree but neither calls for using Cloud mode, and so the |
| // Cloud integration is not involved in dealing with this. |
| ConfigChangeIrrelevant ConfigChangeMode = '🤷' |
| ) |
| |
| // DetectConfigChangeType encapsulates the fiddly logic for deciding what kind |
| // of Cloud configuration change we seem to be making, based on the existing |
| // working directory state (if any) and the current configuration. |
| // |
| // This is a pretty specialized sort of thing focused on finicky details of |
| // the way we currently model working directory settings and config, so its |
| // signature probably won't survive any non-trivial refactoring of how |
| // the CLI layer thinks about backends/state storage. |
| func DetectConfigChangeType(wdState *legacy.BackendState, config *configs.Backend, haveLocalStates bool) ConfigChangeMode { |
| // Although externally the cloud integration isn't really a "backend", |
| // internally we treat it a bit like one just to preserve all of our |
| // existing interfaces that assume backends. "cloud" is the placeholder |
| // name we use for it, even though that isn't a backend that's actually |
| // available for selection in the usual way. |
| wdIsCloud := wdState != nil && wdState.Type == "cloud" |
| configIsCloud := config != nil && config.Type == "cloud" |
| |
| // "uninit" here means that the working directory is totally uninitialized, |
| // even taking into account the possibility of implied local state that |
| // therefore doesn't typically require explicit "terraform init". |
| wdIsUninit := wdState == nil && !haveLocalStates |
| |
| switch { |
| case configIsCloud: |
| switch { |
| case wdIsCloud || wdIsUninit: |
| // If config has cloud and the working directory is completely |
| // uninitialized then we assume we're doing the initial activation |
| // of this working directory for an already-migrated-to-cloud |
| // remote state. |
| return ConfigChangeInPlace |
| default: |
| // Otherwise, we seem to be migrating into cloud mode from a backend. |
| return ConfigMigrationIn |
| } |
| default: |
| switch { |
| case wdIsCloud: |
| // If working directory is already cloud but config isn't, we're |
| // migrating away from cloud to a backend. |
| return ConfigMigrationOut |
| default: |
| // Otherwise, this situation seems to be something unrelated to |
| // cloud mode and so outside of our scope here. |
| return ConfigChangeIrrelevant |
| } |
| } |
| |
| } |
| |
| func (m ConfigChangeMode) InvolvesCloud() bool { |
| switch m { |
| case ConfigMigrationIn, ConfigMigrationOut, ConfigChangeInPlace: |
| return true |
| default: |
| return false |
| } |
| } |
| |
| func (m ConfigChangeMode) IsCloudMigration() bool { |
| switch m { |
| case ConfigMigrationIn, ConfigMigrationOut: |
| return true |
| default: |
| return false |
| } |
| } |