states: Disable Terraform version check

For this version of Terraform and forward, we no longer refuse to read
compatible state files written by future versions of Terraform. This is
a commitment that any changes to the semantics or format of the state
file after this commit will require a new state file version 5.

The result of this is that users of this Terraform version will be able
to share remote state with users of future versions, and all users will
be able to read and write state. This will be true until the next major
state file version is required.

This does not affect users of previous versions of Terraform, which will
continue to refuse to read state written by later versions.
This commit is contained in:
Alisdair McDiarmid 2020-10-28 12:41:11 -04:00
parent 92a8d2061c
commit dc2e7520e5
4 changed files with 82 additions and 17 deletions

View File

@ -17,7 +17,6 @@ import (
"github.com/mitchellh/cli"
"github.com/zclconf/go-cty/cty"
version "github.com/hashicorp/go-version"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configschema"
@ -25,7 +24,6 @@ import (
"github.com/hashicorp/terraform/internal/getproviders"
"github.com/hashicorp/terraform/internal/providercache"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/states/statefile"
"github.com/hashicorp/terraform/states/statemgr"
)
@ -965,12 +963,27 @@ func TestInit_getProvider(t *testing.T) {
}
defer f.Close()
s := &statefile.File{
Lineage: "",
State: states.NewState(),
TerraformVersion: version.Must(version.NewVersion("100.1.0")),
// Construct a mock state file from the far future
type FutureState struct {
Version uint `json:"version"`
Lineage string `json:"lineage"`
TerraformVersion string `json:"terraform_version"`
Outputs map[string]interface{} `json:"outputs"`
Resources []map[string]interface{} `json:"resources"`
}
statefile.WriteForTest(s, f)
fs := &FutureState{
Version: 999,
Lineage: "123-456-789",
TerraformVersion: "999.0.0",
Outputs: make(map[string]interface{}, 0),
Resources: make([]map[string]interface{}, 0),
}
src, err := json.MarshalIndent(fs, "", " ")
if err != nil {
t.Fatalf("failed to marshal future state: %s", err)
}
src = append(src, '\n')
_, err = f.Write(src)
ui := new(cli.MockUi)
m.Ui = ui
@ -983,7 +996,7 @@ func TestInit_getProvider(t *testing.T) {
}
errMsg := ui.ErrorWriter.String()
if !strings.Contains(errMsg, "which is newer than current") {
if !strings.Contains(errMsg, "Unsupported state file format") {
t.Fatal("unexpected error:", errMsg)
}
})

View File

@ -62,15 +62,6 @@ func Read(r io.Reader) (*File, error) {
panic("readState returned nil state with no errors")
}
if state.TerraformVersion != nil && state.TerraformVersion.GreaterThan(tfversion.SemVer) {
return state, fmt.Errorf(
"state snapshot was created by Terraform v%s, which is newer than current v%s; upgrade to Terraform v%s or greater to work with this state",
state.TerraformVersion,
tfversion.SemVer,
state.TerraformVersion,
)
}
return state, diags.Err()
}

View File

@ -0,0 +1,60 @@
{
"version": 4,
"serial": 0,
"lineage": "f2968801-fa14-41ab-a044-224f3a4adf04",
"terraform_version": "999.0.0",
"outputs": {
"numbers": {
"type": "string",
"value": "0,1"
}
},
"resources": [
{
"mode": "managed",
"type": "null_resource",
"name": "bar",
"provider": "provider[\"registry.terraform.io/-/null\"]",
"instances": [
{
"schema_version": 0,
"attributes_flat": {
"id": "5388490630832483079",
"triggers.%": "1",
"triggers.whaaat": "0,1"
},
"depends_on": [
"null_resource.foo"
]
}
]
},
{
"mode": "managed",
"type": "null_resource",
"name": "foo",
"provider": "provider[\"registry.terraform.io/-/null\"]",
"each": "list",
"instances": [
{
"index_key": 0,
"schema_version": 0,
"attributes_flat": {
"id": "8212585058302700791",
"triggers.%": "1",
"triggers.what": "0"
}
},
{
"index_key": 1,
"schema_version": 0,
"attributes_flat": {
"id": "1523897709610803586",
"triggers.%": "1",
"triggers.what": "0"
}
}
]
}
]
}

View File

@ -0,0 +1 @@
v4-future.in.tfstate