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

[New Resource]aws_finspace_kx_scaling_group #34832

Merged
merged 12 commits into from
Dec 14, 2023
Merged
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
Loading