Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/34832.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_finspace_kx_scaling_group
```
292 changes: 292 additions & 0 deletions internal/service/finspace/kx_scaling_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package finspace

import (
"context"
"errors"
"log"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/finspace"
"github.com/aws/aws-sdk-go-v2/service/finspace/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/create"
"github.com/hashicorp/terraform-provider-aws/internal/enum"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @SDKResource("aws_finspace_kx_scaling_group", name="Kx Scaling Group")
// @Tags(identifierAttribute="arn")
func ResourceKxScalingGroup() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceKxScalingGroupCreate,
ReadWithoutTimeout: resourceKxScalingGroupRead,
UpdateWithoutTimeout: resourceKxScalingGroupUpdate,
DeleteWithoutTimeout: resourceKxScalingGroupDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

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

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"availability_zone_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"environment_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 32),
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(3, 63),
},
"host_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 32),
},
"created_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"last_modified_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"clusters": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"status_reason": {
Type: schema.TypeString,
Computed: true,
},
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
},
CustomizeDiff: verify.SetTagsDiff,
}
}

const (
ResNameKxScalingGroup = "Kx Scaling Group"
kxScalingGroupIDPartCount = 2
)

func resourceKxScalingGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).FinSpaceClient(ctx)

environmentId := d.Get("environment_id").(string)
scalingGroupName := d.Get("name").(string)
idParts := []string{
environmentId,
scalingGroupName,
}
rID, err := flex.FlattenResourceId(idParts, kxScalingGroupIDPartCount, false)
if err != nil {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionFlatteningResourceId, ResNameKxScalingGroup, d.Get("name").(string), err)
}
d.SetId(rID)

in := &finspace.CreateKxScalingGroupInput{
EnvironmentId: aws.String(environmentId),
ScalingGroupName: aws.String(scalingGroupName),
HostType: aws.String(d.Get("host_type").(string)),
AvailabilityZoneId: aws.String(d.Get("availability_zone_id").(string)),
Tags: getTagsIn(ctx),
}

out, err := conn.CreateKxScalingGroup(ctx, in)
if err != nil {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionCreating, ResNameKxScalingGroup, d.Get("name").(string), err)
}

if out == nil {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionCreating, ResNameKxScalingGroup, d.Get("name").(string), errors.New("empty output"))
}

if _, err := waitKxScalingGroupCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxScalingGroup, d.Id(), err)
}

return append(diags, resourceKxScalingGroupRead(ctx, d, meta)...)
}

func resourceKxScalingGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).FinSpaceClient(ctx)

out, err := FindKxScalingGroupById(ctx, conn, d.Id())
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] FinSpace KxScalingGroup (%s) not found, removing from state", d.Id())
d.SetId("")
return diags
}

if err != nil {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionReading, ResNameKxScalingGroup, d.Id(), err)
}
d.Set("arn", out.ScalingGroupArn)
d.Set("status", out.Status)
d.Set("status_reason", out.StatusReason)
d.Set("created_timestamp", out.CreatedTimestamp.String())
d.Set("last_modified_timestamp", out.LastModifiedTimestamp.String())
d.Set("name", out.ScalingGroupName)
d.Set("availability_zone_id", out.AvailabilityZoneId)
d.Set("host_type", out.HostType)
d.Set("clusters", out.Clusters)

parts, err := flex.ExpandResourceId(d.Id(), kxUserIDPartCount, false)
if err != nil {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionSetting, ResNameKxScalingGroup, d.Id(), err)
}
d.Set("environment_id", parts[0])

return diags
}

func resourceKxScalingGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
// Tags only.
return append(diags, resourceKxScalingGroupRead(ctx, d, meta)...)
}

func resourceKxScalingGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).FinSpaceClient(ctx)

log.Printf("[INFO] Deleting FinSpace KxScalingGroup %s", d.Id())
_, err := conn.DeleteKxScalingGroup(ctx, &finspace.DeleteKxScalingGroupInput{
ScalingGroupName: aws.String(d.Get("name").(string)),
EnvironmentId: aws.String(d.Get("environment_id").(string)),
})
if err != nil {
var nfe *types.ResourceNotFoundException
if errors.As(err, &nfe) {
return diags
}

return create.AppendDiagError(diags, names.FinSpace, create.ErrActionDeleting, ResNameKxScalingGroup, d.Id(), err)
}

_, err = waitKxScalingGroupDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete))
if err != nil && !tfresource.NotFound(err) {
return create.AppendDiagError(diags, names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxScalingGroup, d.Id(), err)
}

return diags
}

func FindKxScalingGroupById(ctx context.Context, conn *finspace.Client, id string) (*finspace.GetKxScalingGroupOutput, error) {
parts, err := flex.ExpandResourceId(id, kxScalingGroupIDPartCount, false)
if err != nil {
return nil, err
}
in := &finspace.GetKxScalingGroupInput{
EnvironmentId: aws.String(parts[0]),
ScalingGroupName: aws.String(parts[1]),
}

out, err := conn.GetKxScalingGroup(ctx, in)
if err != nil {
var nfe *types.ResourceNotFoundException
if errors.As(err, &nfe) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: in,
}
}

return nil, err
}

if out == nil || out.ScalingGroupName == nil {
return nil, tfresource.NewEmptyResultError(in)
}
return out, nil
}

func waitKxScalingGroupCreated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxScalingGroupOutput, error) {
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(types.KxScalingGroupStatusCreating),
Target: enum.Slice(types.KxScalingGroupStatusActive),
Refresh: statusKxScalingGroup(ctx, conn, id),
Timeout: timeout,
NotFoundChecks: 20,
ContinuousTargetOccurence: 2,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)
if out, ok := outputRaw.(*finspace.GetKxScalingGroupOutput); ok {
return out, err
}

return nil, err
}

func waitKxScalingGroupDeleted(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxScalingGroupOutput, error) {
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(types.KxScalingGroupStatusDeleting),
Target: enum.Slice(types.KxScalingGroupStatusDeleted),
Refresh: statusKxScalingGroup(ctx, conn, id),
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)
if out, ok := outputRaw.(*finspace.GetKxScalingGroupOutput); ok {
return out, err
}

return nil, err
}

func statusKxScalingGroup(ctx context.Context, conn *finspace.Client, id string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
out, err := FindKxScalingGroupById(ctx, conn, id)
if tfresource.NotFound(err) {
return nil, "", nil
}

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

return out, string(out.Status), nil
}
}
Loading