Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to Read Previously Saved State for UpgradeResourceState TF 0.12 #415

Closed
bendbennett opened this issue Jul 14, 2022 · 2 comments · Fixed by #426
Closed

Unable to Read Previously Saved State for UpgradeResourceState TF 0.12 #415

bendbennett opened this issue Jul 14, 2022 · 2 comments · Fixed by #426
Assignees
Labels
bug Something isn't working
Milestone

Comments

@bendbennett
Copy link
Contributor

Module version

v0.9.0

Relevant provider source code

func TestAccResourceString_UpgradeFromVersion3_3_2(t *testing.T) {
	resource.Test(t, resource.TestCase{
		Steps: []resource.TestStep{
			{
				ExternalProviders: providerVersion332(),
				Config: `resource "random_string" "min" {
							length = 12
							override_special = "!#@"
							min_lower = 2
							min_upper = 3
							min_special = 1
							min_numeric = 4
						}`,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttrWith("random_string.min", "result", testCheckLen(12)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([a-z].*){2,}`)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([0-9].*){4,}`)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([!#@])`)),
					resource.TestCheckResourceAttr("random_string.min", "special", "true"),
					resource.TestCheckResourceAttr("random_string.min", "upper", "true"),
					resource.TestCheckResourceAttr("random_string.min", "lower", "true"),
					resource.TestCheckResourceAttr("random_string.min", "numeric", "true"),
					resource.TestCheckResourceAttr("random_string.min", "min_special", "1"),
					resource.TestCheckResourceAttr("random_string.min", "min_upper", "3"),
					resource.TestCheckResourceAttr("random_string.min", "min_lower", "2"),
					resource.TestCheckResourceAttr("random_string.min", "min_numeric", "4"),
				),
			},
			{
				ProtoV5ProviderFactories: protoV5ProviderFactories(),
				Config: `resource "random_string" "min" {
							length = 12
							override_special = "!#@"
							min_lower = 2
							min_upper = 3
							min_special = 1
							min_numeric = 4
						}`,
				PlanOnly: true,
			},
			{
				ProtoV5ProviderFactories: protoV5ProviderFactories(),
				Config: `resource "random_string" "min" {
							length = 12
							override_special = "!#@"
							min_lower = 2
							min_upper = 3
							min_special = 1
							min_numeric = 4
						}`,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttrWith("random_string.min", "result", testCheckLen(12)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([a-z].*){2,}`)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([A-Z].*){3,}`)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([0-9].*){4,}`)),
					resource.TestMatchResourceAttr("random_string.min", "result", regexp.MustCompile(`([!#@])`)),
					resource.TestCheckResourceAttr("random_string.min", "special", "true"),
					resource.TestCheckResourceAttr("random_string.min", "upper", "true"),
					resource.TestCheckResourceAttr("random_string.min", "lower", "true"),
					resource.TestCheckResourceAttr("random_string.min", "numeric", "true"),
					resource.TestCheckResourceAttr("random_string.min", "min_special", "1"),
					resource.TestCheckResourceAttr("random_string.min", "min_upper", "3"),
					resource.TestCheckResourceAttr("random_string.min", "min_lower", "2"),
					resource.TestCheckResourceAttr("random_string.min", "min_numeric", "4"),
				),
			},
		},
	})
}

Terraform Configuration Files

`resource "random_string" "min" {
	length = 12
	override_special = "!#@"
	min_lower = 2
	min_upper = 3
	min_special = 1
	min_numeric = 4
}

Debug Output

https://gist.github.com/bendbennett/d6ff45746b0ec931389b9ec5cfc79ee7

Expected Behavior

During the running of the test to verify that upgrading the provider from v3.3.2 to current version (v4.0.0) upgrade resource state should run without error.

Actual Behavior

The following error is generated:

    resource_string_test.go:304: Step 2/3 error: Error running pre-apply refresh: exit status 1
        2022/07/12 13:50:45 [DEBUG] Using modified User-Agent: Terraform/0.12.31 HashiCorp-terraform-exec/0.17.2
        Error: Unable to Read Previously Saved State for UpgradeResourceState
        There was an error reading the saved resource state using the current resource
        schema.
        If this resource state was last refreshed with Terraform CLI 0.11 and earlier,
        it must be refreshed or applied with an older provider version first. If you
        manually modified the resource state, you will need to manually modify it to
        match the current resource schema. Otherwise, please report this to the
        provider developer:
        ElementKeyValue(tftypes.String<unknown>): unsupported attribute "number"
    testing_new.go:73: Error retrieving state, there may be dangling resources: exit status 1
        2022/07/12 13:50:45 [DEBUG] Using modified User-Agent: Terraform/0.12.31 HashiCorp-terraform-exec/0.17.2
        Failed to marshal state to json: unsupported attribute "number"

Steps to Reproduce

This can be reproduced by running the test using TF 0.12.

Investigation

The issue arises as a consequence of the fact that TF core behaves differently in versions >= 0.13 in that, if attributes defined within a schema do not have a matching value stored within state then they are ignored, whereas in TF 0.12 this results in an error.
This appears to arise within the UpgradeResourceState func.

@bendbennett bendbennett added the bug Something isn't working label Jul 14, 2022
@bflad
Copy link
Contributor

bflad commented Jul 14, 2022

Some initial ideas around resolution include the below, without investigating the underlying details too much yet or considering whether they could have bad consequences:

If an unsupported attribute error happens there in the logic, checking to see if the resource implements state upgrades and walking backwards through versions to find a prior schema that does decode the value properly, then run that specific state upgrader.

Whether we can convince terraform-plugin-go's (RawState).Unmarshal() to ignore non-schema defined data or provide a variant that does.

Similarly, we could see if terraform-plugin-go's (RawState).Unmarshal() can collect all errors and still try to return as much data as it can. It'd need a well-defined error type for framework to match against for that to work though and semantics of go-multierror (a defacto module used for collecting multiple errors into one) could be interesting or a bad time.

@github-actions
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants