Repository: hashicorp/terraform (Go)

Issue:
Import fails with “Terraform version mismatch” using Terraform Cloud
https://github.com/hashicorp/terraform/pull/26947 introduced an unexpected behaviour for Terraform Cloud users using local execution mode when running `terraform import`. The `terraform-version` field on the workspace properties would be set to whatever the default was when the workspace was first created — and prior to April this year there was no way to create a workspace with local execution mode directly so all workspaces would have had some version set — and that would cause `terraform import` to fail even though the project and its state files were all considerably newer.

The workaround is simple:

1. Change the workspace to remote execution mode
2. Select a version >= 0.14.0
3. Save
4. Set local execution mode
5. Save


Discussion:
Hi @acdha, thanks for reporting this. I haven't yet been able to reproduce the issue but from re-reading the code I think I can see the issue. Unless I'm missing something, I don't think there's any reason for Terraform to check the remote workspace version when using local operations, so hopefully we should be able to fix this.

In the mean time, can you confirm that using the `-ignore-remote-version` flag with `terraform import` works as expected?
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.




Patch:
diff --git a/backend/remote/backend.go b/backend/remote/backend.go
index 8ff64e34a724..c79ff32e8cf8 100644
--- a/backend/remote/backend.go
+++ b/backend/remote/backend.go
@@ -903,6 +903,12 @@ func (b *Remote) VerifyWorkspaceTerraformVersion(workspaceName string) tfdiags.D
 		return nil
 	}
 
+	// If the workspace has remote operations disabled, the remote Terraform
+	// version is effectively meaningless, so we'll skip version verification.
+	if workspace.Operations == false {
+		return nil
+	}
+
 	remoteVersion, err := version.NewSemver(workspace.TerraformVersion)
 	if err != nil {
 		diags = diags.Append(tfdiags.Sourceless(


Test patch:
diff --git a/backend/remote/backend_test.go b/backend/remote/backend_test.go
index 139ddafd3044..0155ba590c04 100644
--- a/backend/remote/backend_test.go
+++ b/backend/remote/backend_test.go
@@ -556,18 +556,20 @@ func TestRemote_StateMgr_versionCheckLatest(t *testing.T) {
 
 func TestRemote_VerifyWorkspaceTerraformVersion(t *testing.T) {
 	testCases := []struct {
-		local   string
-		remote  string
-		wantErr bool
+		local      string
+		remote     string
+		operations bool
+		wantErr    bool
 	}{
-		{"0.13.5", "0.13.5", false},
-		{"0.14.0", "0.13.5", true},
-		{"0.14.0", "0.14.1", false},
-		{"0.14.0", "1.0.99", false},
-		{"0.14.0", "1.1.0", true},
-		{"1.2.0", "1.2.99", false},
-		{"1.2.0", "1.3.0", true},
-		{"0.15.0", "latest", false},
+		{"0.13.5", "0.13.5", true, false},
+		{"0.14.0", "0.13.5", true, true},
+		{"0.14.0", "0.13.5", false, false},
+		{"0.14.0", "0.14.1", true, false},
+		{"0.14.0", "1.0.99", true, false},
+		{"0.14.0", "1.1.0", true, true},
+		{"1.2.0", "1.2.99", true, false},
+		{"1.2.0", "1.3.0", true, true},
+		{"0.15.0", "latest", true, false},
 	}
 	for _, tc := range testCases {
 		t.Run(fmt.Sprintf("local %s, remote %s", tc.local, tc.remote), func(t *testing.T) {
@@ -598,6 +600,7 @@ func TestRemote_VerifyWorkspaceTerraformVersion(t *testing.T) {
 				b.organization,
 				b.workspace,
 				tfe.WorkspaceUpdateOptions{
+					Operations:       tfe.Bool(tc.operations),
 					TerraformVersion: tfe.String(tc.remote),
 				},
 			); err != nil {