From dc2e7520e57888efe2aef4ac82ed26eabe7125c1 Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Wed, 28 Oct 2020 12:41:11 -0400 Subject: [PATCH] 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. --- command/init_test.go | 29 ++++++--- states/statefile/read.go | 9 --- .../testdata/roundtrip/v4-future.in.tfstate | 60 +++++++++++++++++++ .../testdata/roundtrip/v4-future.out.tfstate | 1 + 4 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 states/statefile/testdata/roundtrip/v4-future.in.tfstate create mode 120000 states/statefile/testdata/roundtrip/v4-future.out.tfstate diff --git a/command/init_test.go b/command/init_test.go index 96d853d36..a809a3814 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -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) } }) diff --git a/states/statefile/read.go b/states/statefile/read.go index d691c0290..8abd3be14 100644 --- a/states/statefile/read.go +++ b/states/statefile/read.go @@ -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() } diff --git a/states/statefile/testdata/roundtrip/v4-future.in.tfstate b/states/statefile/testdata/roundtrip/v4-future.in.tfstate new file mode 100644 index 000000000..71d759bc7 --- /dev/null +++ b/states/statefile/testdata/roundtrip/v4-future.in.tfstate @@ -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" + } + } + ] + } + ] +} diff --git a/states/statefile/testdata/roundtrip/v4-future.out.tfstate b/states/statefile/testdata/roundtrip/v4-future.out.tfstate new file mode 120000 index 000000000..b4037372e --- /dev/null +++ b/states/statefile/testdata/roundtrip/v4-future.out.tfstate @@ -0,0 +1 @@ +v4-future.in.tfstate \ No newline at end of file