Skip to content
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

F register target resource #31074

Merged
merged 22 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2488f5e
Initial code with expand and flateners
markoskandylis Apr 24, 2023
a12a386
adding waiters
markoskandylis Apr 25, 2023
6cd813f
Merge branch 'hashicorp:main' into f-register-targets-resource
markoskandylis Apr 25, 2023
bfc8cab
Creating a list of targets
markoskandylis Apr 26, 2023
83e5424
tests
markoskandylis Apr 26, 2023
f299187
Adding target group identifier to the importer
markoskandylis Apr 27, 2023
67c24bc
adding update
markoskandylis Apr 27, 2023
264b62a
Adding lambda
markoskandylis Apr 28, 2023
b3f4966
Succeded tests
markoskandylis Apr 28, 2023
2d14df0
finished tests
markoskandylis Apr 30, 2023
0c8f510
Merge branch 'hashicorp:main' into f-register-target-resource
markoskandylis Apr 30, 2023
97f65ba
Run all tests
markoskandylis Apr 30, 2023
c896714
Merge branch 'main' into f-register-target-resource
markoskandylis Apr 30, 2023
5b49b13
Merge branch 'f-register-target-resource' of github.com:markoskandyli…
markoskandylis Apr 30, 2023
92e1613
added Attributes Referance for the docs
markoskandylis Apr 30, 2023
7ade4c1
fixed conflicts
markoskandylis May 2, 2023
23464d4
'aws_vpclattice_register_targets' -> 'aws_vpclattice_target_group_att…
ewbankkit May 2, 2023
d2df152
r/aws_vpclattice_target_group_attachment: Correct 'TestAccVPCLatticeT…
ewbankkit May 2, 2023
8766667
r/aws_vpclattice_target_group_attachment: Correct 'TestAccVPCLatticeT…
ewbankkit May 2, 2023
326beaa
r/aws_vpclattice_target_group_attachment: Correct 'TestAccVPCLatticeT…
ewbankkit May 2, 2023
0ee03c4
r/aws_vpclattice_target_group_attachment: Correct 'TestAccVPCLatticeT…
ewbankkit May 2, 2023
e9417e8
r/aws_vpclattice_target_group_attachment: Add 'TestAccVPCLatticeTarge…
ewbankkit May 2, 2023
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/31039.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_vpclattice_target_group_attachment
```
8 changes: 8 additions & 0 deletions internal/service/vpclattice/exports_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package vpclattice

// Exports for use in tests only.
var (
FindTargetByThreePartKey = findTargetByThreePartKey

ResourceTargetGroupAttachment = resourceTargetGroupAttachment
)
5 changes: 5 additions & 0 deletions internal/service/vpclattice/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

275 changes: 275 additions & 0 deletions internal/service/vpclattice/target_group_attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
package vpclattice

import (
"context"
"errors"
"log"
"strconv"
"strings"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/vpclattice"
"github.com/aws/aws-sdk-go-v2/service/vpclattice/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/enum"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

// @SDKResource("aws_vpclattice_target_group_attachment", name="Target Group Attachment")
func resourceTargetGroupAttachment() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceTargetGroupAttachmentCreate,
ReadWithoutTimeout: resourceTargetGroupAttachmentRead,
DeleteWithoutTimeout: resourceTargetGroupAttachmentDelete,

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Schema: map[string]*schema.Schema{
"target": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
MaxItems: 1,
MinItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 2048),
},
"port": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validation.IsPortNumber,
},
},
},
},
"target_group_identifier": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}

func resourceTargetGroupAttachmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).VPCLatticeClient()

targetGroupID := d.Get("target_group_identifier").(string)
target := expandTarget(d.Get("target").([]interface{})[0].(map[string]interface{}))
targetID := aws.ToString(target.Id)
targetPort := int(aws.ToInt32(target.Port))
id := strings.Join([]string{targetGroupID, targetID, strconv.Itoa(targetPort)}, "/")
input := &vpclattice.RegisterTargetsInput{
TargetGroupIdentifier: aws.String(targetGroupID),
Targets: []types.Target{target},
}

_, err := conn.RegisterTargets(ctx, input)

if err != nil {
return diag.Errorf("creating VPC Lattice Target Group Attachment (%s): %s", id, err)
}

d.SetId(id)

if _, err := waitTargetGroupAttachmentCreated(ctx, conn, targetGroupID, targetID, targetPort, d.Timeout(schema.TimeoutCreate)); err != nil {
return diag.Errorf("waiting for VPC Lattice Target Group Attachment (%s) create: %s", id, err)
}

return resourceTargetGroupAttachmentRead(ctx, d, meta)
}

func resourceTargetGroupAttachmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).VPCLatticeClient()

targetGroupID := d.Get("target_group_identifier").(string)
target := expandTarget(d.Get("target").([]interface{})[0].(map[string]interface{}))
targetID := aws.ToString(target.Id)
targetPort := int(aws.ToInt32(target.Port))

output, err := findTargetByThreePartKey(ctx, conn, targetGroupID, targetID, targetPort)

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] VPC Lattice Target Group Attachment (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return diag.Errorf("reading VPC Lattice Target Group Attachment (%s): %s", d.Id(), err)
}

if err := d.Set("target", []interface{}{flattenTargetSummary(output)}); err != nil {
return diag.Errorf("setting target: %s", err)
}
d.Set("target_group_identifier", targetGroupID)

return nil
}

func resourceTargetGroupAttachmentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).VPCLatticeClient()

targetGroupID := d.Get("target_group_identifier").(string)
target := expandTarget(d.Get("target").([]interface{})[0].(map[string]interface{}))
targetID := aws.ToString(target.Id)
targetPort := int(aws.ToInt32(target.Port))

log.Printf("[INFO] Deleting VPC Lattice Target Group Attachment: %s", d.Id())
_, err := conn.DeregisterTargets(ctx, &vpclattice.DeregisterTargetsInput{
TargetGroupIdentifier: aws.String(targetGroupID),
Targets: []types.Target{target},
})

if errs.IsA[*types.ResourceNotFoundException](err) {
return nil
}

if err != nil {
return diag.Errorf("deleting VPC Lattice Target Group Attachment (%s): %s", d.Id(), err)
}

if _, err := waitTargetGroupAttachmentDeleted(ctx, conn, targetGroupID, targetID, targetPort, d.Timeout(schema.TimeoutDelete)); err != nil {
return diag.Errorf("waiting for VPC Lattice Target Group Attachment (%s) delete: %s", d.Id(), err)
}

return nil
}

func findTargetByThreePartKey(ctx context.Context, conn *vpclattice.Client, targetGroupID, targetID string, targetPort int) (*types.TargetSummary, error) {
input := &vpclattice.ListTargetsInput{
TargetGroupIdentifier: aws.String(targetGroupID),
Targets: []types.Target{{
Id: aws.String(targetID),
}},
}
if targetPort > 0 {
input.Targets[0].Port = aws.Int32(int32(targetPort))
}

paginator := vpclattice.NewListTargetsPaginator(conn, input)
for paginator.HasMorePages() {
output, err := paginator.NextPage(ctx)

if errs.IsA[*types.ResourceNotFoundException](err) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output != nil && len(output.Items) == 1 {
return &(output.Items[0]), nil
}
}

return nil, &retry.NotFoundError{}
}

func statusTarget(ctx context.Context, conn *vpclattice.Client, targetGroupID, targetID string, targetPort int) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findTargetByThreePartKey(ctx, conn, targetGroupID, targetID, targetPort)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, string(output.Status), nil
}
}

func waitTargetGroupAttachmentCreated(ctx context.Context, conn *vpclattice.Client, targetGroupID, targetID string, targetPort int, timeout time.Duration) (*types.TargetSummary, error) {
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(types.TargetStatusInitial),
Target: enum.Slice(types.TargetStatusHealthy, types.TargetStatusUnhealthy, types.TargetStatusUnused, types.TargetStatusUnavailable),
Refresh: statusTarget(ctx, conn, targetGroupID, targetID, targetPort),
Timeout: timeout,
NotFoundChecks: 20,
ContinuousTargetOccurence: 2,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*types.TargetSummary); ok {
tfresource.SetLastError(err, errors.New(aws.ToString(output.ReasonCode)))

return output, err
}

return nil, err
}

func waitTargetGroupAttachmentDeleted(ctx context.Context, conn *vpclattice.Client, targetGroupID, targetID string, targetPort int, timeout time.Duration) (*types.TargetSummary, error) {
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(types.TargetStatusDraining, types.TargetStatusInitial),
Target: []string{},
Refresh: statusTarget(ctx, conn, targetGroupID, targetID, targetPort),
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*types.TargetSummary); ok {
tfresource.SetLastError(err, errors.New(aws.ToString(output.ReasonCode)))

return output, err
}

return nil, err
}

func flattenTargetSummary(apiObject *types.TargetSummary) map[string]interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.Id; v != nil {
tfMap["id"] = aws.ToString(v)
}

if v := apiObject.Port; v != nil {
tfMap["port"] = aws.ToInt32(v)
}

return tfMap
}

func expandTarget(tfMap map[string]interface{}) types.Target {
apiObject := types.Target{}

if v, ok := tfMap["id"].(string); ok && v != "" {
apiObject.Id = aws.String(v)
}

if v, ok := tfMap["port"].(int); ok && v != 0 {
apiObject.Port = aws.Int32(int32(v))
}

return apiObject
}
Loading