Skip to content

Commit

Permalink
Merge branch 'f/datazone-form-type-resource' of github.com:hashicorp/…
Browse files Browse the repository at this point in the history
…terraform-provider-aws into f/datazone-form-type-resource

Merge conflicts
  • Loading branch information
ThomasZalewski committed Aug 7, 2024
2 parents 6ed0de6 + 98a27b0 commit bfe748e
Show file tree
Hide file tree
Showing 6 changed files with 670 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/38668.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_datazone_form_type
```
2 changes: 2 additions & 0 deletions internal/service/datazone/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ var (
ResourceProject = newResourceProject
ResourceGlossary = newResourceGlossary
FindGlossaryByID = findGlossaryByID
ResourceFormType = newResourceFormType
FindFormTypeByID = findFormTypeByID
)
317 changes: 317 additions & 0 deletions internal/service/datazone/form_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package datazone

import (
"context"
"errors"
"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/diag"
"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"
"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"
)

// @FrameworkResource("aws_datazone_form_type", name="Form Type")
func newResourceFormType(_ context.Context) (resource.ResourceWithConfigure, error) {
r := &resourceFormType{}
return r, nil
}

const (
ResNameFormType = "Form Type"
)

type resourceFormType struct {
framework.ResourceWithConfigure
framework.WithImportByID
framework.WithTimeouts
framework.WithNoUpdate
}

func (r *resourceFormType) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = "aws_datazone_form_type"
}
func (r *resourceFormType) 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.LengthBetween(1, 2048),
},
},
names.AttrName: schema.StringAttribute{
Required: true,
Validators: []validator.String{},
},
"owning_project_identifier": schema.StringAttribute{
Required: true,
Validators: []validator.String{
stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9_-]{1,36}$`), "^[a-zA-Z0-9_-]{1,36}$"),
},
},
names.AttrStatus: schema.StringAttribute{
CustomType: fwtypes.StringEnumType[awstypes.FormTypeStatus](),
Optional: true,
Computed: true,
},
"domain_identifier": schema.StringAttribute{
Required: true,
Validators: []validator.String{
stringvalidator.RegexMatches(regexache.MustCompile(`^dzd[-_][a-zA-Z0-9_-]{1,36}$`), "^dzd[-_][a-zA-Z0-9_-]{1,36}$"),
},
},
"origin_domain_id": schema.StringAttribute{
Computed: true,
},
"origin_project_id": schema.StringAttribute{
Computed: true,
},
"revision": schema.StringAttribute{
Computed: true,
},
names.AttrCreatedAt: schema.StringAttribute{
CustomType: timetypes.RFC3339Type{},
Computed: true,
},
"created_by": schema.StringAttribute{
Computed: true,
},
"imports": schema.ListAttribute{
CustomType: fwtypes.NewListNestedObjectTypeOf[importData](ctx),
Computed: true,
},
},
Blocks: map[string]schema.Block{
"model": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[modelData](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
listvalidator.IsRequired(),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"smithy": schema.StringAttribute{
Required: true,
},
},
},
},
names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{
Create: true,
}),
},
}
}

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

var plan resourceFormTypeData
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}
in := &datazone.CreateFormTypeInput{}
in.DomainIdentifier = plan.DomainIdentifier.ValueStringPointer()
resp.Diagnostics.Append(flex.Expand(ctx, &plan, in)...)
if resp.Diagnostics.HasError() {
return
}
option := flex.WithIgnoredFieldNames([]string{"Model"})
out, err := conn.CreateFormType(ctx, in)
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameFormType, plan.Name.String(), err),
err.Error(),
)
return
}
if out == nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameFormType, plan.Name.String(), nil),
errors.New("empty output").Error(),
)
return
}

createTimeout := r.CreateTimeout(ctx, plan.Timeouts)
outputRaws, err := tfresource.RetryWhenNotFound(ctx, createTimeout, func() (interface{}, error) {
return findFormTypeByID(ctx, conn, *out.DomainId, *out.Name, *out.Revision)
})
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataZone, create.ErrActionCreating, ResNameFormType, plan.Name.String(), err),
err.Error(),
)
return
}
output := outputRaws.(*datazone.GetFormTypeOutput)
resp.Diagnostics.Append(flex.Flatten(ctx, output, &plan, option)...)
if resp.Diagnostics.HasError() {
return
}
plan.OriginDomainId = flex.StringToFrameworkLegacy(ctx, output.OriginDomainId)
plan.OriginProjectId = flex.StringToFrameworkLegacy(ctx, output.OriginProjectId)
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}

func (r *resourceFormType) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
conn := r.Meta().DataZoneClient(ctx)

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

out, err := findFormTypeByID(ctx, conn, state.DomainIdentifier.ValueString(), state.Name.ValueString(), state.Revision.ValueString())
if tfresource.NotFound(err) {
resp.State.RemoveResource(ctx)
return
}
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataZone, create.ErrActionSetting, ResNameFormType, state.Name.String(), err),
err.Error(),
)
return
}
option := flex.WithIgnoredFieldNames([]string{"Model"})

resp.Diagnostics.Append(flex.Flatten(ctx, out, &state, option)...)
if resp.Diagnostics.HasError() {
return
}
state.OwningProjectIdentifier = flex.StringToFramework(ctx, out.OwningProjectId)
state.OriginDomainId = flex.StringToFrameworkLegacy(ctx, out.OriginDomainId)
state.OriginProjectId = flex.StringToFrameworkLegacy(ctx, out.OriginProjectId)

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *resourceFormType) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
}

func (r *resourceFormType) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
conn := r.Meta().DataZoneClient(ctx)

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

in := &datazone.DeleteFormTypeInput{
DomainIdentifier: state.DomainIdentifier.ValueStringPointer(),
FormTypeIdentifier: state.Name.ValueStringPointer(),
}

_, err := conn.DeleteFormType(ctx, in)
if err != nil {
if errs.IsA[*awstypes.ResourceNotFoundException](err) || errs.IsA[*awstypes.AccessDeniedException](err) {
return
}
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.DataZone, create.ErrActionDeleting, ResNameFormType, state.Name.String(), err),
err.Error(),
)
return
}
}
func (r *resourceFormType) 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", `Unexpected format for import ID, use: "DomainIdentifier:Name,Revision"`)
return
}

resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("domain_identifier"), parts[0])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrName), parts[1])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("revision"), parts[2])...)
}

func findFormTypeByID(ctx context.Context, conn *datazone.Client, domainId string, name string, revision string) (*datazone.GetFormTypeOutput, error) {
in := &datazone.GetFormTypeInput{
DomainIdentifier: aws.String(domainId),
FormTypeIdentifier: aws.String(name),
Revision: aws.String(revision),
}

out, err := conn.GetFormType(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 (m modelData) Expand(ctx context.Context) (result any, diags diag.Diagnostics) {
switch {
case !m.Smithy.IsNull():

var r awstypes.ModelMemberSmithy

r.Value = m.Smithy.ValueString()
return &r, diags
}
return
}

type resourceFormTypeData struct {
Description types.String `tfsdk:"description"`
Model fwtypes.ListNestedObjectValueOf[modelData] `tfsdk:"model"`
Name types.String `tfsdk:"name"`
OwningProjectIdentifier types.String `tfsdk:"owning_project_identifier"`
Status fwtypes.StringEnum[awstypes.FormTypeStatus] `tfsdk:"status"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
DomainIdentifier types.String `tfsdk:"domain_identifier"`
OriginDomainId types.String `tfsdk:"origin_domain_id"`
OriginProjectId types.String `tfsdk:"origin_project_id"`
Revision types.String `tfsdk:"revision"`
CreatedAt timetypes.RFC3339 `tfsdk:"created_at"`
CreatedBy types.String `tfsdk:"created_by"`
Imports fwtypes.ListNestedObjectValueOf[importData] `tfsdk:"imports"`
}

type modelData struct {
Smithy types.String `tfsdk:"smithy"`
}

type importData struct {
Name types.String `tfsdk:"name"`
Revision types.String `tfsdk:"revision"`
}
Loading

0 comments on commit bfe748e

Please sign in to comment.