mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Merge pull request #16920 from hashicorp/jbardin/init-future-state
check state version during init
This commit is contained in:
commit
504ea578ee
@ -180,7 +180,6 @@ func (c *InitCommand) Run(args []string) int {
|
||||
"Error downloading modules: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we're requesting backend configuration or looking for required
|
||||
@ -280,6 +279,12 @@ func (c *InitCommand) getProviders(path string, state *terraform.State, upgrade
|
||||
return diags.Err()
|
||||
}
|
||||
|
||||
if err := terraform.CheckStateVersion(state); err != nil {
|
||||
diags = diags.Append(err)
|
||||
c.showDiagnostics(diags)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := terraform.CheckRequiredVersion(mod); err != nil {
|
||||
diags = diags.Append(err)
|
||||
c.showDiagnostics(diags)
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/backend/local"
|
||||
"github.com/hashicorp/terraform/helper/copy"
|
||||
"github.com/hashicorp/terraform/plugin/discovery"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
@ -583,12 +584,12 @@ func TestInit_getProvider(t *testing.T) {
|
||||
defer os.RemoveAll(td)
|
||||
defer testChdir(t, td)()
|
||||
|
||||
overrides := metaOverridesForProvider(testProvider())
|
||||
ui := new(cli.MockUi)
|
||||
m := Meta{
|
||||
testingOverrides: metaOverridesForProvider(testProvider()),
|
||||
testingOverrides: overrides,
|
||||
Ui: ui,
|
||||
}
|
||||
|
||||
installer := &mockProviderInstaller{
|
||||
Providers: map[string][]string{
|
||||
// looking for an exact version
|
||||
@ -631,6 +632,36 @@ func TestInit_getProvider(t *testing.T) {
|
||||
if _, err := os.Stat(betweenPath); os.IsNotExist(err) {
|
||||
t.Fatal("provider 'between' not downloaded")
|
||||
}
|
||||
|
||||
t.Run("future-state", func(t *testing.T) {
|
||||
// getting providers should fail if a state from a newer version of
|
||||
// terraform exists, since InitCommand.getProviders needs to inspect that
|
||||
// state.
|
||||
s := terraform.NewState()
|
||||
s.TFVersion = "100.1.0"
|
||||
local := &state.LocalState{
|
||||
Path: local.DefaultStateFilename,
|
||||
}
|
||||
if err := local.WriteState(s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
m.Ui = ui
|
||||
c := &InitCommand{
|
||||
Meta: m,
|
||||
providerInstaller: installer,
|
||||
}
|
||||
|
||||
if code := c.Run(nil); code == 0 {
|
||||
t.Fatal("expected error, got:", ui.OutputWriter)
|
||||
}
|
||||
|
||||
errMsg := ui.ErrorWriter.String()
|
||||
if !strings.Contains(errMsg, "future Terraform version") {
|
||||
t.Fatal("unexpected error:", errMsg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// make sure we can locate providers in various paths
|
||||
|
@ -145,13 +145,8 @@ func NewContext(opts *ContextOpts) (*Context, error) {
|
||||
|
||||
// If our state is from the future, then error. Callers can avoid
|
||||
// this error by explicitly setting `StateFutureAllowed`.
|
||||
if !opts.StateFutureAllowed && state.FromFutureTerraform() {
|
||||
return nil, fmt.Errorf(
|
||||
"Terraform doesn't allow running any operations against a state\n"+
|
||||
"that was written by a future Terraform version. The state is\n"+
|
||||
"reporting it is written by Terraform '%s'.\n\n"+
|
||||
"Please run at least that version of Terraform to continue.",
|
||||
state.TFVersion)
|
||||
if err := CheckStateVersion(state); err != nil && !opts.StateFutureAllowed {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Explicitly reset our state version to our current version so that
|
||||
|
@ -2174,6 +2174,19 @@ func (s moduleStateSort) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// StateCompatible returns an error if the state is not compatible with the
|
||||
// current version of terraform.
|
||||
func CheckStateVersion(state *State) error {
|
||||
if state == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if state.FromFutureTerraform() {
|
||||
return fmt.Errorf(stateInvalidTerraformVersionErr, state.TFVersion)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const stateValidateErrMultiModule = `
|
||||
Multiple modules with the same path: %s
|
||||
|
||||
@ -2182,3 +2195,11 @@ in your state file that point to the same module. This will cause Terraform
|
||||
to behave in unexpected and error prone ways and is invalid. Please back up
|
||||
and modify your state file manually to resolve this.
|
||||
`
|
||||
|
||||
const stateInvalidTerraformVersionErr = `
|
||||
Terraform doesn't allow running any operations against a state
|
||||
that was written by a future Terraform version. The state is
|
||||
reporting it is written by Terraform '%s'
|
||||
|
||||
Please run at least that version of Terraform to continue.
|
||||
`
|
||||
|
Loading…
Reference in New Issue
Block a user