docs/resource-name-generation.md
Terraform AWS Provider resources can use shared logic to support and test name generation, where the operator can choose between an expected naming value, a generated naming value with a prefix, or a fully generated name.
Implementing name generation requires modifying the following:
name_prefix attribute, along with handling in the Create function.name_prefix argument and update the name argument description.internal/service/{service}/{thing}.go), add the following import: "github.com/hashicorp/terraform-provider-aws/internal/create".name_prefix attribute and adjust the name attribute to be Optional, Computed, and conflict with the name_prefix attribute. Be sure to keep any existing validation functions already present on the name.=== "Terraform Plugin Framework (Preferred)"
go "name": schema.StringAttribute{ Optional: true Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), stringplanmodifier.RequiresReplace(), }, Validators: append( stringvalidator.ExactlyOneOf( path.MatchRelative().AtParent().AtName("name"), path.MatchRelative().AtParent().AtName("name_prefix"), ), ), }, "name_prefix": schema.StringAttribute{ Optional: true, Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), stringplanmodifier.RequiresReplace(), }, },
=== "Terraform Plugin SDK V2"
go "name": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, ConflictsWith: []string{"name_prefix"}, }, "name_prefix": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, ConflictsWith: []string{"name"}, },
Create function, make use of the create.Name() function.=== "Terraform Plugin Framework (Preferred)" ```go name := create.Name(ctx, plan.Name.ValueString(), plan.NamePrefix.ValueString())
// ... in AWS Go SDK V2 Input types, etc. use aws.ToString(name)
```
=== "Terraform Plugin SDK V2" ```go name := create.Name(ctx, d.Get("name").(string), d.Get("name_prefix").(string))
// ... in AWS Go SDK V2 Input types, etc. use aws.ToString(name)
```
name and name_prefix in the resource Read function.=== "Terraform Plugin Framework (Preferred)"
go state.Name = flex.StringToFramework(ctx, resp.Name) state.NamePrefix = create.NamePrefixFromName(flex.StringToFramework(ctx, resp.Name))
=== "Terraform Plugin SDK V2"
go d.Set("name", resp.Name) d.Set("name_prefix", create.NamePrefixFromName(aws.StringValue(resp.Name)))
internal/service/{service}/{thing}_test.go), add the following import: sdkid "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"._nameGenerated and _namePrefix which verify the creation of the resource without name and name_prefix arguments, and with only the name_prefix argument, respectively.func TestAccServiceThing_nameGenerated(t *testing.T) {
ctx := acctest.Context(t)
var thing service.ServiceThing
resourceName := "aws_service_thing.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.ServiceServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckThingDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccThingConfig_nameGenerated(),
Check: resource.ComposeTestCheckFunc(
testAccCheckThingExists(ctx, resourceName, &thing),
acctest.CheckResourceAttrNameGenerated(resourceName, "name"),
resource.TestCheckResourceAttr(resourceName, "name_prefix", sdkid.UniqueIdPrefix),
),
},
// If the resource supports import:
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccServiceThing_namePrefix(t *testing.T) {
ctx := acctest.Context(t)
var thing service.ServiceThing
resourceName := "aws_service_thing.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.ServiceServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckThingDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccThingConfig_namePrefix("tf-acc-test-prefix-"),
Check: resource.ComposeTestCheckFunc(
testAccCheckThingExists(ctx, resourceName, &thing),
acctest.CheckResourceAttrNameFromPrefix(resourceName, "name", "tf-acc-test-prefix-"),
resource.TestCheckResourceAttr(resourceName, "name_prefix", "tf-acc-test-prefix-"),
),
},
// If the resource supports import:
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccThingConfig_nameGenerated() string {
return fmt.Sprintf(`
resource "aws_service_thing" "test" {
# ... other configuration ...
}
`)
}
func testAccThingConfig_namePrefix(namePrefix string) string {
return fmt.Sprintf(`
resource "aws_service_thing" "test" {
# ... other configuration ...
name_prefix = %[1]q
}
`, namePrefix)
}
website/docs/r/{service}_{thing}.html.markdown), add the following to the arguments reference.* `name_prefix` - (Optional) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
name argument description to ensure it is denoted as Optional, mention that it can be generated and that it conflicts with name_prefix.* `name` - (Optional) Name of the thing. If omitted, Terraform will assign a random, unique name. Conflicts with `name_prefix`.