From c5be0c481491a172d4a9b7d40d50c847aa6603d6 Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Mon, 5 Aug 2024 16:58:06 -0400 Subject: [PATCH 1/8] Completed crud operations for the datazone glossary term. --- internal/service/datazone/exports_test.go | 2 + internal/service/datazone/glossary_term.go | 344 ++++++++++++++++++ .../service/datazone/glossary_term_test.go | 291 +++++++++++++++ .../service/datazone/service_package_gen.go | 4 + .../r/datazone_glossary_term.html.markdown | 75 ++++ 5 files changed, 716 insertions(+) create mode 100644 internal/service/datazone/glossary_term.go create mode 100644 internal/service/datazone/glossary_term_test.go create mode 100644 website/docs/r/datazone_glossary_term.html.markdown diff --git a/internal/service/datazone/exports_test.go b/internal/service/datazone/exports_test.go index f971f2cd71a..8b285612969 100644 --- a/internal/service/datazone/exports_test.go +++ b/internal/service/datazone/exports_test.go @@ -11,4 +11,6 @@ var ( ResourceProject = newResourceProject ResourceGlossary = newResourceGlossary FindGlossaryByID = findGlossaryByID + ResourceGlossaryTerm = newResourceGlossaryTerm + FindGlossaryTermByID = findGlossaryTermByID ) diff --git a/internal/service/datazone/glossary_term.go b/internal/service/datazone/glossary_term.go new file mode 100644 index 00000000000..f5af9b65032 --- /dev/null +++ b/internal/service/datazone/glossary_term.go @@ -0,0 +1,344 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package datazone + +import ( + "context" + "errors" + "fmt" + "strings" + + "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-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "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/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/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" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource("aws_datazone_glossary_term", name="Glossary Term") +func newResourceGlossaryTerm(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceGlossaryTerm{} + return r, nil +} + +const ( + ResNameGlossaryTerm = "Glossary Term" +) + +type resourceGlossaryTerm struct { + framework.ResourceWithConfigure + framework.WithTimeouts +} + +func (r *resourceGlossaryTerm) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_datazone_glossary_term" +} + +func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "domain_identifier": schema.StringAttribute{ + Optional: true, + }, + "glossary_identifier": schema.StringAttribute{ + Required: true, + }, + names.AttrID: framework.IDAttribute(), + "long_description": schema.StringAttribute{ + Optional: true, + }, + names.AttrName: schema.StringAttribute{ + Required: true, + }, + "short_description": schema.StringAttribute{ + Optional: true, + }, + names.AttrStatus: schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.GlossaryTermStatus](), + Optional: true, + }, + names.AttrCreatedAt: schema.StringAttribute{ + CustomType: timetypes.RFC3339Type{}, + Computed: true, + }, + "updated_at": schema.StringAttribute{ + CustomType: timetypes.RFC3339Type{}, + Computed: true, + }, + "created_by": schema.StringAttribute{ + Computed: true, + }, + "updated_by": schema.StringAttribute{ + Computed: true, + }, + }, + Blocks: map[string]schema.Block{ + "term_relations": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[resourceTermRelationsData](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "classifies": schema.ListAttribute{ + CustomType: fwtypes.ListOfStringType, + ElementType: types.StringType, + Optional: true, + }, + "is_a": schema.ListAttribute{ + CustomType: fwtypes.ListOfStringType, + ElementType: types.StringType, + Optional: true, + }, + }, + }, + }, + names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{ + Create: true, + }), + }, + } +} + +func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().DataZoneClient(ctx) + + var plan resourceGlossaryTermData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + in := &datazone.CreateGlossaryTermInput{} + resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) + if resp.Diagnostics.HasError() { + return + } + out, err := conn.CreateGlossaryTerm(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 + } + createTimeout := r.CreateTimeout(ctx, plan.Timeouts) + outputRaws, err := tfresource.RetryWhenNotFound(ctx, createTimeout, func() (interface{}, error) { + return findGlossaryTermByID(ctx, conn, *out.Id, *out.DomainId) + }) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameGlossaryTerm, plan.Name.String(), err), + err.Error(), + ) + return + } + output := outputRaws.(*datazone.GetGlossaryTermOutput) + resp.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + if resp.Diagnostics.HasError() { + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *resourceGlossaryTerm) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().DataZoneClient(ctx) + + var state resourceGlossaryTermData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + out, err := findGlossaryTermByID(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), + 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 *resourceGlossaryTerm) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().DataZoneClient(ctx) + + var plan, state resourceGlossaryTermData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if !plan.ShortDescription.Equal(state.ShortDescription) || !plan.LongDescription.Equal(state.LongDescription) || !plan.Name.Equal(state.Name) || !plan.Status.Equal(state.Status) || + !plan.Name.Equal(state.Name) { + in := &datazone.UpdateGlossaryTermInput{} + resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) + if resp.Diagnostics.HasError() { + return + } + in.Identifier = plan.Id.ValueStringPointer() + out, err := conn.UpdateGlossaryTerm(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 term 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 *resourceGlossaryTerm) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().DataZoneClient(ctx) + var state resourceGlossaryTermData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + in := &datazone.UpdateGlossaryTermInput{} + resp.Diagnostics.Append(flex.Expand(ctx, &state, in)...) + if resp.Diagnostics.HasError() { + return + } + in.Status = "DISABLED" + in.Identifier = state.Id.ValueStringPointer() + + _, err := conn.UpdateGlossaryTerm(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.DeleteGlossaryTermInput{ + DomainIdentifier: state.DomainIdentifier.ValueStringPointer(), + Identifier: state.Id.ValueStringPointer(), + } + + _, err2 := conn.DeleteGlossaryTerm(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 *resourceGlossaryTerm) 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)) + return + } + 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("glossary_identifier"), parts[2])...) +} + +func findGlossaryTermByID(ctx context.Context, conn *datazone.Client, id string, domain_id string) (*datazone.GetGlossaryTermOutput, error) { + in := &datazone.GetGlossaryTermInput{ + Identifier: aws.String(id), + DomainIdentifier: aws.String(domain_id), + } + + out, err := conn.GetGlossaryTerm(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 resourceGlossaryTermData struct { + GlossaryIdentifier types.String `tfsdk:"glossary_identifier"` + DomainIdentifier types.String `tfsdk:"domain_identifier"` + LongDescription types.String `tfsdk:"long_description"` + Name types.String `tfsdk:"name"` + ShortDescription types.String `tfsdk:"short_description"` + Status fwtypes.StringEnum[awstypes.GlossaryTermStatus] `tfsdk:"status"` + TermRelations fwtypes.ListNestedObjectValueOf[resourceTermRelationsData] `tfsdk:"term_relations"` + Id types.String `tfsdk:"id"` + + // from get + CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` + CreatedBy types.String `tfsdk:"created_by"` + UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"` + UpdatedBy types.String `tfsdk:"updated_by"` + + Timeouts timeouts.Value `tfsdk:"timeouts"` +} + +type resourceTermRelationsData struct { + Classifies fwtypes.ListValueOf[types.String] `tfsdk:"classifies"` + IsA fwtypes.ListValueOf[types.String] `tfsdk:"is_a"` +} diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go new file mode 100644 index 00000000000..2bbe0198316 --- /dev/null +++ b/internal/service/datazone/glossary_term_test.go @@ -0,0 +1,291 @@ +// 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" + "github.com/aws/aws-sdk-go-v2/service/datazone/types" + 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/names" +) + +func TestAccDataZoneGlossaryTerm_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var glossaryterm datazone.GetGlossaryTermOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + gName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resourceName := "aws_datazone_glossary_term.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGlossaryTermDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGlossaryTermConfig_basic(rName, gName, dName, pName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + resource.TestCheckResourceAttrSet(resourceName, "glossary_identifier"), + resource.TestCheckResourceAttr(resourceName, "long_description", "long_description"), + resource.TestCheckResourceAttr(resourceName, "short_description", "short_desc"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), + //resource.TestCheckResourceAttrSet(resourceName, "term_relations.classifies.#"), + //resource.TestCheckResourceAttrSet(resourceName, "term_relations.is_a.#"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), + resource.TestCheckResourceAttrSet(resourceName, "created_by"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + ImportStateIdFunc: testAccAuthorizerGlossaryTermImportStateIdFunc(resourceName), + }, + }, + }) +} +func TestAccDataZoneGlossaryTerm_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var glossaryterm1, glossaryterm2 datazone.GetGlossaryTermOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + gName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resourceName := "aws_datazone_glossary_term.test" + domainName := "aws_datazone_domain.test" + glossaryName := "aws_datazone_glossary.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGlossaryTermDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGlossaryTermConfig_basic(rName, gName, dName, pName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm1), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "glossary_identifier", glossaryName, "id"), + resource.TestCheckResourceAttr(resourceName, "long_description", "long_description"), + resource.TestCheckResourceAttr(resourceName, "short_description", "short_desc"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), + //resource.TestCheckResourceAttrSet(resourceName, "term_relations.classifies.#"), + //resource.TestCheckResourceAttrSet(resourceName, "term_relations.is_a.#"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), + resource.TestCheckResourceAttrSet(resourceName, "created_by"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "user"}, + ImportStateIdFunc: testAccAuthorizerGlossaryTermImportStateIdFunc(resourceName), + }, + { + Config: testAccGlossaryTermConfig_update(rName, gName, dName, pName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm2), + testAccCheckGlossaryTermNotRecreated(&glossaryterm1, &glossaryterm2), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + resource.TestCheckResourceAttrSet(resourceName, "glossary_identifier"), + resource.TestCheckResourceAttr(resourceName, "long_description", "long"), + resource.TestCheckResourceAttr(resourceName, "short_description", "short"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), + resource.TestCheckResourceAttrSet(resourceName, "created_by"), + resource.TestCheckResourceAttrSet(resourceName, "updated_by"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"updated_at"}, + ImportStateIdFunc: testAccAuthorizerGlossaryTermImportStateIdFunc(resourceName), + }, + }, + }) +} + +func TestAccDataZoneGlossaryTerm_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var glossaryterm datazone.GetGlossaryTermOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + gName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_glossary_term.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGlossaryTermDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGlossaryTermConfig_basic(rName, gName, dName, pName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceGlossaryTerm, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckGlossaryTermDestroy(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_term" { + continue + } + _, err := conn.GetGlossaryTerm(ctx, &datazone.GetGlossaryTermInput{ + Identifier: aws.String(rs.Primary.ID), + DomainIdentifier: aws.String(rs.Primary.Attributes["domain_identifier"]), + }) + if errs.IsA[*types.ResourceNotFoundException](err) || errs.IsA[*types.AccessDeniedException](err) { + return nil + } + if err != nil { + return create.Error(names.DataZone, create.ErrActionCheckingDestroyed, tfdatazone.ResNameGlossaryTerm, rs.Primary.ID, err) + } + + return create.Error(names.DataZone, create.ErrActionCheckingDestroyed, tfdatazone.ResNameGlossaryTerm, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccAuthorizerGlossaryTermImportStateIdFunc(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_identifier"], rs.Primary.ID, rs.Primary.Attributes["glossary_identifier"]}, ","), nil + } +} + +func testAccCheckGlossaryTermExists(ctx context.Context, name string, glossaryterm *datazone.GetGlossaryTermOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossaryTerm, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossaryTerm, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) + resp, err := conn.GetGlossaryTerm(ctx, &datazone.GetGlossaryTermInput{ + Identifier: aws.String(rs.Primary.ID), + DomainIdentifier: aws.String(rs.Primary.Attributes["domain_identifier"]), + }) + + if err != nil { + return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossaryTerm, rs.Primary.ID, err) + } + + *glossaryterm = *resp + + return nil + } +} + +func testAccCheckGlossaryTermNotRecreated(before, after *datazone.GetGlossaryTermOutput) 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.ResNameGlossaryTerm, before, errors.New("recreated")) + } + + return nil + } +} + +func testAccGlossaryTermConfig_basic(rName, gName, dName, pName string) string { + return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` + + +resource "aws_datazone_glossary_term" "test" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = %[1]q + short_description = "short_desc" + status = "ENABLED" +} +`, rName)) +} + +func testAccGlossaryTermConfig_update(rName, gName, dName, pName string) string { + return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` + + +resource "aws_datazone_glossary_term" "test" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long" + name = %[1]q + short_description = "short" + status = "ENABLED" +} +`, rName)) +} diff --git a/internal/service/datazone/service_package_gen.go b/internal/service/datazone/service_package_gen.go index 27d808e33a1..fc4f2737075 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: newResourceGlossary, Name: "Glossary", }, + { + Factory: newResourceGlossaryTerm, + Name: "Glossary Term", + }, { Factory: newResourceProject, Name: "Project", diff --git a/website/docs/r/datazone_glossary_term.html.markdown b/website/docs/r/datazone_glossary_term.html.markdown new file mode 100644 index 00000000000..6e08a2a72aa --- /dev/null +++ b/website/docs/r/datazone_glossary_term.html.markdown @@ -0,0 +1,75 @@ +--- +subcategory: "DataZone" +layout: "aws" +page_title: "AWS: aws_datazone_glossary_term" +description: |- + Terraform resource for managing an AWS DataZone Glossary Term. +--- +# Resource: aws_datazone_glossary_term + +Terraform resource for managing an AWS DataZone Glossary Term. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_datazone_glossary_term" "test" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = "example_name" + short_description = "short_desc" + status = "ENABLED" +} +``` + +## Argument Reference + +The following arguments are required: + +* `glossary_identifier` - (Required) Identifier of glossary. +* `domain_identifier` - (Required) Identifier of domain. +* `name` - (Required) Name of glossary term./ + +The following arguments are optional: + +* `long_description` - (Optional) Long description of entry. +* `short_description` - (Optional) Short description of entry. +* `status` - (Optional) If glossary term is ENABLED or DISABLED. +* `term_relations` - (Optional) Object classifying the term relations through the following attributes: + * `classifies` - (Optional) String array that calssifies the term relations. + * `is_as` - (Optional) The isA property of the term relations. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `id` - Id of the glossary term. +* `created_at` - Time of glossary term creation. +* `created_by` - Creator of glossary term. +* `updated_at` - Time of glossary term update. +* `updated_by` - Updater of glossary term. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import DataZone Glossary Term using a comma-delimited string combining the domain id, glossary term id, and the glossary id. For example: + +```terraform +import { + to = aws_datazone_glossary_term.example + id = "domain-id,glossary-term-id,glossary-id" +} +``` + +Using `terraform import`, import DataZone Glossary Term using a comma-delimited string combining the domain id, glossary term id, and the glossary id. For example: + +```console +% terraform import aws_datazone_glossary_term.example domain-id,glossary-term-id,glossary-id +``` From 011baaac932c10058f6211fec85207a18be1c25e Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 6 Aug 2024 10:23:30 -0400 Subject: [PATCH 2/8] Added validators --- internal/service/datazone/glossary_term.go | 24 +++++++++++-- .../service/datazone/glossary_term_test.go | 36 +++++++++++++------ .../r/datazone_glossary_term.html.markdown | 6 +++- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/internal/service/datazone/glossary_term.go b/internal/service/datazone/glossary_term.go index f5af9b65032..8ef723fe5b3 100644 --- a/internal/service/datazone/glossary_term.go +++ b/internal/service/datazone/glossary_term.go @@ -9,14 +9,18 @@ import ( "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-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "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/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" @@ -53,9 +57,15 @@ func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRe Attributes: map[string]schema.Attribute{ "domain_identifier": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexache.MustCompile(`^dzd[-_][a-zA-Z0-9_-]{1,36}$`), "must conform to: ^dzd[-_][a-zA-Z0-9_-]{1,36}$ "), + }, }, "glossary_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}$"), + }, }, names.AttrID: framework.IDAttribute(), "long_description": schema.StringAttribute{ @@ -63,6 +73,9 @@ func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRe }, names.AttrName: schema.StringAttribute{ Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 256), + }, }, "short_description": schema.StringAttribute{ Optional: true, @@ -89,17 +102,26 @@ func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRe Blocks: map[string]schema.Block{ "term_relations": schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[resourceTermRelationsData](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "classifies": schema.ListAttribute{ CustomType: fwtypes.ListOfStringType, ElementType: types.StringType, Optional: true, + Validators: []validator.List{ + listvalidator.SizeBetween(1, 10), + }, }, "is_a": schema.ListAttribute{ CustomType: fwtypes.ListOfStringType, ElementType: types.StringType, Optional: true, + Validators: []validator.List{ + listvalidator.SizeBetween(1, 10), + }, }, }, }, @@ -119,7 +141,6 @@ func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRe if resp.Diagnostics.HasError() { return } - in := &datazone.CreateGlossaryTermInput{} resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) if resp.Diagnostics.HasError() { @@ -166,7 +187,6 @@ func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRe func (r *resourceGlossaryTerm) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { conn := r.Meta().DataZoneClient(ctx) - var state resourceGlossaryTermData resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go index 2bbe0198316..9f45545818e 100644 --- a/internal/service/datazone/glossary_term_test.go +++ b/internal/service/datazone/glossary_term_test.go @@ -37,6 +37,10 @@ func TestAccDataZoneGlossaryTerm_basic(t *testing.T) { dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary_term.test" + glossaryName := "aws_datazone_glossary.test" + glossarySecond := "aws_datazone_glossary_term.second" + + domianName := "aws_datazone_domain.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -53,13 +57,14 @@ func TestAccDataZoneGlossaryTerm_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, "glossary_identifier"), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domianName, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "glossary_identifier", glossaryName, names.AttrID), resource.TestCheckResourceAttr(resourceName, "long_description", "long_description"), resource.TestCheckResourceAttr(resourceName, "short_description", "short_desc"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), - //resource.TestCheckResourceAttrSet(resourceName, "term_relations.classifies.#"), - //resource.TestCheckResourceAttrSet(resourceName, "term_relations.is_a.#"), + resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.classifies.0", glossarySecond, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.is_a.0", glossarySecond, names.AttrID), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, "created_by"), ), @@ -105,8 +110,8 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm1), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, "id"), - resource.TestCheckResourceAttrPair(resourceName, "glossary_identifier", glossaryName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "glossary_identifier", glossaryName, names.AttrID), resource.TestCheckResourceAttr(resourceName, "long_description", "long_description"), resource.TestCheckResourceAttr(resourceName, "short_description", "short_desc"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), @@ -235,11 +240,7 @@ func testAccCheckGlossaryTermExists(ctx context.Context, name string, glossaryte } conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) - resp, err := conn.GetGlossaryTerm(ctx, &datazone.GetGlossaryTermInput{ - Identifier: aws.String(rs.Primary.ID), - DomainIdentifier: aws.String(rs.Primary.Attributes["domain_identifier"]), - }) - + resp, err := tfdatazone.FindGlossaryTermByID(ctx, conn, rs.Primary.ID, rs.Primary.Attributes["domain_identifier"]) if err != nil { return create.Error(names.DataZone, create.ErrActionCheckingExistence, tfdatazone.ResNameGlossaryTerm, rs.Primary.ID, err) } @@ -264,6 +265,15 @@ func testAccGlossaryTermConfig_basic(rName, gName, dName, pName string) string { return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` +resource "aws_datazone_glossary_term" "second" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = %[2]q + short_description = "short_desc" + status = "ENABLED" +} + resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -271,8 +281,12 @@ resource "aws_datazone_glossary_term" "test" { name = %[1]q short_description = "short_desc" status = "ENABLED" + term_relations { + classifies = ["${aws_datazone_glossary_term.second.id}"] + is_a = ["${aws_datazone_glossary_term.second.id}"] + } } -`, rName)) +`, rName, gName)) } func testAccGlossaryTermConfig_update(rName, gName, dName, pName string) string { diff --git a/website/docs/r/datazone_glossary_term.html.markdown b/website/docs/r/datazone_glossary_term.html.markdown index 6e08a2a72aa..a595deda80e 100644 --- a/website/docs/r/datazone_glossary_term.html.markdown +++ b/website/docs/r/datazone_glossary_term.html.markdown @@ -18,9 +18,13 @@ resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id long_description = "long_description" - name = "example_name" + name = %[1]q short_description = "short_desc" status = "ENABLED" + term_relations { + classifies = ["id of other glossary term"] + is_a = ["id of other glossary term"] + } } ``` From cd607186676141ac336cca05eb6ed96ad460e4ba Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 6 Aug 2024 10:54:25 -0400 Subject: [PATCH 3/8] Changes to updating terms --- internal/service/datazone/glossary_term.go | 6 ++--- .../service/datazone/glossary_term_test.go | 24 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/internal/service/datazone/glossary_term.go b/internal/service/datazone/glossary_term.go index 8ef723fe5b3..50ffded022d 100644 --- a/internal/service/datazone/glossary_term.go +++ b/internal/service/datazone/glossary_term.go @@ -224,7 +224,7 @@ func (r *resourceGlossaryTerm) Update(ctx context.Context, req resource.UpdateRe } if !plan.ShortDescription.Equal(state.ShortDescription) || !plan.LongDescription.Equal(state.LongDescription) || !plan.Name.Equal(state.Name) || !plan.Status.Equal(state.Status) || - !plan.Name.Equal(state.Name) { + !plan.TermRelations.Equal(state.TermRelations) { in := &datazone.UpdateGlossaryTermInput{} resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) if resp.Diagnostics.HasError() { @@ -263,9 +263,9 @@ func (r *resourceGlossaryTerm) Delete(ctx context.Context, req resource.DeleteRe if resp.Diagnostics.HasError() { return } - + option := flex.WithIgnoredFieldNames([]string{"TermRelations"}) in := &datazone.UpdateGlossaryTermInput{} - resp.Diagnostics.Append(flex.Expand(ctx, &state, in)...) + resp.Diagnostics.Append(flex.Expand(ctx, &state, in, option)...) if resp.Diagnostics.HasError() { return } diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go index 9f45545818e..fff59b43860 100644 --- a/internal/service/datazone/glossary_term_test.go +++ b/internal/service/datazone/glossary_term_test.go @@ -291,8 +291,22 @@ resource "aws_datazone_glossary_term" "test" { func testAccGlossaryTermConfig_update(rName, gName, dName, pName string) string { return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` - - +resource "aws_datazone_glossary_term" "second" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = %[2]q + short_description = "short_desc" + status = "ENABLED" +} + resource "aws_datazone_glossary_term" "third" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = %[3]q + short_description = "short_desc" + status = "ENABLED" +} resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -300,6 +314,10 @@ resource "aws_datazone_glossary_term" "test" { name = %[1]q short_description = "short" status = "ENABLED" + term_relations { + classifies = ["${aws_datazone_glossary_term.third.id}"] + is_a = ["${aws_datazone_glossary_term.third.id}"] + } } -`, rName)) +`, rName, gName, dName)) } From f523209bded9faae7a375d09a6a0c57f7be8a4df Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 6 Aug 2024 11:35:21 -0400 Subject: [PATCH 4/8] CI changes --- .../service/datazone/glossary_term_test.go | 8 +- .../r/datazone_glossary_term.html.markdown | 88 ++++++++++++++++++- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go index fff59b43860..bae8d17446d 100644 --- a/internal/service/datazone/glossary_term_test.go +++ b/internal/service/datazone/glossary_term_test.go @@ -265,6 +265,8 @@ func testAccGlossaryTermConfig_basic(rName, gName, dName, pName string) string { return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` + + resource "aws_datazone_glossary_term" "second" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -283,7 +285,7 @@ resource "aws_datazone_glossary_term" "test" { status = "ENABLED" term_relations { classifies = ["${aws_datazone_glossary_term.second.id}"] - is_a = ["${aws_datazone_glossary_term.second.id}"] + is_a = ["${aws_datazone_glossary_term.second.id}"] } } `, rName, gName)) @@ -299,7 +301,7 @@ resource "aws_datazone_glossary_term" "second" { short_description = "short_desc" status = "ENABLED" } - resource "aws_datazone_glossary_term" "third" { +resource "aws_datazone_glossary_term" "third" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id long_description = "long_description" @@ -316,7 +318,7 @@ resource "aws_datazone_glossary_term" "test" { status = "ENABLED" term_relations { classifies = ["${aws_datazone_glossary_term.third.id}"] - is_a = ["${aws_datazone_glossary_term.third.id}"] + is_a = ["${aws_datazone_glossary_term.third.id}"] } } `, rName, gName, dName)) diff --git a/website/docs/r/datazone_glossary_term.html.markdown b/website/docs/r/datazone_glossary_term.html.markdown index a595deda80e..2cf0c8c2a89 100644 --- a/website/docs/r/datazone_glossary_term.html.markdown +++ b/website/docs/r/datazone_glossary_term.html.markdown @@ -10,6 +10,86 @@ description: |- Terraform resource for managing an AWS DataZone Glossary Term. ## 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" { + description = "description" + name = "example_name" + owning_project_identifier = aws_datazone_project.test.id + status = "DISABLED" + domain_identifier = aws_datazone_project.test.domain_identifier +} +resource "aws_datazone_glossary_term" "test" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = "example-name" + short_description = "short_desc" + status = "ENABLED" + term_relations { + classifies = ["id of other glossary term"] + is_a = ["id of other glossary term"] + } +} +``` ### Basic Usage @@ -18,12 +98,12 @@ resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id long_description = "long_description" - name = %[1]q + name = "example-name" short_description = "short_desc" status = "ENABLED" term_relations { classifies = ["id of other glossary term"] - is_a = ["id of other glossary term"] + is_a = ["id of other glossary term"] } } ``` @@ -42,8 +122,8 @@ The following arguments are optional: * `short_description` - (Optional) Short description of entry. * `status` - (Optional) If glossary term is ENABLED or DISABLED. * `term_relations` - (Optional) Object classifying the term relations through the following attributes: - * `classifies` - (Optional) String array that calssifies the term relations. - * `is_as` - (Optional) The isA property of the term relations. + * `classifies` - (Optional) String array that calssifies the term relations. + * `is_as` - (Optional) The isA property of the term relations. ## Attribute Reference From 624ff51af3bb883e8579bd92153c4eb5d3d788fe Mon Sep 17 00:00:00 2001 From: ThomasZalewski Date: Tue, 6 Aug 2024 11:38:34 -0400 Subject: [PATCH 5/8] doc changes --- website/docs/r/datazone_glossary_term.html.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/website/docs/r/datazone_glossary_term.html.markdown b/website/docs/r/datazone_glossary_term.html.markdown index 2cf0c8c2a89..0ae70aae46f 100644 --- a/website/docs/r/datazone_glossary_term.html.markdown +++ b/website/docs/r/datazone_glossary_term.html.markdown @@ -10,6 +10,7 @@ description: |- Terraform resource for managing an AWS DataZone Glossary Term. ## Example Usage + ```terraform resource "aws_iam_role" "domain_execution_role" { name = "example_name" @@ -86,7 +87,7 @@ resource "aws_datazone_glossary_term" "test" { status = "ENABLED" term_relations { classifies = ["id of other glossary term"] - is_a = ["id of other glossary term"] + is_a = ["id of other glossary term"] } } ``` @@ -103,7 +104,7 @@ resource "aws_datazone_glossary_term" "test" { status = "ENABLED" term_relations { classifies = ["id of other glossary term"] - is_a = ["id of other glossary term"] + is_a = ["id of other glossary term"] } } ``` From 3e3ef5922cc3f040e2a82e9ed41483bd53e39267 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 13 Aug 2024 16:12:48 -0400 Subject: [PATCH 6/8] cleanup schmea --- internal/service/datazone/glossary_term.go | 184 ++++++++++-------- .../service/datazone/glossary_term_test.go | 22 +-- 2 files changed, 112 insertions(+), 94 deletions(-) diff --git a/internal/service/datazone/glossary_term.go b/internal/service/datazone/glossary_term.go index 50ffded022d..3acd7079b73 100644 --- a/internal/service/datazone/glossary_term.go +++ b/internal/service/datazone/glossary_term.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "strings" + "time" "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" @@ -16,10 +17,13 @@ import ( "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "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" @@ -36,6 +40,8 @@ import ( // @FrameworkResource("aws_datazone_glossary_term", name="Glossary Term") func newResourceGlossaryTerm(_ context.Context) (resource.ResourceWithConfigure, error) { r := &resourceGlossaryTerm{} + r.SetDefaultCreateTimeout(30 * time.Second) + return r, nil } @@ -55,6 +61,19 @@ func (r *resourceGlossaryTerm) Metadata(_ context.Context, req resource.Metadata func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ + names.AttrCreatedAt: schema.StringAttribute{ + CustomType: timetypes.RFC3339Type{}, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "created_by": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, "domain_identifier": schema.StringAttribute{ Optional: true, Validators: []validator.String{ @@ -84,20 +103,6 @@ func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRe CustomType: fwtypes.StringEnumType[awstypes.GlossaryTermStatus](), Optional: true, }, - names.AttrCreatedAt: schema.StringAttribute{ - CustomType: timetypes.RFC3339Type{}, - Computed: true, - }, - "updated_at": schema.StringAttribute{ - CustomType: timetypes.RFC3339Type{}, - Computed: true, - }, - "created_by": schema.StringAttribute{ - Computed: true, - }, - "updated_by": schema.StringAttribute{ - Computed: true, - }, }, Blocks: map[string]schema.Block{ "term_relations": schema.ListNestedBlock{ @@ -107,20 +112,18 @@ func (r *resourceGlossaryTerm) Schema(ctx context.Context, req resource.SchemaRe }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ - "classifies": schema.ListAttribute{ - CustomType: fwtypes.ListOfStringType, - ElementType: types.StringType, - Optional: true, - Validators: []validator.List{ - listvalidator.SizeBetween(1, 10), + "classifies": schema.SetAttribute{ + CustomType: fwtypes.SetOfStringType, + Optional: true, + Validators: []validator.Set{ + setvalidator.SizeBetween(1, 10), }, }, - "is_a": schema.ListAttribute{ - CustomType: fwtypes.ListOfStringType, - ElementType: types.StringType, - Optional: true, - Validators: []validator.List{ - listvalidator.SizeBetween(1, 10), + "is_a": schema.SetAttribute{ + CustomType: fwtypes.SetOfStringType, + Optional: true, + Validators: []validator.Set{ + setvalidator.SizeBetween(1, 10), }, }, }, @@ -141,12 +144,15 @@ func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRe if resp.Diagnostics.HasError() { return } + in := &datazone.CreateGlossaryTermInput{} resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) if resp.Diagnostics.HasError() { return } + out, err := conn.CreateGlossaryTerm(ctx, in) + if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameGlossary, plan.Name.String(), err), @@ -154,6 +160,7 @@ func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRe ) return } + if out == nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameGlossary, plan.Name.String(), nil), @@ -166,10 +173,12 @@ func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRe if resp.Diagnostics.HasError() { return } + createTimeout := r.CreateTimeout(ctx, plan.Timeouts) outputRaws, err := tfresource.RetryWhenNotFound(ctx, createTimeout, func() (interface{}, error) { return findGlossaryTermByID(ctx, conn, *out.Id, *out.DomainId) }) + if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameGlossaryTerm, plan.Name.String(), err), @@ -177,11 +186,14 @@ func (r *resourceGlossaryTerm) Create(ctx context.Context, req resource.CreateRe ) return } + output := outputRaws.(*datazone.GetGlossaryTermOutput) resp.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + if resp.Diagnostics.HasError() { return } + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } @@ -193,23 +205,26 @@ func (r *resourceGlossaryTerm) Read(ctx context.Context, req resource.ReadReques return } - out, err := findGlossaryTermByID(ctx, conn, state.Id.ValueString(), state.DomainIdentifier.ValueString()) + out, err := findGlossaryTermByID(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), + 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)...) } @@ -223,37 +238,41 @@ func (r *resourceGlossaryTerm) Update(ctx context.Context, req resource.UpdateRe return } - if !plan.ShortDescription.Equal(state.ShortDescription) || !plan.LongDescription.Equal(state.LongDescription) || !plan.Name.Equal(state.Name) || !plan.Status.Equal(state.Status) || - !plan.TermRelations.Equal(state.TermRelations) { + if !plan.ShortDescription.Equal(state.ShortDescription) || !plan.LongDescription.Equal(state.LongDescription) || !plan.Name.Equal(state.Name) || + !plan.Status.Equal(state.Status) || !plan.TermRelations.Equal(state.TermRelations) { in := &datazone.UpdateGlossaryTermInput{} resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...) + if resp.Diagnostics.HasError() { return } - in.Identifier = plan.Id.ValueStringPointer() + + in.Identifier = plan.ID.ValueStringPointer() out, err := conn.UpdateGlossaryTerm(ctx, in) if err != nil { resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.DataZone, create.ErrActionUpdating, ResNameProject, plan.Id.String(), err), + 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), + create.ProblemStandardMessage(names.DataZone, create.ErrActionUpdating, ResNameProject, plan.ID.String(), nil), errors.New("empty output from glossary term update").Error(), ) return } - resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &plan)...) + if resp.Diagnostics.HasError() { return } } - resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } func (r *resourceGlossaryTerm) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { @@ -263,43 +282,50 @@ func (r *resourceGlossaryTerm) Delete(ctx context.Context, req resource.DeleteRe if resp.Diagnostics.HasError() { return } - option := flex.WithIgnoredFieldNames([]string{"TermRelations"}) - in := &datazone.UpdateGlossaryTermInput{} - resp.Diagnostics.Append(flex.Expand(ctx, &state, in, option)...) - if resp.Diagnostics.HasError() { - return + + if state.Status.ValueEnum() == awstypes.GlossaryTermStatusEnabled { + option := flex.WithIgnoredFieldNames([]string{"TermRelations"}) + in := &datazone.UpdateGlossaryTermInput{} + resp.Diagnostics.Append(flex.Expand(ctx, &state, in, option)...) + if resp.Diagnostics.HasError() { + return + } + + in.Status = awstypes.GlossaryTermStatusDisabled + in.Identifier = state.ID.ValueStringPointer() + + _, err := conn.UpdateGlossaryTerm(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 + } } - in.Status = "DISABLED" - in.Identifier = state.Id.ValueStringPointer() - _, err := conn.UpdateGlossaryTerm(ctx, in) + in := &datazone.DeleteGlossaryTermInput{ + DomainIdentifier: state.DomainIdentifier.ValueStringPointer(), + Identifier: state.ID.ValueStringPointer(), + } + + _, err := conn.DeleteGlossaryTerm(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), + create.ProblemStandardMessage(names.DataZone, create.ErrActionDeleting, ResNameGlossary, state.ID.String(), err), err.Error(), ) return } - - in2 := &datazone.DeleteGlossaryTermInput{ - DomainIdentifier: state.DomainIdentifier.ValueStringPointer(), - Identifier: state.Id.ValueStringPointer(), - } - - _, err2 := conn.DeleteGlossaryTerm(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 *resourceGlossaryTerm) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { @@ -314,21 +340,22 @@ func (r *resourceGlossaryTerm) ImportState(ctx context.Context, req resource.Imp resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("glossary_identifier"), parts[2])...) } -func findGlossaryTermByID(ctx context.Context, conn *datazone.Client, id string, domain_id string) (*datazone.GetGlossaryTermOutput, error) { +func findGlossaryTermByID(ctx context.Context, conn *datazone.Client, id string, domainID string) (*datazone.GetGlossaryTermOutput, error) { in := &datazone.GetGlossaryTermInput{ Identifier: aws.String(id), - DomainIdentifier: aws.String(domain_id), + DomainIdentifier: aws.String(domainID), } out, err := conn.GetGlossaryTerm(ctx, in) - if err != nil { - if errs.IsA[*awstypes.ResourceNotFoundException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, } + } + if err != nil { return nil, err } @@ -340,25 +367,20 @@ func findGlossaryTermByID(ctx context.Context, conn *datazone.Client, id string, } type resourceGlossaryTermData struct { - GlossaryIdentifier types.String `tfsdk:"glossary_identifier"` + CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` + CreatedBy types.String `tfsdk:"created_by"` DomainIdentifier types.String `tfsdk:"domain_identifier"` + GlossaryIdentifier types.String `tfsdk:"glossary_identifier"` LongDescription types.String `tfsdk:"long_description"` Name types.String `tfsdk:"name"` ShortDescription types.String `tfsdk:"short_description"` Status fwtypes.StringEnum[awstypes.GlossaryTermStatus] `tfsdk:"status"` TermRelations fwtypes.ListNestedObjectValueOf[resourceTermRelationsData] `tfsdk:"term_relations"` - Id types.String `tfsdk:"id"` - - // from get - CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` - CreatedBy types.String `tfsdk:"created_by"` - UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"` - UpdatedBy types.String `tfsdk:"updated_by"` - - Timeouts timeouts.Value `tfsdk:"timeouts"` + ID types.String `tfsdk:"id"` + Timeouts timeouts.Value `tfsdk:"timeouts"` } type resourceTermRelationsData struct { - Classifies fwtypes.ListValueOf[types.String] `tfsdk:"classifies"` - IsA fwtypes.ListValueOf[types.String] `tfsdk:"is_a"` + Classifies fwtypes.SetValueOf[types.String] `tfsdk:"classifies"` + IsA fwtypes.SetValueOf[types.String] `tfsdk:"is_a"` } diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go index bae8d17446d..e860941b081 100644 --- a/internal/service/datazone/glossary_term_test.go +++ b/internal/service/datazone/glossary_term_test.go @@ -116,8 +116,6 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "short_description", "short_desc"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), - //resource.TestCheckResourceAttrSet(resourceName, "term_relations.classifies.#"), - //resource.TestCheckResourceAttrSet(resourceName, "term_relations.is_a.#"), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, "created_by"), ), @@ -142,15 +140,13 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, "created_by"), - resource.TestCheckResourceAttrSet(resourceName, "updated_by"), ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"updated_at"}, - ImportStateIdFunc: testAccAuthorizerGlossaryTermImportStateIdFunc(resourceName), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerGlossaryTermImportStateIdFunc(resourceName), }, }, }) @@ -203,9 +199,11 @@ func testAccCheckGlossaryTermDestroy(ctx context.Context) resource.TestCheckFunc Identifier: aws.String(rs.Primary.ID), DomainIdentifier: aws.String(rs.Primary.Attributes["domain_identifier"]), }) + if errs.IsA[*types.ResourceNotFoundException](err) || errs.IsA[*types.AccessDeniedException](err) { - return nil + continue } + if err != nil { return create.Error(names.DataZone, create.ErrActionCheckingDestroyed, tfdatazone.ResNameGlossaryTerm, rs.Primary.ID, err) } @@ -263,10 +261,6 @@ func testAccCheckGlossaryTermNotRecreated(before, after *datazone.GetGlossaryTer func testAccGlossaryTermConfig_basic(rName, gName, dName, pName string) string { return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` - - - - resource "aws_datazone_glossary_term" "second" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -301,6 +295,7 @@ resource "aws_datazone_glossary_term" "second" { short_description = "short_desc" status = "ENABLED" } + resource "aws_datazone_glossary_term" "third" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -309,6 +304,7 @@ resource "aws_datazone_glossary_term" "third" { short_description = "short_desc" status = "ENABLED" } + resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id From 88c608a7670f08bd62dddd27edcd704031ef2350 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 13 Aug 2024 16:23:11 -0400 Subject: [PATCH 7/8] tweak documentation --- .../service/datazone/glossary_term_test.go | 4 +- .../r/datazone_glossary_term.html.markdown | 73 ++++++------------- 2 files changed, 26 insertions(+), 51 deletions(-) diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go index e860941b081..a9a0b9605b6 100644 --- a/internal/service/datazone/glossary_term_test.go +++ b/internal/service/datazone/glossary_term_test.go @@ -313,8 +313,8 @@ resource "aws_datazone_glossary_term" "test" { short_description = "short" status = "ENABLED" term_relations { - classifies = ["${aws_datazone_glossary_term.third.id}"] - is_a = ["${aws_datazone_glossary_term.third.id}"] + classifies = [aws_datazone_glossary_term.third.id] + is_a = [aws_datazone_glossary_term.third.id] } } `, rName, gName, dName)) diff --git a/website/docs/r/datazone_glossary_term.html.markdown b/website/docs/r/datazone_glossary_term.html.markdown index 0ae70aae46f..91a4e171883 100644 --- a/website/docs/r/datazone_glossary_term.html.markdown +++ b/website/docs/r/datazone_glossary_term.html.markdown @@ -12,8 +12,8 @@ Terraform resource for managing an AWS DataZone Glossary Term. ## Example Usage ```terraform -resource "aws_iam_role" "domain_execution_role" { - name = "example_name" +resource "aws_iam_role" "example" { + name = "example" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ @@ -35,7 +35,7 @@ resource "aws_iam_role" "domain_execution_role" { }) inline_policy { - name = "example_name" + name = "example" policy = jsonencode({ Version = "2012-10-17" Statement = [ @@ -54,58 +54,35 @@ resource "aws_iam_role" "domain_execution_role" { } } -resource "aws_datazone_domain" "test" { +resource "aws_datazone_domain" "example" { name = "example_name" - domain_execution_role = aws_iam_role.domain_execution_role.arn + domain_execution_role = aws_iam_role.example.arn } -resource "aws_security_group" "test" { +resource "aws_security_group" "example" { name = "example_name" } -resource "aws_datazone_project" "test" { - domain_identifier = aws_datazone_domain.test.id +resource "aws_datazone_project" "example" { + domain_identifier = aws_datazone_domain.example.id glossary_terms = ["2N8w6XJCwZf"] - name = "example_name" - description = "desc" + name = "example" skip_deletion_check = true } -resource "aws_datazone_glossary" "test" { +resource "aws_datazone_glossary" "example" { description = "description" - name = "example_name" - owning_project_identifier = aws_datazone_project.test.id - status = "DISABLED" - domain_identifier = aws_datazone_project.test.domain_identifier + name = "example" + owning_project_identifier = aws_datazone_project.example.id + status = "ENABLED" + domain_identifier = aws_datazone_project.example.domain_identifier } -resource "aws_datazone_glossary_term" "test" { - domain_identifier = aws_datazone_domain.test.id - glossary_identifier = aws_datazone_glossary.test.id - long_description = "long_description" - name = "example-name" - short_description = "short_desc" - status = "ENABLED" - term_relations { - classifies = ["id of other glossary term"] - is_a = ["id of other glossary term"] - } -} -``` -### Basic Usage - -```terraform -resource "aws_datazone_glossary_term" "test" { - domain_identifier = aws_datazone_domain.test.id - glossary_identifier = aws_datazone_glossary.test.id - long_description = "long_description" - name = "example-name" - short_description = "short_desc" +resource "aws_datazone_glossary_term" "example" { + domain_identifier = aws_datazone_domain.example.id + glossary_identifier = aws_datazone_glossary.example.id + name = "example" status = "ENABLED" - term_relations { - classifies = ["id of other glossary term"] - is_a = ["id of other glossary term"] - } } ``` @@ -113,9 +90,9 @@ resource "aws_datazone_glossary_term" "test" { The following arguments are required: -* `glossary_identifier` - (Required) Identifier of glossary. * `domain_identifier` - (Required) Identifier of domain. -* `name` - (Required) Name of glossary term./ +* `glossary_identifier` - (Required) Identifier of glossary. +* `name` - (Required) Name of glossary term. The following arguments are optional: @@ -133,27 +110,25 @@ This resource exports the following attributes in addition to the arguments abov * `id` - Id of the glossary term. * `created_at` - Time of glossary term creation. * `created_by` - Creator of glossary term. -* `updated_at` - Time of glossary term update. -* `updated_by` - Updater of glossary term. ## Timeouts [Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): -* `create` - (Default `30m`) +* `create` - (Default `30s`) ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import DataZone Glossary Term using a comma-delimited string combining the domain id, glossary term id, and the glossary id. For example: +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import DataZone Glossary Term using a comma-delimited string combining the `domain_identifier`, `id`, and the `glossary_identifier`. For example: ```terraform import { to = aws_datazone_glossary_term.example - id = "domain-id,glossary-term-id,glossary-id" + id = "domain_identifier,id,glossary_identifier" } ``` -Using `terraform import`, import DataZone Glossary Term using a comma-delimited string combining the domain id, glossary term id, and the glossary id. For example: +Using `terraform import`, import DataZone Glossary Term using a comma-delimited string combining the `domain_identifier`, `id`, and the `glossary_identifier`. For example: ```console % terraform import aws_datazone_glossary_term.example domain-id,glossary-term-id,glossary-id From 4b6b41b035dae0f8b4d9a41ae302c8e296ee2a4a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 13 Aug 2024 16:26:22 -0400 Subject: [PATCH 8/8] add CHANGELOG entry --- .changelog/38706.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changelog/38706.txt diff --git a/.changelog/38706.txt b/.changelog/38706.txt new file mode 100644 index 00000000000..338914b8ea8 --- /dev/null +++ b/.changelog/38706.txt @@ -0,0 +1,4 @@ + +```release-note:new-resource +aws_datazone_glossary_term +``` \ No newline at end of file