mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Previously the Go toolchain had no explicit support for "tools" and so we used the typical Go community workaround of adding "tools.go" files (two, for some reason) that existed only to trick the Go toolchain into considering the tools as dependencies we could track in go.mod. Go 1.24 introduced explicit support for tracking tools as part of go.mod, and the ability to run those using "go tool" instead of "go run", and so this commit switches us over to using that strategy for everything we were previously managing in tools.go. There are some intentional exceptions here: - The protobuf-compile script can't use "go tool" or "go run" because the tools in question are run only indirectly through protoc. However, we do still use the "tool" directive in go.mod to tell the Go toolchain that we depend on those tools, so that it'll track which versions we are currently using as part of go.mod. - Our golangci-lint Makefile target uses "go run" to run a specific version of golangci-lint. We _intentionally_ don't consider that tool to be a direct dependency of OpenTofu because it has a lot of indirect dependencies that would pollute our go.mod file. Therefore that continues to use "go run" after this commit. - Both of our tools.go files previously referred to github.com/nishanths/exhaustive , but nothing actually appears to be using that tool in the current OpenTofu tree, so it's no longer a dependency after this commit. All of the dependencies we have _only_ for tools are now classified as "indirect" in the go.mod file. This is the default behavior of the Go toolchain and appears to be motivated by making it clearer that these modules do not contribute anything to the runtime behavior of OpenTofu. This also corrected a historical oddity in our go.mod where for some reason the "indirect" dependencies had been split across two different "require" directives; they are now all grouped together in a single directive. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
112 lines
4.1 KiB
Go
112 lines
4.1 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package cloud
|
|
|
|
import (
|
|
"github.com/opentofu/opentofu/internal/configs"
|
|
legacy "github.com/opentofu/opentofu/internal/legacy/tofu"
|
|
)
|
|
|
|
// 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 tool 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 "tofu 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
|
|
}
|
|
}
|