-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40835 from hashicorp/d-id-attribute-standards
docs: add id attribute standards reference
- Loading branch information
Showing
3 changed files
with
128 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# `id` Attributes | ||
|
||
## Background | ||
|
||
Historically all resources in the Terraform AWS provider have included a read-only `id` attribute, as [Terraform Plugin SDK V2](https://developer.hashicorp.com/terraform/plugin/sdkv2) and its associated acceptance testing library require it. | ||
In most cases, this attribute corresponds to a unique identifier generated by AWS during resource creation. | ||
However, for some resources the identifier is a value provided by the user and the resulting `id` attribute inherently duplicates the value of some other required argument. | ||
|
||
With the general availability of [Terraform Plugin Framework](https://developer.hashicorp.com/terraform/plugin/framework), the separation of the provider testing functionality into its own standalone library ([`terraform-plugin-testing`](https://github.com/hashicorp/terraform-plugin-testing)), and some [corresponding enhancements](https://github.com/hashicorp/terraform-plugin-testing/pull/164) made to this library, resources are no longer **required** to have an `id` attribute. | ||
|
||
## Standard Usage | ||
|
||
As net-new resources [must be implemented](terraform-plugin-development-packages.md) with Terraform Plugin Framework, the following standard should be applied. | ||
|
||
!!! info "`id` Attribute Standard" | ||
For all net-new resources, the `id` attribute should be omitted if it is redundant with an existing argument or is a combination of multiple arguments. | ||
When the unique identifier is a combination of arguments, these should be delimited with a comma (`,`), and rely on the internal [`ExpandResourceID`](https://github.com/hashicorp/terraform-provider-aws/blob/v5.51.1/internal/flex/flex.go#L326-L354) function to handle splitting values within the `ImportState` method. | ||
In all other cases the `id` attribute should continue to be used as it has been historically. | ||
|
||
## Examples | ||
|
||
For resources omitting an `id` argument, minor changes are required to customize the import method and acceptance test the import operation. | ||
For testing, the import verification [`TestStep`](https://pkg.go.dev/github.com/hashicorp/[email protected]/helper/resource#TestStep) will now require the `ImportStateVerifyIdentifierAttribute` and one of `ImportStateID` or `ImportStateIdFunc` be configured. | ||
Examples for a single, non-`id` identifier and a multi-part identifier are included below. | ||
|
||
### Non-`id` Identifier | ||
|
||
In this example, the `vpc_endpoint_id` argument is used as the resource identifier. | ||
|
||
`ImportState` method: | ||
|
||
```go | ||
func (r *resourceEndpointPrivateDNS) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
resource.ImportStatePassthroughID(ctx, path.Root("vpc_endpoint_id"), req, resp) | ||
} | ||
``` | ||
|
||
`TestStep`: | ||
|
||
```go | ||
{ | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateIdFunc: testAccVPCEndpointPrivateDNSImportStateIdFunc(resourceName), | ||
ImportStateVerify: true, | ||
ImportStateVerifyIdentifierAttribute: "vpc_endpoint_id", | ||
}, | ||
``` | ||
|
||
`ImportStateIdFunc`: | ||
|
||
```go | ||
func testAccVPCEndpointPrivateDNSImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { | ||
return func(s *terraform.State) (string, error) { | ||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return "", fmt.Errorf("Not found: %s", resourceName) | ||
} | ||
|
||
return rs.Primary.Attributes["vpc_endpoint_id"], nil | ||
} | ||
} | ||
``` | ||
|
||
### Multi-part Identifier | ||
|
||
In this example, the resource identifier is a combination of the `function_name` and `qualifier` arguments. | ||
|
||
`ImportState` Method: | ||
|
||
```go | ||
func (r *resourceRuntimeManagementConfig) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
parts, err := intflex.ExpandResourceId(req.ID, runtimeManagementConfigIDParts, true) | ||
if err != nil { | ||
resp.Diagnostics.AddError( | ||
"Unexpected Import Identifier", | ||
fmt.Sprintf("Expected import identifier with format: function_name,qualifier. Got: %q", req.ID), | ||
) | ||
return | ||
} | ||
|
||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("function_name"), parts[0])...) | ||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("qualifier"), parts[1])...) | ||
} | ||
``` | ||
|
||
`TestStep`: | ||
|
||
```go | ||
{ | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateIdFunc: testAccRuntimeManagementConfigImportStateIdFunc(resourceName), | ||
ImportStateVerify: true, | ||
ImportStateVerifyIdentifierAttribute: "function_name", | ||
}, | ||
``` | ||
|
||
`ImportStateIdFunc`: | ||
|
||
```go | ||
func testAccRuntimeManagementConfigImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { | ||
return func(s *terraform.State) (string, error) { | ||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return "", fmt.Errorf("Not found: %s", resourceName) | ||
} | ||
|
||
return fmt.Sprintf("%s,%s", rs.Primary.Attributes["function_name"], rs.Primary.Attributes["qualifier"]), nil | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters