Skip to content

Resource Identity: Add identity data to existing RPCs and add two new identity related RPCs"#1444

Merged
rainkwan merged 34 commits intomainfrom
feat/resource-identity
Mar 19, 2025
Merged

Resource Identity: Add identity data to existing RPCs and add two new identity related RPCs"#1444
rainkwan merged 34 commits intomainfrom
feat/resource-identity

Conversation

@ansgarm
Copy link
Copy Markdown
Member

@ansgarm ansgarm commented Mar 14, 2025

This PR adds initial support for Resource Identity to the SDKv2. It's in an early stage, meaning it's only lightly tested and mostly covering the happy path.

  • update plugin go
  • initial generate of RPC + small shim test
  • wip - resource identity schema
  • Added initial testing for getresourceidentityschemas
  • Added initial attempt for GetResourceIdentitySchemas and UpgradeResourceIdentity.
  • start implementing identity in ReadResource – test doesn't work yet, but getting close
  • Added more for GetResourceIdentitySchemas and UpgradeResourceIdentity.
  • Copied CoreIdentitySchema to CoreResourceIdentitySchema and started ConfigIdentitySchemaToProto and coreConfigIdentitySchema to use in GetResourceIdentitySchemas
  • Continuing addition of functions for Resource Identity
  • Added TODO for internal validation later
  • Tests for GetResourceIdentity passing
  • Initial test written for UpgradeResourceIdentity passing
  • make ReadResource test pass
  • use the right identity upgraders
  • support get, set for identity data
  • support get, set for identity data in diffs in PlanResourceChange customize diff functions
  • Added to the internal validation in schema and corresponding tests, need to check if the expected behavior is correct
  • Added TestUpgradeResourceIdentity_removedAttr and TestUpgradeResourceIdentity_jsonStateBigInt however BigInt doesn't work just yet
  • safeguard empty identity sent by Terraform
  • implement identity in ApplyResourceChange
  • allow using Identity() when there wasn't one yet
  • fix check for previous state
  • Added scaffolding for internalIdentityValidate in resource.go to validate resource identities
  • update terraform-plugin-go to latest main
  • fix diff possibly being empty
  • update RawIdentity to RawState as the former was retired
  • update code comments and remove obsolete todos

@ansgarm ansgarm force-pushed the feat/resource-identity branch from 5a14a0c to 1aaf288 Compare March 14, 2025 17:12
Copy link
Copy Markdown
Member

@austinvalle austinvalle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a first look, good stuff so far!

Comment thread helper/schema/grpc_provider.go
Comment thread helper/schema/grpc_provider.go Outdated
Comment thread helper/schema/grpc_provider.go Outdated
Comment thread helper/schema/grpc_provider.go Outdated
Comment thread helper/schema/grpc_provider.go Outdated
Comment thread helper/schema/resource_data.go Outdated
Comment thread internal/configs/configschema/schema.go
Comment thread helper/schema/schema.go Outdated
Comment on lines +959 to +963
if v.RequiredForImport {

} else if v.OptionalForImport {

} else if !v.Required && !v.Optional && !v.Computed {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to validate the identity schema separate from the other schemas, it would make logic like this a little cleaner.

Would this allow you to create invalid resource schemas that use OptionalForImport or RequiredForImport, and therefore have Required, Optional, and Computed as false?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, this internalValidate() should be schema type agnostic. I don't think it's even possible to pass information about the schema type to this method without some major refactoring. If we have resource identity schema-specific validation that might need to be a separate method that's called in (*provider).InternalValidate(). This is where the validation that blocks write-only attributes in non-managed resource schemas is:

dataSourceSchema := schemaMap(r.SchemaMap())
if dataSourceSchema.hasWriteOnly() {
validationErrors = append(validationErrors, fmt.Errorf("data source %s cannot contain write-only attributes", k))
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll implement validation in a follow-up PR – I'll leave this discussion open for reference.

Comment thread helper/schema/resource_identity.go Outdated
Comment thread helper/schema/identity_data.go
@ansgarm ansgarm force-pushed the feat/resource-identity branch from 37bfb7d to 2fe253a Compare March 17, 2025 11:12
Copy link
Copy Markdown
Contributor

@SBGoods SBGoods left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good so far! Left a couple of comments

Comment thread helper/schema/grpc_provider.go Outdated
Comment thread helper/schema/schema.go Outdated
Comment on lines +959 to +963
if v.RequiredForImport {

} else if v.OptionalForImport {

} else if !v.Required && !v.Optional && !v.Computed {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, this internalValidate() should be schema type agnostic. I don't think it's even possible to pass information about the schema type to this method without some major refactoring. If we have resource identity schema-specific validation that might need to be a separate method that's called in (*provider).InternalValidate(). This is where the validation that blocks write-only attributes in non-managed resource schemas is:

dataSourceSchema := schemaMap(r.SchemaMap())
if dataSourceSchema.hasWriteOnly() {
validationErrors = append(validationErrors, fmt.Errorf("data source %s cannot contain write-only attributes", k))
}

@rainkwan rainkwan added this to the v2.37.0 milestone Mar 19, 2025
@ansgarm ansgarm marked this pull request as ready for review March 19, 2025 07:43
@ansgarm ansgarm requested a review from a team as a code owner March 19, 2025 07:43
austinvalle and others added 22 commits March 19, 2025 08:43
…onfigIdentitySchemaToProto and coreConfigIdentitySchema to use in GetResourceIdentitySchemas
…eed to check if the expected behavior is correct
…Identity_jsonStateBigInt however BigInt doesn't work just yet
@ansgarm ansgarm force-pushed the feat/resource-identity branch from 08cbafd to 379753f Compare March 19, 2025 07:43
@ansgarm ansgarm requested review from SBGoods and austinvalle March 19, 2025 08:01
@ansgarm ansgarm force-pushed the feat/resource-identity branch from 4dd72ac to fea8e20 Compare March 19, 2025 12:13
Comment thread helper/schema/schema.go
Comment on lines +1015 to +1017
if v.WriteOnly && v.Default != nil {
return fmt.Errorf("%s: Default cannot be set with WriteOnly", k)
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can keep this small improvement

Copy link
Copy Markdown
Member

@austinvalle austinvalle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

We should follow up this PR with a bump to the terraform-plugin-go@v0.27.0-alpha.1 and maybe a pre-release changelog similar to the framework one -> https://github.com/hashicorp/terraform-plugin-framework/blob/main/.changes/1.15.0-alpha.1.md

Comment on lines +824 to +825
// TODO: is there a more elegant way to do this? this requires us to look for the identity schema block again
if req.CurrentIdentity != nil && req.CurrentIdentity.IdentityData != nil {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure what you mean by this comment, but in general we'll always need the identity schema to decode identity data from the protocol (any DynamicValue in the protocol needs a schema to decode to avoid losing any type/value information)

Perhaps all of this logic can eventually be extracted to a function that transforms a *tfprotov5.ResourceIdentityData into a flatmap, but not sure we can avoid the usage of the schema.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that comment is mostly there to indicate that this code is repeated multiple times – so extracting it into a function might make sense, but yeah, schema would need to be passed into it to work.


// convert req.CurrentIdentity to flat map identity structure
// Step 1: Turn JSON into cty.Value based on schema
identityBlock := s.getResourceIdentitySchemaBlock(req.TypeName) // TODO: handle error if no schema exists (and after we add the error)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should generally trying to return some nice error if we encounter identity data unexpectedly

// Step 2: Turn cty.Value into flatmap representation
identityAttrs := hcl2shim.FlatmapValueFromHCL2(identityVal)
// Step 3: Well, set it in the priorState
priorState.Identity = identityAttrs
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird, I didn't know that planned state was also kind of side-car'd with prior state 😅

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be copy-pasted in error – I don't recall if it was needed

Comment on lines +1444 to +1445
// TODO: if schema defines identity, we should error if there's none written to newInstanceState
if res.Identity != nil {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing I think needs immediate action before we merge this PR, just some thoughts

I'm actually not sure where the logic to "delete" the resource (send back a null value) happens in SDKv2, but I think we'll want to make sure we send a null identity object back if we're destroying.

For example, here it is in framework: https://github.com/hashicorp/terraform-plugin-framework/blob/f01eb331c102f536ee3b93c7a6066edbabb815fb/internal/fwserver/server_deleteresource.go#L116-L134

I also don't know if core cares about what we send back, but this might be something we run into if they do. Perhaps a follow-up! (Once we start using terraform-plugin-testing to test identity, we'll find out quick if this is a problem 😆 )

UnsafeToUseLegacyTypeSystem: true,
},
},
"basic-plan-with-identity": {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are great tests to have here! ❤️

I'd say once we start getting more complex then this, we can start implementing terraform-provider-corner tests, since they'll hit the plan/apply combo

Comment thread helper/schema/schema.go
}

result.Identity = mapWIdentity.Map()
} // TODO: else log error?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➕ to eventually returning errors in situations like this. This would indicate that either Terraform has a bug or the SDK has a bug, so we want to explicitly call that out.

Comment thread helper/schema/identity_data.go
ansgarm added a commit to hashicorp/terraform-provider-corner that referenced this pull request Mar 19, 2025
@rainkwan rainkwan merged commit f58eb00 into main Mar 19, 2025
21 checks passed
@rainkwan rainkwan deleted the feat/resource-identity branch March 19, 2025 14:24
@ansgarm
Copy link
Copy Markdown
Member Author

ansgarm commented Mar 19, 2025

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Apr 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants