Skip to content

add aws_dataexchange_event_action #40552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a1f1c63
add aws_dataexchange_job
TSKnuhtsen Dec 13, 2024
7984b27
aws_dataexchange_event_action
TSKnuhtsen Dec 13, 2024
2476243
Addresses review comments for aws_dataexchange_event_action
TSKnuhtsen Dec 30, 2024
8f805b0
pass DataSetID as ENV variable + linters
TSKnuhtsen Jan 15, 2025
6a5a801
Removes manually-created `Metadata` function
gdavison Feb 27, 2025
7414ce0
Uses constants for attribute names
gdavison Feb 27, 2025
0e29746
Moves API inputs off heap
gdavison Feb 27, 2025
41fe780
Regenerates service package
gdavison Feb 27, 2025
e24a604
Markdown cleanup
gdavison Feb 27, 2025
0f97640
Documentation `terrafmt`
gdavison Feb 27, 2025
263cc19
Uses `aws_s3_bucket` `bucket` instead of `id`
gdavison Feb 27, 2025
e93f4e1
Uses `aws_s3_bucket` `bucket` instead of `id` in tests
gdavison Feb 27, 2025
955cc97
Retrieves identity using `aws_caller_identity` data source
gdavison Feb 27, 2025
7a5192f
Fixes `Exists` check calls
gdavison Feb 27, 2025
6c52744
Fixes format verbs
gdavison Feb 27, 2025
02a15c6
Adds missing value checks
gdavison Feb 27, 2025
a35b20d
Removes unneeded values
gdavison Feb 27, 2025
64f9f01
Runs tests in parallel
gdavison Feb 27, 2025
63859e6
Updates test to use non-default `key_pattern`
gdavison Feb 27, 2025
18a2aab
Uses standard bucket naming in tests
gdavison Feb 27, 2025
ffacc4b
Adds test steps for removing encryption or key pattern
gdavison Feb 27, 2025
e1b69e9
Renames encryption tests
gdavison Feb 27, 2025
278863e
API call tweaks
gdavison Feb 27, 2025
f559165
Updates to standard variable names
gdavison Feb 27, 2025
256474c
Adds missing `created_at` and `updated_at` attributes
gdavison Feb 27, 2025
79993f3
Doesn't export `findEventActionByID`
gdavison Feb 27, 2025
c492a0c
Replaces `ComposeTestCheckFunc` with `ComposeAggregateTestCheckFunc`
gdavison Feb 28, 2025
dc024b6
Fixes schema to use `ListNestedBlock` instead of `SingleNestedBlock`
gdavison Feb 28, 2025
a6f7b4c
Allocates input on stack instead of heap
gdavison Feb 28, 2025
0d5f535
Recreates resource if `event.revision_published.data_set_id` changed
gdavison Feb 28, 2025
fccae73
Updates documentation
gdavison Feb 28, 2025
ad55df0
Removes timeouts, as API requests are synchronous and quick
gdavison Feb 28, 2025
293e1d9
Adds `TF_AWS_DATAEXCHANGE_DATA_SET_ID` to list of testing environment…
gdavison Feb 28, 2025
4927516
Alphabetizes struct fields
gdavison Feb 28, 2025
c91b12d
Adds missing `created_at` and `updated_at` to documentation
gdavison Feb 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/40552.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_dataexchange_event_action
```
1 change: 1 addition & 0 deletions docs/acc-test-environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Environment variables (beyond standard AWS Go SDK ones) used by acceptance testi
| `TF_ACC` | Enables Go tests containing `resource.Test()` and `resource.ParallelTest()`. |
| `TF_ACC_ASSUME_ROLE_ARN` | Amazon Resource Name of existing IAM Role to use for limited permissions acceptance testing. |
| `TF_AWS_BEDROCK_OSS_COLLECTION_NAME` | Name of the OpenSearch Serverless collection to be used with an Amazon Bedrock Knowledge Base. |
| `TF_AWS_DATAEXCHANGE_DATA_SET_ID` | ID of DataExchange Data Set to use for testing. |
| `TF_AWS_LICENSE_MANAGER_GRANT_HOME_REGION` | Region where a License Manager license is imported. |
| `TF_AWS_LICENSE_MANAGER_GRANT_LICENSE_ARN` | ARN for a License Manager license imported into the current account. |
| `TF_AWS_LICENSE_MANAGER_GRANT_PRINCIPAL` | ARN of a principal to share the License Manager license with. Either a root user, Organization, or Organizational Unit. |
Expand Down
352 changes: 352 additions & 0 deletions internal/service/dataexchange/event_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package dataexchange

import (
"context"
"errors"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/dataexchange"
awstypes "github.com/aws/aws-sdk-go-v2/service/dataexchange/types"
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
"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/stringdefault"
"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/framework/validators"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @FrameworkResource("aws_dataexchange_event_action", name="Event Action")
func ResourceEventAction(_ context.Context) (resource.ResourceWithConfigure, error) {
return &resourceEventAction{}, nil
}

const (
ResNameEventAction = "Event Action"
)

type resourceEventAction struct {
framework.ResourceWithConfigure
framework.WithTimeouts
}

func (r *resourceEventAction) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
names.AttrARN: framework.ARNAttributeComputedOnly(),
names.AttrCreatedAt: schema.StringAttribute{
CustomType: timetypes.RFC3339Type{},
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
names.AttrID: framework.IDAttribute(),
"updated_at": schema.StringAttribute{
CustomType: timetypes.RFC3339Type{},
Computed: true,
},
},
Blocks: map[string]schema.Block{
names.AttrAction: schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[actionModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Blocks: map[string]schema.Block{
"export_revision_to_s3": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[autoExportRevisionToS3RequestDetailsModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Blocks: map[string]schema.Block{
"encryption": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[actionS3Encryption](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
names.AttrKMSKeyARN: schema.StringAttribute{
CustomType: fwtypes.ARNType,
Optional: true,
Validators: []validator.String{
validators.ARN(),
},
},
names.AttrType: schema.StringAttribute{
Optional: true,
CustomType: fwtypes.StringEnumType[awstypes.ServerSideEncryptionTypes](),
},
},
},
},
"revision_destination": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[autoExportRevisionDestinationEntryModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
names.AttrBucket: schema.StringAttribute{
Required: true,
},
"key_pattern": schema.StringAttribute{
Optional: true,
Computed: true,
Default: stringdefault.StaticString("${Revision.CreatedAt}/${Asset.Name}"),
},
},
},
},
},
},
},
},
},
},
"event": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[eventModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Blocks: map[string]schema.Block{
"revision_published": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[revisionPublishedModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"data_set_id": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
},
},
},
},
},
},
},
}
}

func (r *resourceEventAction) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
conn := r.Meta().DataExchangeClient(ctx)

var plan resourceEventActionModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}

input := dataexchange.CreateEventActionInput{}
resp.Diagnostics.Append(flex.Expand(ctx, plan, &input)...)
if resp.Diagnostics.HasError() {
return
}

out, err := conn.CreateEventAction(ctx, &input)
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataExchange, create.ErrActionCreating, ResNameEventAction, "", err),
err.Error(),
)
return
}
if out == nil || out.Id == nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataExchange, create.ErrActionCreating, ResNameEventAction, "", 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 *resourceEventAction) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
conn := r.Meta().DataExchangeClient(ctx)

var state resourceEventActionModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

out, err := findEventActionByID(ctx, conn, state.ID.ValueString())
if tfresource.NotFound(err) {
resp.State.RemoveResource(ctx)
return
}
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataExchange, create.ErrActionSetting, ResNameEventAction, 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 *resourceEventAction) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
conn := r.Meta().DataExchangeClient(ctx)

var plan, state resourceEventActionModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

input := dataexchange.UpdateEventActionInput{}
resp.Diagnostics.Append(flex.Expand(ctx, plan, &input, flex.WithFieldNamePrefix("EventAction"))...)
if resp.Diagnostics.HasError() {
return
}

out, err := conn.UpdateEventAction(ctx, &input)
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataExchange, create.ErrActionUpdating, ResNameEventAction, plan.ID.String(), err),
err.Error(),
)
return
}
if out == nil || out.Id == nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataExchange, create.ErrActionUpdating, ResNameEventAction, plan.ID.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 *resourceEventAction) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
conn := r.Meta().DataExchangeClient(ctx)

var state resourceEventActionModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

input := dataexchange.DeleteEventActionInput{
EventActionId: state.ID.ValueStringPointer(),
}
_, err := conn.DeleteEventAction(ctx, &input)
if err != nil {
if errs.IsA[*awstypes.ResourceNotFoundException](err) {
return
}

resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataExchange, create.ErrActionDeleting, ResNameEventAction, state.ID.String(), err),
err.Error(),
)
return
}
}

func (r *resourceEventAction) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root(names.AttrID), req, resp)
}

func findEventActionByID(ctx context.Context, conn *dataexchange.Client, id string) (*dataexchange.GetEventActionOutput, error) {
input := dataexchange.GetEventActionInput{
EventActionId: aws.String(id),
}

out, err := conn.GetEventAction(ctx, &input)
if err != nil {
if errs.IsA[*awstypes.ResourceNotFoundException](err) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

return nil, err
}

if out == nil || out.Id == nil {
return nil, tfresource.NewEmptyResultError(&input)
}

return out, nil
}

type resourceEventActionModel struct {
Action fwtypes.ListNestedObjectValueOf[actionModel] `tfsdk:"action"`
ARN types.String `tfsdk:"arn"`
CreatedAt timetypes.RFC3339 `tfsdk:"created_at"`
Event fwtypes.ListNestedObjectValueOf[eventModel] `tfsdk:"event"`
ID types.String `tfsdk:"id"`
UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"`
}

type actionModel struct {
ExportRevisionToS3 fwtypes.ListNestedObjectValueOf[autoExportRevisionToS3RequestDetailsModel] `tfsdk:"export_revision_to_s3"`
}

type autoExportRevisionToS3RequestDetailsModel struct {
Encryption fwtypes.ListNestedObjectValueOf[actionS3Encryption] `tfsdk:"encryption"`
RevisionDestination fwtypes.ListNestedObjectValueOf[autoExportRevisionDestinationEntryModel] `tfsdk:"revision_destination"`
}

type autoExportRevisionDestinationEntryModel struct {
Bucket types.String `tfsdk:"bucket"`
KeyPattern types.String `tfsdk:"key_pattern"`
}

type actionS3Encryption struct {
KmsKeyArn types.String `tfsdk:"kms_key_arn"`
Type fwtypes.StringEnum[awstypes.ServerSideEncryptionTypes] `tfsdk:"type"`
}

type eventModel struct {
RevisionPublished fwtypes.ListNestedObjectValueOf[revisionPublishedModel] `tfsdk:"revision_published"`
}

type revisionPublishedModel struct {
DataSetId types.String `tfsdk:"data_set_id"`
}
Loading
Loading