From cbf9852584a0363d5d554cf76e758b37bdc14359 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 30 Jul 2024 15:19:57 -0400 Subject: [PATCH 01/11] Added support for datazone glossary resource. --- internal/service/datazone/exports_test.go | 1 + internal/service/datazone/glossary.go | 335 ++++++++++++++++++ internal/service/datazone/glossary_test.go | 298 ++++++++++++++++ .../service/datazone/service_package_gen.go | 4 + .../docs/r/datazone_glossary.html.markdown | 148 ++++++++ 5 files changed, 786 insertions(+) create mode 100644 internal/service/datazone/glossary.go create mode 100644 internal/service/datazone/glossary_test.go create mode 100644 website/docs/r/datazone_glossary.html.markdown diff --git a/internal/service/datazone/exports_test.go b/internal/service/datazone/exports_test.go index 58f3e4834fdc..d6e0107dc346 100644 --- a/internal/service/datazone/exports_test.go +++ b/internal/service/datazone/exports_test.go @@ -9,4 +9,5 @@ var ( ResourceEnvironmentBlueprintConfiguration = newResourceEnvironmentBlueprintConfiguration IsResourceMissing = isResourceMissing ResourceProject = newResourceProject + ResourceGlossary = newResourceGlossary ) diff --git a/internal/service/datazone/glossary.go b/internal/service/datazone/glossary.go new file mode 100644 index 000000000000..561406c1562d --- /dev/null +++ b/internal/service/datazone/glossary.go @@ -0,0 +1,335 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package datazone + +// **PLEASE DELETE THIS AND ALL TIP COMMENTS BEFORE SUBMITTING A PR FOR REVIEW!** +// +// TIP: ==== INTRODUCTION ==== +// Thank you for trying the skaff tool! +// +// You have opted to include these helpful comments. They all include "TIP:" +// to help you find and remove them when you're done with them. +// +// While some aspects of this file are customized to your input, the +// scaffold tool does *not* look at the AWS API and ensure it has correct +// function, structure, and variable names. It makes guesses based on +// commonalities. You will need to make significant adjustments. +// +// In other words, as generated, this is a rough outline of the work you will +// need to do. If something doesn't make sense for your situation, get rid of +// it. + +import ( + // TIP: ==== IMPORTS ==== + // This is a common set of imports but not customized to your code since + // your code hasn't been written yet. Make sure you, your IDE, or + // goimports -w fixes these imports. + // + // The provider linter wants your imports to be in two groups: first, + // standard library (i.e., "fmt" or "strings"), second, everything else. + // + // Also, AWS Go SDK v2 may handle nested structures differently than v1, + // using the services/datazone/types package. If so, you'll + // need to import types and reference the nested types, e.g., as + // awstypes.. + "context" + "errors" + "fmt" + "strings" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/datazone" + awstypes "github.com/aws/aws-sdk-go-v2/service/datazone/types" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// TIP: ==== FILE STRUCTURE ==== +// All resources should follow this basic outline. Improve this resource's +// maintainability by sticking to it. +// +// 1. Package declaration +// 2. Imports +// 3. Main resource struct with schema method +// 4. Create, read, update, delete methods (in that order) +// 5. Other functions (flatteners, expanders, waiters, finders, etc.) + +// Function annotations are used for resource registration to the Provider. DO NOT EDIT. +// @FrameworkResource("aws_datazone_glossary", name="Glossary") +func newResourceGlossary(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceGlossary{} + + return r, nil +} + +const ( + ResNameGlossary = "Glossary" +) + +type resourceGlossary struct { + framework.ResourceWithConfigure +} + +func (r *resourceGlossary) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_datazone_glossary" +} + +func (r *resourceGlossary) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + names.AttrDescription: schema.StringAttribute{ + Optional: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexache.MustCompile(`^[\x21-\x7E]+$`), "must conform to: ^[\x21-\x7E]+$ "), + stringvalidator.LengthBetween(1, 128), + }, + }, + names.AttrName: schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 256), + }, + }, + "owning_project_identifier": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9_-]{1,36}$`), "must conform to: ^[a-zA-Z0-9_-]{1,36}$ "), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + names.AttrStatus: schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.GlossaryStatus](), + Optional: true, + }, + "domain_id": schema.StringAttribute{ + Required: true, + }, + names.AttrID: schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + }, + } +} + +func (r *resourceGlossary) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().DataZoneClient(ctx) + + var plan glossaryData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + in := &datazone.CreateGlossaryInput{} + + resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) + if resp.Diagnostics.HasError() { + return + } + in.DomainIdentifier = plan.DomainId.ValueStringPointer() + out, err := conn.CreateGlossary(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameGlossary, plan.Name.String(), err), + err.Error(), + ) + return + } + if out == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameGlossary, plan.Name.String(), nil), + errors.New("empty output").Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &plan)...) + if resp.Diagnostics.HasError() { + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) +} + +func (r *resourceGlossary) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().DataZoneClient(ctx) + + var state glossaryData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + out, err := findGlossaryByID(ctx, conn, state.Id.ValueString(), state.DomainId.ValueString()) + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionSetting, ResNameProject, state.Id.String(), err), + err.Error(), + ) + return + } + resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + if resp.Diagnostics.HasError() { + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceGlossary) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().DataZoneClient(ctx) + + var plan, state glossaryData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if !plan.Description.Equal(state.Description) || !plan.Name.Equal(state.Name) || !plan.Description.Equal(state.Description) { + in := &datazone.UpdateGlossaryInput{} + resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) + if resp.Diagnostics.HasError() { + return + } + in.DomainIdentifier = plan.DomainId.ValueStringPointer() + in.Identifier = plan.Id.ValueStringPointer() + out, err := conn.UpdateGlossary(ctx, in) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionUpdating, ResNameProject, plan.Id.String(), err), + err.Error(), + ) + return + } + if out == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionUpdating, ResNameProject, plan.Id.String(), nil), + errors.New("empty output from glossary update").Error(), + ) + return + } + resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + if resp.Diagnostics.HasError() { + return + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceGlossary) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().DataZoneClient(ctx) + var state glossaryData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + in := &datazone.UpdateGlossaryInput{} + resp.Diagnostics.Append(flex.Expand(ctx, &state, in)...) + if resp.Diagnostics.HasError() { + return + } + in.DomainIdentifier = state.DomainId.ValueStringPointer() + in.Identifier = state.Id.ValueStringPointer() + in.Status = "DISABLED" + + _, err := conn.UpdateGlossary(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionDeleting, ResNameGlossary, state.Id.String(), err), + err.Error(), + ) + return + } + + in2 := &datazone.DeleteGlossaryInput{ + DomainIdentifier: state.DomainId.ValueStringPointer(), + Identifier: state.Id.ValueStringPointer(), + } + + _, err2 := conn.DeleteGlossary(ctx, in2) + if err2 != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err2) { + return + } + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionDeleting, ResNameGlossary, state.Id.String(), err), + err2.Error(), + ) + return + } +} + +func (r *resourceGlossary) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + parts := strings.Split(req.ID, ",") + + if len(parts) != 3 { + resp.Diagnostics.AddError("Resource Import Invalid ID", fmt.Sprintf(`Unexpected format for import ID (%s), use: "DomainIdentifier,Id,OwningProjectIdentifier"`, req.ID)) + } + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("domain_id"), parts[0])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), parts[1])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("owning_project_identifier"), parts[2])...) +} + +func findGlossaryByID(ctx context.Context, conn *datazone.Client, id string, domain_id string) (*datazone.GetGlossaryOutput, error) { + in := &datazone.GetGlossaryInput{ + Identifier: aws.String(id), + DomainIdentifier: aws.String(domain_id), + } + + out, err := conn.GetGlossary(ctx, in) + if err != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + return nil, err + } + + if out == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +type glossaryData struct { + Description types.String `tfsdk:"description"` + Name types.String `tfsdk:"name"` + OwningProjectIdentifier types.String `tfsdk:"owning_project_identifier"` + Status fwtypes.StringEnum[awstypes.GlossaryStatus] `tfsdk:"status"` + DomainId types.String `tfsdk:"domain_id"` + Id types.String `tfsdk:"id"` +} diff --git a/internal/service/datazone/glossary_test.go b/internal/service/datazone/glossary_test.go new file mode 100644 index 000000000000..8c1575daba55 --- /dev/null +++ b/internal/service/datazone/glossary_test.go @@ -0,0 +1,298 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package datazone_test + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/datazone" + awstypes "github.com/aws/aws-sdk-go-v2/service/datazone/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + tfdatazone "github.com/hashicorp/terraform-provider-aws/internal/service/datazone" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccDataZoneGlossary_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var glossary datazone.GetGlossaryOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + token := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resourceName := "aws_datazone_glossary.test" + projectName := "aws_datazone_project.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGlossaryDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGlossaryConfig_basic(rName, token, pName, dName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryExists(ctx, resourceName, &glossary), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrPair(resourceName, "owning_project_identifier", projectName, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "domain_id", projectName, "domain_identifier"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + }, + }, + }) +} +func TestAccDataZoneGlossary_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var glossary, glossary2 datazone.GetGlossaryOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + token := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resourceName := "aws_datazone_glossary.test" + projectName := "aws_datazone_project.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGlossaryDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGlossaryConfig_basic(rName, token, pName, dName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryExists(ctx, resourceName, &glossary), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "desc"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrPair(resourceName, "owning_project_identifier", projectName, names.AttrID), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), + resource.TestCheckResourceAttrPair(resourceName, "domain_id", projectName, "domain_identifier"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + }, + { + Config: testAccGlossaryConfig_update(rName, token, pName, dName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryExists(ctx, resourceName, &glossary2), + testAccCheckGlossaryNotRecreated(&glossary, &glossary2), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, names.AttrDescription), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrPair(resourceName, "owning_project_identifier", projectName, names.AttrID), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DISABLED"), + resource.TestCheckResourceAttrPair(resourceName, "domain_id", projectName, "domain_identifier"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + }, + }, + }) +} + +func TestAccDataZoneGlossary_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var glossary datazone.GetGlossaryOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + token := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_glossary.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGlossaryDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGlossaryConfig_basic(rName, token, pName, dName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryExists(ctx, resourceName, &glossary), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceGlossary, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckGlossaryDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_datazone_glossary" { + continue + } + _, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_id"]) + if errs.IsA[*awstypes.ResourceNotFoundException](err) || errs.IsA[*awstypes.AccessDeniedException](err) { + return nil + } + if err != nil { + return create.Error(names.DataZone, create.ErrActionCheckingDestroyed, tfdatazone.ResNameGlossary, rs.Primary.ID, err) + } + + return create.Error(names.DataZone, create.ErrActionCheckingDestroyed, tfdatazone.ResNameGlossary, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckGlossaryExists(ctx context.Context, name string, glossary *datazone.GetGlossaryOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossary, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossary, name, errors.New("not set")) + } + if rs.Primary.Attributes["domain_id"] == "" { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameProject, name, errors.New("domain identifier not set")) + } + conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) + resp, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_id"]) + + if err != nil { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossary, rs.Primary.ID, err) + } + + *glossary = *resp + + return nil + } +} + +func findGlossaryByID(ctx context.Context, conn *datazone.Client, id string, domain_id string) (*datazone.GetGlossaryOutput, error) { + in := &datazone.GetGlossaryInput{ + Identifier: aws.String(id), + DomainIdentifier: aws.String(domain_id), + } + + out, err := conn.GetGlossary(ctx, in) + if err != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + return nil, err + } + + if out == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func testAccCheckGlossaryNotRecreated(before, after *datazone.GetGlossaryOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + if before, after := aws.ToString(before.Id), aws.ToString(after.Id); before != after { + return create.Error(names.DataZone, create.ErrActionCheckingNotRecreated, tfdatazone.ResNameGlossary, before, errors.New("recreated")) + } + + return nil + } +} + +func testAccAuthorizerGlossaryImportStateIdFunc(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 strings.Join([]string{rs.Primary.Attributes["domain_id"], rs.Primary.ID, rs.Primary.Attributes["owning_project_identifier"]}, ","), nil + } +} + +func testAccGlossaryConfig_basic(rName, token, dName, pName string) string { + return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` + + + + +resource "aws_datazone_glossary" "test" { + description = "desc" + name = %[1]q + owning_project_identifier = aws_datazone_project.test.id + status = "ENABLED" + domain_id = aws_datazone_project.test.domain_identifier +} +`, rName, token)) +} + +func testAccGlossaryConfig_update(rName, token, dName, pName string) string { + return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` + + + + +resource "aws_datazone_glossary" "test" { + description = "description" + name = %[1]q + owning_project_identifier = aws_datazone_project.test.id + status = "DISABLED" + domain_id = aws_datazone_project.test.domain_identifier +} +`, rName, token)) +} diff --git a/internal/service/datazone/service_package_gen.go b/internal/service/datazone/service_package_gen.go index a2745588aad0..796f7514310c 100644 --- a/internal/service/datazone/service_package_gen.go +++ b/internal/service/datazone/service_package_gen.go @@ -40,6 +40,10 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic Factory: newResourceProject, Name: "Project", }, + { + Factory: newResourceGlossary, + Name: "Glossary", + }, } } diff --git a/website/docs/r/datazone_glossary.html.markdown b/website/docs/r/datazone_glossary.html.markdown new file mode 100644 index 000000000000..7b5b9dc250fa --- /dev/null +++ b/website/docs/r/datazone_glossary.html.markdown @@ -0,0 +1,148 @@ +--- +subcategory: "DataZone" +layout: "aws" +page_title: "AWS: aws_datazone_glossary" +description: |- + Terraform resource for managing an AWS DataZone Glossary. +--- +# Resource: aws_datazone_glossary + +Terraform resource for managing an AWS DataZone Glossary. + +## Example Usage + +```terraform + +resource "aws_iam_role" "domain_execution_role" { + name = "example_name" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = ["sts:AssumeRole", "sts:TagSession"] + Effect = "Allow" + Principal = { + Service = "datazone.amazonaws.com" + } + }, + { + Action = ["sts:AssumeRole", "sts:TagSession"] + Effect = "Allow" + Principal = { + Service = "cloudformation.amazonaws.com" + } + }, + ] + }) + + inline_policy { + name = "example_name" + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = [ + "datazone:*", + "ram:*", + "sso:*", + "kms:*", + ] + Effect = "Allow" + Resource = "*" + }, + ] + }) + } +} + + +resource "aws_datazone_domain" "test" { + name = "example_name" + domain_execution_role = aws_iam_role.domain_execution_role.arn +} + +resource "aws_security_group" "test" { + name = "example_name" +} + +resource "aws_datazone_project" "test" { + domain_identifier = aws_datazone_domain.test.id + glossary_terms = ["2N8w6XJCwZf"] + name = "example_name" + description = "desc" + skip_deletion_check = true +} + + +resource "aws_datazone_glossary" "test" { + client_token = "example_token" + description = "description" + name = "example_name" + owning_project_identifier = aws_datazone_project.test.id + status = "DISABLED" + domain_identifier = aws_datazone_project.test.domain_identifier +} +``` + + +### Basic Usage + + + +```terraform +resource "aws_datazone_glossary" "test" { + client_token = "example_token" + description = "description" + name = "example_name" + owning_project_identifier = aws_datazone_project.test.id + status = "DISABLED" + domain_identifier = aws_datazone_project.test.domain_identifier +} +``` + +## Argument Reference + +The following arguments are required: + +* `client_token` - (Required) Unique case-sensitive identifier that is provided to ensure the idempotency of the request. Must follow regex pattern of ^[\x21-\x7E]+$ and have length between 1 and 128. +* `name` - (Required) Name of the glossary. Must have length between 1 and 256. +* `owning_project_identifier` - (Required) ID of the project that owns business glossary. Must follow regex of ^[a-zA-Z0-9_-]{1,36}$. + + + +The following arguments are optional: + +* `description` - (Optional) Description of the glossary. Must have a length between 0 and 4096. +* `status` - (Optional) Status of business glossary. Valid values are DISABLED and ENABLED. + + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `id` - Id of the Glossary. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `60m`) +* `update` - (Default `180m`) +* `delete` - (Default `90m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import DataZone Glossary using the `example_id_arg`. For example: + +```terraform +import { + to = aws_datazone_glossary.example + id = "domain-id,glossary-id,owning_project_identifier" +} +``` + +Using `terraform import`, import DataZone Glossary using the `example_id_arg`. For example: + +```console +% terraform import aws_datazone_glossary.example domain-id,glossary-id,owning-project-identifier +``` From e6654ab8bde7060a0cf3a17628dd95c6d1baa81c Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 30 Jul 2024 15:44:23 -0400 Subject: [PATCH 02/11] Documentation changes --- website/docs/r/datazone_glossary.html.markdown | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/website/docs/r/datazone_glossary.html.markdown b/website/docs/r/datazone_glossary.html.markdown index 7b5b9dc250fa..8561c01fdaa5 100644 --- a/website/docs/r/datazone_glossary.html.markdown +++ b/website/docs/r/datazone_glossary.html.markdown @@ -55,7 +55,6 @@ resource "aws_iam_role" "domain_execution_role" { } } - resource "aws_datazone_domain" "test" { name = "example_name" domain_execution_role = aws_iam_role.domain_execution_role.arn @@ -84,11 +83,8 @@ resource "aws_datazone_glossary" "test" { } ``` - ### Basic Usage - - ```terraform resource "aws_datazone_glossary" "test" { client_token = "example_token" @@ -108,8 +104,6 @@ The following arguments are required: * `name` - (Required) Name of the glossary. Must have length between 1 and 256. * `owning_project_identifier` - (Required) ID of the project that owns business glossary. Must follow regex of ^[a-zA-Z0-9_-]{1,36}$. - - The following arguments are optional: * `description` - (Optional) Description of the glossary. Must have a length between 0 and 4096. @@ -122,14 +116,6 @@ This resource exports the following attributes in addition to the arguments abov * `id` - Id of the Glossary. -## Timeouts - -[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): - -* `create` - (Default `60m`) -* `update` - (Default `180m`) -* `delete` - (Default `90m`) - ## Import In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import DataZone Glossary using the `example_id_arg`. For example: @@ -141,8 +127,8 @@ import { } ``` -Using `terraform import`, import DataZone Glossary using the `example_id_arg`. For example: +Using `terraform import`, import DataZone Glossary using the import Datazone Glossary using a comma-delimited string combining the domain id, glossary id, and the id of the project it's under. For example: ```console % terraform import aws_datazone_glossary.example domain-id,glossary-id,owning-project-identifier -``` +``` \ No newline at end of file From 9e123f97a7a56538c32d18767c0c97788c003f76 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 30 Jul 2024 15:46:17 -0400 Subject: [PATCH 03/11] Ci formatting --- website/docs/r/datazone_glossary.html.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/website/docs/r/datazone_glossary.html.markdown b/website/docs/r/datazone_glossary.html.markdown index 8561c01fdaa5..09af2a082155 100644 --- a/website/docs/r/datazone_glossary.html.markdown +++ b/website/docs/r/datazone_glossary.html.markdown @@ -109,7 +109,6 @@ The following arguments are optional: * `description` - (Optional) Description of the glossary. Must have a length between 0 and 4096. * `status` - (Optional) Status of business glossary. Valid values are DISABLED and ENABLED. - ## Attribute Reference This resource exports the following attributes in addition to the arguments above: @@ -131,4 +130,4 @@ Using `terraform import`, import DataZone Glossary using the import Datazone Glo ```console % terraform import aws_datazone_glossary.example domain-id,glossary-id,owning-project-identifier -``` \ No newline at end of file +``` From 10945ab660b70b9328b50375044c9bf7b8285e32 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 30 Jul 2024 15:52:04 -0400 Subject: [PATCH 04/11] Commentt removal --- internal/service/datazone/glossary.go | 41 --------------------------- 1 file changed, 41 deletions(-) diff --git a/internal/service/datazone/glossary.go b/internal/service/datazone/glossary.go index 561406c1562d..099d723b9d16 100644 --- a/internal/service/datazone/glossary.go +++ b/internal/service/datazone/glossary.go @@ -3,36 +3,7 @@ package datazone -// **PLEASE DELETE THIS AND ALL TIP COMMENTS BEFORE SUBMITTING A PR FOR REVIEW!** -// -// TIP: ==== INTRODUCTION ==== -// Thank you for trying the skaff tool! -// -// You have opted to include these helpful comments. They all include "TIP:" -// to help you find and remove them when you're done with them. -// -// While some aspects of this file are customized to your input, the -// scaffold tool does *not* look at the AWS API and ensure it has correct -// function, structure, and variable names. It makes guesses based on -// commonalities. You will need to make significant adjustments. -// -// In other words, as generated, this is a rough outline of the work you will -// need to do. If something doesn't make sense for your situation, get rid of -// it. - import ( - // TIP: ==== IMPORTS ==== - // This is a common set of imports but not customized to your code since - // your code hasn't been written yet. Make sure you, your IDE, or - // goimports -w fixes these imports. - // - // The provider linter wants your imports to be in two groups: first, - // standard library (i.e., "fmt" or "strings"), second, everything else. - // - // Also, AWS Go SDK v2 may handle nested structures differently than v1, - // using the services/datazone/types package. If so, you'll - // need to import types and reference the nested types, e.g., as - // awstypes.. "context" "errors" "fmt" @@ -60,21 +31,9 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -// TIP: ==== FILE STRUCTURE ==== -// All resources should follow this basic outline. Improve this resource's -// maintainability by sticking to it. -// -// 1. Package declaration -// 2. Imports -// 3. Main resource struct with schema method -// 4. Create, read, update, delete methods (in that order) -// 5. Other functions (flatteners, expanders, waiters, finders, etc.) - -// Function annotations are used for resource registration to the Provider. DO NOT EDIT. // @FrameworkResource("aws_datazone_glossary", name="Glossary") func newResourceGlossary(_ context.Context) (resource.ResourceWithConfigure, error) { r := &resourceGlossary{} - return r, nil } From 96d6a384fe74c353b4e226defb68a7da1ff06ba5 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 30 Jul 2024 16:25:47 -0400 Subject: [PATCH 05/11] Make gen changes --- internal/service/datazone/service_package_gen.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/datazone/service_package_gen.go b/internal/service/datazone/service_package_gen.go index 796f7514310c..27d808e33a1a 100644 --- a/internal/service/datazone/service_package_gen.go +++ b/internal/service/datazone/service_package_gen.go @@ -36,14 +36,14 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic Factory: newResourceEnvironmentBlueprintConfiguration, Name: "Environment Blueprint Configuration", }, - { - Factory: newResourceProject, - Name: "Project", - }, { Factory: newResourceGlossary, Name: "Glossary", }, + { + Factory: newResourceProject, + Name: "Project", + }, } } From 06e567ab2050372bb7cbd65deb5675cf1305ada7 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Wed, 31 Jul 2024 09:52:55 -0400 Subject: [PATCH 06/11] Added changelog --- .changelog/38602.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/38602.txt diff --git a/.changelog/38602.txt b/.changelog/38602.txt new file mode 100644 index 000000000000..046b4af5896a --- /dev/null +++ b/.changelog/38602.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_datazone_glossary +``` \ No newline at end of file From dafa43e58da47dc44f0b7b00e3a55ea134cea845 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Thu, 1 Aug 2024 11:18:59 -0400 Subject: [PATCH 07/11] Update internal/service/datazone/glossary.go Co-authored-by: Adrian Johnson --- internal/service/datazone/glossary.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/internal/service/datazone/glossary.go b/internal/service/datazone/glossary.go index 099d723b9d16..225e26197d62 100644 --- a/internal/service/datazone/glossary.go +++ b/internal/service/datazone/glossary.go @@ -81,12 +81,7 @@ func (r *resourceGlossary) Schema(ctx context.Context, req resource.SchemaReques "domain_id": schema.StringAttribute{ Required: true, }, - names.AttrID: schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, + names.AttrID: framework.IDAttribute(), }, } } From cc4dda93d36b4c209a022b02cef51f4cabcf289f Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Thu, 1 Aug 2024 11:31:07 -0400 Subject: [PATCH 08/11] Changes to naming and documentation --- internal/service/datazone/glossary.go | 15 +++++------ internal/service/datazone/glossary_test.go | 26 +++++++------------ .../docs/r/datazone_glossary.html.markdown | 2 -- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/internal/service/datazone/glossary.go b/internal/service/datazone/glossary.go index 225e26197d62..49942911a018 100644 --- a/internal/service/datazone/glossary.go +++ b/internal/service/datazone/glossary.go @@ -78,7 +78,7 @@ func (r *resourceGlossary) Schema(ctx context.Context, req resource.SchemaReques CustomType: fwtypes.StringEnumType[awstypes.GlossaryStatus](), Optional: true, }, - "domain_id": schema.StringAttribute{ + "domain_identifier": schema.StringAttribute{ Required: true, }, names.AttrID: framework.IDAttribute(), @@ -101,7 +101,6 @@ func (r *resourceGlossary) Create(ctx context.Context, req resource.CreateReques if resp.Diagnostics.HasError() { return } - in.DomainIdentifier = plan.DomainId.ValueStringPointer() out, err := conn.CreateGlossary(ctx, in) if err != nil { resp.Diagnostics.AddError( @@ -134,7 +133,7 @@ func (r *resourceGlossary) Read(ctx context.Context, req resource.ReadRequest, r return } - out, err := findGlossaryByID(ctx, conn, state.Id.ValueString(), state.DomainId.ValueString()) + out, err := findGlossaryByID(ctx, conn, state.Id.ValueString(), state.DomainIdentifier.ValueString()) if tfresource.NotFound(err) { resp.State.RemoveResource(ctx) return @@ -164,13 +163,12 @@ func (r *resourceGlossary) Update(ctx context.Context, req resource.UpdateReques return } - if !plan.Description.Equal(state.Description) || !plan.Name.Equal(state.Name) || !plan.Description.Equal(state.Description) { + if !plan.Description.Equal(state.Description) || !plan.Name.Equal(state.Name) { in := &datazone.UpdateGlossaryInput{} resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) if resp.Diagnostics.HasError() { return } - in.DomainIdentifier = plan.DomainId.ValueStringPointer() in.Identifier = plan.Id.ValueStringPointer() out, err := conn.UpdateGlossary(ctx, in) @@ -210,7 +208,6 @@ func (r *resourceGlossary) Delete(ctx context.Context, req resource.DeleteReques if resp.Diagnostics.HasError() { return } - in.DomainIdentifier = state.DomainId.ValueStringPointer() in.Identifier = state.Id.ValueStringPointer() in.Status = "DISABLED" @@ -227,7 +224,7 @@ func (r *resourceGlossary) Delete(ctx context.Context, req resource.DeleteReques } in2 := &datazone.DeleteGlossaryInput{ - DomainIdentifier: state.DomainId.ValueStringPointer(), + DomainIdentifier: state.DomainIdentifier.ValueStringPointer(), Identifier: state.Id.ValueStringPointer(), } @@ -250,7 +247,7 @@ func (r *resourceGlossary) ImportState(ctx context.Context, req resource.ImportS if len(parts) != 3 { resp.Diagnostics.AddError("Resource Import Invalid ID", fmt.Sprintf(`Unexpected format for import ID (%s), use: "DomainIdentifier,Id,OwningProjectIdentifier"`, req.ID)) } - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("domain_id"), parts[0])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("domain_identifier"), parts[0])...) resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), parts[1])...) resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("owning_project_identifier"), parts[2])...) } @@ -284,6 +281,6 @@ type glossaryData struct { Name types.String `tfsdk:"name"` OwningProjectIdentifier types.String `tfsdk:"owning_project_identifier"` Status fwtypes.StringEnum[awstypes.GlossaryStatus] `tfsdk:"status"` - DomainId types.String `tfsdk:"domain_id"` + DomainIdentifier types.String `tfsdk:"domain_identifier"` Id types.String `tfsdk:"id"` } diff --git a/internal/service/datazone/glossary_test.go b/internal/service/datazone/glossary_test.go index 8c1575daba55..2c674c1c6790 100644 --- a/internal/service/datazone/glossary_test.go +++ b/internal/service/datazone/glossary_test.go @@ -56,7 +56,7 @@ func TestAccDataZoneGlossary_basic(t *testing.T) { testAccCheckGlossaryExists(ctx, resourceName, &glossary), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrPair(resourceName, "owning_project_identifier", projectName, names.AttrID), - resource.TestCheckResourceAttrPair(resourceName, "domain_id", projectName, "domain_identifier"), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", projectName, "domain_identifier"), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), ), }, @@ -102,7 +102,7 @@ func TestAccDataZoneGlossary_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrPair(resourceName, "owning_project_identifier", projectName, names.AttrID), resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), - resource.TestCheckResourceAttrPair(resourceName, "domain_id", projectName, "domain_identifier"), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", projectName, "domain_identifier"), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), ), }, @@ -122,7 +122,7 @@ func TestAccDataZoneGlossary_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrPair(resourceName, "owning_project_identifier", projectName, names.AttrID), resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DISABLED"), - resource.TestCheckResourceAttrPair(resourceName, "domain_id", projectName, "domain_identifier"), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", projectName, "domain_identifier"), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), ), }, @@ -178,7 +178,7 @@ func testAccCheckGlossaryDestroy(ctx context.Context) resource.TestCheckFunc { if rs.Type != "aws_datazone_glossary" { continue } - _, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_id"]) + _, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) if errs.IsA[*awstypes.ResourceNotFoundException](err) || errs.IsA[*awstypes.AccessDeniedException](err) { return nil } @@ -203,11 +203,11 @@ func testAccCheckGlossaryExists(ctx context.Context, name string, glossary *data if rs.Primary.ID == "" { return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossary, name, errors.New("not set")) } - if rs.Primary.Attributes["domain_id"] == "" { + if rs.Primary.Attributes["domain_identifier"] == "" { return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameProject, name, errors.New("domain identifier not set")) } conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) - resp, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_id"]) + resp, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) if err != nil { return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossary, rs.Primary.ID, err) @@ -261,38 +261,30 @@ func testAccAuthorizerGlossaryImportStateIdFunc(resourceName string) resource.Im return "", fmt.Errorf("Not found: %s", resourceName) } - return strings.Join([]string{rs.Primary.Attributes["domain_id"], rs.Primary.ID, rs.Primary.Attributes["owning_project_identifier"]}, ","), nil + return strings.Join([]string{rs.Primary.Attributes["domain_identifier"], rs.Primary.ID, rs.Primary.Attributes["owning_project_identifier"]}, ","), nil } } func testAccGlossaryConfig_basic(rName, token, dName, pName string) string { return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` - - - - resource "aws_datazone_glossary" "test" { description = "desc" name = %[1]q owning_project_identifier = aws_datazone_project.test.id status = "ENABLED" - domain_id = aws_datazone_project.test.domain_identifier + domain_identifier = aws_datazone_project.test.domain_identifier } `, rName, token)) } func testAccGlossaryConfig_update(rName, token, dName, pName string) string { return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` - - - - resource "aws_datazone_glossary" "test" { description = "description" name = %[1]q owning_project_identifier = aws_datazone_project.test.id status = "DISABLED" - domain_id = aws_datazone_project.test.domain_identifier + domain_identifier = aws_datazone_project.test.domain_identifier } `, rName, token)) } diff --git a/website/docs/r/datazone_glossary.html.markdown b/website/docs/r/datazone_glossary.html.markdown index 09af2a082155..3ed116c66b2d 100644 --- a/website/docs/r/datazone_glossary.html.markdown +++ b/website/docs/r/datazone_glossary.html.markdown @@ -87,7 +87,6 @@ resource "aws_datazone_glossary" "test" { ```terraform resource "aws_datazone_glossary" "test" { - client_token = "example_token" description = "description" name = "example_name" owning_project_identifier = aws_datazone_project.test.id @@ -100,7 +99,6 @@ resource "aws_datazone_glossary" "test" { The following arguments are required: -* `client_token` - (Required) Unique case-sensitive identifier that is provided to ensure the idempotency of the request. Must follow regex pattern of ^[\x21-\x7E]+$ and have length between 1 and 128. * `name` - (Required) Name of the glossary. Must have length between 1 and 256. * `owning_project_identifier` - (Required) ID of the project that owns business glossary. Must follow regex of ^[a-zA-Z0-9_-]{1,36}$. From 656ccec80f90ebe32b4d019f73f11b21d9bf6430 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Thu, 1 Aug 2024 15:16:29 -0400 Subject: [PATCH 09/11] schema reordering + document changes --- internal/service/datazone/glossary.go | 19 ++++++++++--------- .../docs/r/datazone_glossary.html.markdown | 1 - 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/service/datazone/glossary.go b/internal/service/datazone/glossary.go index 49942911a018..61dd6ad5f61f 100644 --- a/internal/service/datazone/glossary.go +++ b/internal/service/datazone/glossary.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" @@ -59,12 +60,10 @@ func (r *resourceGlossary) Schema(ctx context.Context, req resource.SchemaReques stringvalidator.LengthBetween(1, 128), }, }, - names.AttrName: schema.StringAttribute{ + "domain_identifier": schema.StringAttribute{ Required: true, - Validators: []validator.String{ - stringvalidator.LengthBetween(1, 256), - }, }, + names.AttrID: framework.IDAttribute(), "owning_project_identifier": schema.StringAttribute{ Required: true, Validators: []validator.String{ @@ -74,14 +73,16 @@ func (r *resourceGlossary) Schema(ctx context.Context, req resource.SchemaReques stringplanmodifier.RequiresReplace(), }, }, + names.AttrName: schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 256), + }, + }, names.AttrStatus: schema.StringAttribute{ CustomType: fwtypes.StringEnumType[awstypes.GlossaryStatus](), Optional: true, }, - "domain_identifier": schema.StringAttribute{ - Required: true, - }, - names.AttrID: framework.IDAttribute(), }, } } @@ -135,10 +136,10 @@ func (r *resourceGlossary) Read(ctx context.Context, req resource.ReadRequest, r out, err := findGlossaryByID(ctx, conn, state.Id.ValueString(), state.DomainIdentifier.ValueString()) if tfresource.NotFound(err) { + resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) resp.State.RemoveResource(ctx) return } - if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionSetting, ResNameProject, state.Id.String(), err), diff --git a/website/docs/r/datazone_glossary.html.markdown b/website/docs/r/datazone_glossary.html.markdown index 3ed116c66b2d..0d54f7721a2a 100644 --- a/website/docs/r/datazone_glossary.html.markdown +++ b/website/docs/r/datazone_glossary.html.markdown @@ -74,7 +74,6 @@ resource "aws_datazone_project" "test" { resource "aws_datazone_glossary" "test" { - client_token = "example_token" description = "description" name = "example_name" owning_project_identifier = aws_datazone_project.test.id From 034ed5d72d8299c72d1791de4ba8f678b56e99f8 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Thu, 1 Aug 2024 15:27:49 -0400 Subject: [PATCH 10/11] test cleanup --- internal/service/datazone/glossary_test.go | 27 ++++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/internal/service/datazone/glossary_test.go b/internal/service/datazone/glossary_test.go index 2c674c1c6790..41eebeee0b13 100644 --- a/internal/service/datazone/glossary_test.go +++ b/internal/service/datazone/glossary_test.go @@ -61,11 +61,10 @@ func TestAccDataZoneGlossary_basic(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), - ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), }, }, }) @@ -107,11 +106,10 @@ func TestAccDataZoneGlossary_update(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), - ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), }, { Config: testAccGlossaryConfig_update(rName, token, pName, dName), @@ -127,11 +125,10 @@ func TestAccDataZoneGlossary_update(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), - ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), }, }, }) From 17ce18a89f4a801b43e4897cbfb0ec4541b51689 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Thu, 1 Aug 2024 15:59:01 -0400 Subject: [PATCH 11/11] Test cleanup 2 --- internal/service/datazone/exports_test.go | 1 + internal/service/datazone/glossary_test.go | 31 ++-------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/internal/service/datazone/exports_test.go b/internal/service/datazone/exports_test.go index d6e0107dc346..f971f2cd71a5 100644 --- a/internal/service/datazone/exports_test.go +++ b/internal/service/datazone/exports_test.go @@ -10,4 +10,5 @@ var ( IsResourceMissing = isResourceMissing ResourceProject = newResourceProject ResourceGlossary = newResourceGlossary + FindGlossaryByID = findGlossaryByID ) diff --git a/internal/service/datazone/glossary_test.go b/internal/service/datazone/glossary_test.go index 41eebeee0b13..d17626482853 100644 --- a/internal/service/datazone/glossary_test.go +++ b/internal/service/datazone/glossary_test.go @@ -13,7 +13,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/datazone" awstypes "github.com/aws/aws-sdk-go-v2/service/datazone/types" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -22,7 +21,6 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" tfdatazone "github.com/hashicorp/terraform-provider-aws/internal/service/datazone" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -175,7 +173,7 @@ func testAccCheckGlossaryDestroy(ctx context.Context) resource.TestCheckFunc { if rs.Type != "aws_datazone_glossary" { continue } - _, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) + _, err := tfdatazone.FindGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) if errs.IsA[*awstypes.ResourceNotFoundException](err) || errs.IsA[*awstypes.AccessDeniedException](err) { return nil } @@ -204,7 +202,7 @@ func testAccCheckGlossaryExists(ctx context.Context, name string, glossary *data return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameProject, name, errors.New("domain identifier not set")) } conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) - resp, err := findGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) + resp, err := tfdatazone.FindGlossaryByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) if err != nil { return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossary, rs.Primary.ID, err) @@ -216,31 +214,6 @@ func testAccCheckGlossaryExists(ctx context.Context, name string, glossary *data } } -func findGlossaryByID(ctx context.Context, conn *datazone.Client, id string, domain_id string) (*datazone.GetGlossaryOutput, error) { - in := &datazone.GetGlossaryInput{ - Identifier: aws.String(id), - DomainIdentifier: aws.String(domain_id), - } - - out, err := conn.GetGlossary(ctx, in) - if err != nil { - if errs.IsA[*awstypes.ResourceNotFoundException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } - } - - return nil, err - } - - if out == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out, nil -} - func testAccCheckGlossaryNotRecreated(before, after *datazone.GetGlossaryOutput) resource.TestCheckFunc { return func(s *terraform.State) error { if before, after := aws.ToString(before.Id), aws.ToString(after.Id); before != after {