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

Read-for-import does not apply Default values under PlanResourceChange #2372

Open
t0yv0 opened this issue Aug 28, 2024 · 11 comments
Open

Read-for-import does not apply Default values under PlanResourceChange #2372

t0yv0 opened this issue Aug 28, 2024 · 11 comments
Assignees
Labels
kind/bug Some behavior is incorrect or out of spec

Comments

@t0yv0
Copy link
Member

t0yv0 commented Aug 28, 2024

What happened?

There is an observable change in behavior with the PlanResourceChange flag for Read for import (Read with empty properties) that leads to the import resource option being broken for SDKv2-based providers.

This got discovered in: pulumi/pulumi-aws#4403

Before PRC:

  Read(properties={}) ==>
  {"properties": {"acl": null, "forceDestroy": null},
   "inputs":     {"acl": "private"}, {"forceDestroy": false}}

  Check(olds={"acl": "private", "forceDestroy": false}, news={}) ==>
  {"acl": "private", "forceDestroy": false}

  Diff(olds={"acl": "private", "forceDestroy": false},
       news={"acl": "private", "forceDestroy": false}) ==>

After PRC:

    Read(properties={}) ==>
    {"acl": null, "forceDestroy": null}

    Check(olds={"acl": null, "forceDestroy": null}, news={}) ==>
    {"acl": "private", "forceDestroy": false}

    Diff(olds={"acl": null, "forceDestroy": null},
         news={"acl": "private", "forceDestroy": false}) ==>
    {"diffs": ["acl", "forceDestroy"]}

Unfortunately this Diff is very sensitive as subsequently pulumi up fails to import without giving the user any good options to move forward.

The issue was discovered on legacy bucket but likely applies to more providers. The "private" and "forceDestroy" values are specified as SDKv2 defaults using something like this:

			"acl": {
				Type:          schema.TypeString,
				Default:       "private",
				Optional:      true,
				ConflictsWith: []string{"grant"},
				ValidateFunc:  validation.StringInSlice(BucketCannedACL_Values(), false),
			},

Looks like Read needs to apply these defaults to the returned inputs section in the case of import.

Example

See above

Output of pulumi about

N/A

Additional context

This issue is for SDKv2 resources. For PF resources it's more complicated since we cannot easily infer default values for them, causing #2272 - it is possible that solving 2272 could unblock this problem as well.

Contributing

Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

@t0yv0 t0yv0 added kind/bug Some behavior is incorrect or out of spec needs-triage Needs attention from the triage team labels Aug 28, 2024
t0yv0 added a commit to pulumi/pulumi-aws that referenced this issue Aug 28, 2024
@t0yv0 t0yv0 self-assigned this Aug 28, 2024
@t0yv0
Copy link
Member Author

t0yv0 commented Aug 28, 2024

Investigated some more in #2373 - it's not that before PRC defaults were applied to the results of Read, they were not, but we are running into the problem #2272 variation, looks like this diff was a DIFF_NONE previously but becomes a DIFF_SOME under PRC.

{
  "method": "/pulumirpc.ResourceProvider/Diff",
  "request": {
    "id": "b1",
    "urn": "urn:pulumi:test::test::prov:index/legacyBucket:LegacyBucket::mainRes",
    "olds": {
      "id": "b1"
    },
    "news": {
      "__defaults": [
        "acl",
        "forceDestroy"
      ],
      "acl": "private",
      "forceDestroy": false
    },
    "oldInputs": {
      "__defaults": []
    }
  },
  "response": {
    "changes": "DIFF_NONE",
    "hasDetailedDiff": true
  }
}

@iwahbe iwahbe removed the needs-triage Needs attention from the triage team label Aug 29, 2024
@VenelinMartinov
Copy link
Contributor

This looks like a provider issue - the provider isn't returning a value for acl when read, even though it must be set since it has a default.

Should we fix this in the provider?

@t0yv0
Copy link
Member Author

t0yv0 commented Aug 29, 2024

We can't fix it in the provider because Read() is not going to guarantee applying defaults in Terraform. I think the impact here might be that every single bridged provider resource with SDKV2 Defaults has the import option broken?

#2373

@VenelinMartinov
Copy link
Contributor

I believe the contract here is that Read should return all properties of the resource - if the resource has a property set, regardless if it is set by the user or a default value it should be returned by Read.

This seems to me like an issue with the TF provider - the property in question is set, because it has a default value. Read, however, returns no value for it

@VenelinMartinov
Copy link
Contributor

Depending on how wide spread this issue is, we could add a workaround in the bridge

@VenelinMartinov
Copy link
Contributor

I wonder if Refresh is also affected here - we call Read then too.

@t0yv0
Copy link
Member Author

t0yv0 commented Aug 29, 2024

We cross-checked a few resources. It seems like the issue is not widespread - most resources actually return the default values from Read() so import option works for them. I've checked a few popular GCP resources with Default: values

  • GCP compute instance works
  • GCP storage bucket works
  • GCP network works

@t0yv0
Copy link
Member Author

t0yv0 commented Aug 29, 2024

The direction so far is to treat it as won't fix in the bridge, and instead treat it as resource-level issue fixed by fixing up Read() as necessary. The change in Diff behavior under Plan Resource Change that makes the following a DIFF_SOME seems sound:

{
  "method": "/pulumirpc.ResourceProvider/Diff",
  "request": {
    "id": "b1",
    "urn": "urn:pulumi:test::test::prov:index/legacyBucket:LegacyBucket::mainRes",
    "olds": {
      "id": "b1"
    },
    "news": {
      "__defaults": [
        "acl",
        "forceDestroy"
      ],
      "acl": "private",
      "forceDestroy": false
    },
    "oldInputs": {
      "__defaults": []
    }
  },
  "response": {
    "changes": "DIFF_NONE",
    "hasDetailedDiff": true
  }
}

@t0yv0
Copy link
Member Author

t0yv0 commented Aug 29, 2024

I was curious how exactly this works in the bridge right now and I debugged this example (with PlanResourceChange=false). It seems to be an implicit logic, not something coded up explicitly. Notable references:

https://github.com/pulumi/pulumi-terraform-bridge/blob/master/pkg/tfbridge/provider.go#L1388
https://github.com/pulumi/pulumi-terraform-bridge/blob/master/pkg/tfshim/sdk-v2/resource.go#L86

func (r v2Resource) InstanceState goes ahead and applies default values for data that was not passed in. This is where it's happening. So then the diff is comparing "effective state" with defaults against news with defaults.

This still seems wrong to me. IN TF InstateState is frozen from the statefile and is not affected by the current provider's settings such as current version's defaults. So I guess this is good this behavior is changing.

@flostadler
Copy link
Contributor

This also affects the ASG resource in pulumi-aws: pulumi/pulumi-aws#4457.

@t0yv0
Copy link
Member Author

t0yv0 commented Sep 23, 2024

Proposing to fix ASG via diff suppression. If we like this approach it can be scaled out to the rest. pulumi/pulumi-aws#4510

@mjeffryes mjeffryes added this to the 0.111 milestone Oct 2, 2024
@mjeffryes mjeffryes removed this from the 0.111 milestone Oct 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Some behavior is incorrect or out of spec
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants