From d7e875aeba6ac3a5ddac347d82df130d94995917 Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Tue, 6 Jun 2023 16:32:22 -0400 Subject: [PATCH 01/26] Adds finspace_kx_cluster resource --- internal/service/finspace/kx_cluster.go | 1140 +++++++++ internal/service/finspace/kx_cluster_test.go | 2195 +++++++++++++++++ .../service/finspace/service_package_gen.go | 10 +- .../docs/r/finspace_kx_cluster.html.markdown | 169 ++ 4 files changed, 3513 insertions(+), 1 deletion(-) create mode 100644 internal/service/finspace/kx_cluster.go create mode 100644 internal/service/finspace/kx_cluster_test.go create mode 100644 website/docs/r/finspace_kx_cluster.html.markdown diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go new file mode 100644 index 000000000000..8aa7ff214c4e --- /dev/null +++ b/internal/service/finspace/kx_cluster.go @@ -0,0 +1,1140 @@ +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/id" + "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_cluster") +// @Tags(identifierAttribute="arn") +func ResourceKxCluster() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceKxClusterCreate, + ReadWithoutTimeout: resourceKxClusterRead, + DeleteWithoutTimeout: resourceKxClusterDelete, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(40 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "status": { + Type: schema.TypeString, + Computed: true, + }, + "status_reason": { + Type: schema.TypeString, + Computed: true, + }, + "created_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "last_modified_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "arn": { + Type: schema.TypeString, + Computed: 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), + }, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.KxClusterType](), + }, + "release_label": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 16), + }, + "az_mode": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.KxAzMode](), + }, + "availability_zone_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1000), + }, + "initialization_script": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + "execution_role": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + "command_line_arguments": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + ValidateDiagFunc: verify.ValidAllDiag( + validation.MapKeyLenBetween(1, 50), + validation.MapValueLenBetween(1, 50), + ), + }, + "capacity_configuration": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 32), + }, + "node_count": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 5), + }, + }, + }, + }, + "vpc_configuration": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vpc_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + "security_group_ids": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + }, + "subnet_ids": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + }, + "ip_address_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(types.IPAddressTypeIpV4), + }, true), + }, + }, + }, + }, + "auto_scaling_configuration": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_scaling_metric": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(types.AutoScalingMetricCpuUtilizationPercentage), + }, true), + }, + "min_node_count": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 5), + }, + "max_node_count": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 5), + }, + "metric_target": { + Type: schema.TypeFloat, + Required: true, + ForceNew: true, + ValidateFunc: validation.FloatBetween(0, 100), + }, + "scale_in_cooldown_seconds": { + Type: schema.TypeFloat, + Required: true, + ForceNew: true, + ValidateFunc: validation.FloatBetween(0, 100000), + }, + "scale_out_cooldown_seconds": { + Type: schema.TypeFloat, + Required: true, + ForceNew: true, + ValidateFunc: validation.FloatBetween(0, 100000), + }, + }, + }, + }, + "savedown_storage_configuration": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(types.KxSavedownStorageTypeSds01), + }, true), + }, + "size": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(4, 16000), + }, + }, + }, + }, + "cache_storage_configurations": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(8, 10), + }, + "size": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1200, 33600), + }, + }, + }, + }, + "database": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "database_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 63), + }, + "cache_configurations": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cache_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "CACHE_1000", + }, true), + }, + "db_paths": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Required: true, + ForceNew: true, + }, + }, + }, + }, + "changeset_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 26), + }, + }, + }, + }, + "code": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "s3_bucket": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 255), + }, + "s3_key": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 1024), + }, + "s3_object_version": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 63), + }, + }, + }, + }, + "tags": tftags.TagsSchemaForceNew(), + "tags_all": tftags.TagsSchemaComputed(), + }, + CustomizeDiff: verify.SetTagsDiff, + } +} + +const ( + ResNameKxCluster = "Kx Cluster" +) + +func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).FinSpaceClient() + + in := &finspace.CreateKxClusterInput{ + EnvironmentId: aws.String(d.Get("environment_id").(string)), + ClusterName: aws.String(d.Get("name").(string)), + ClusterType: types.KxClusterType(d.Get("type").(string)), + ReleaseLabel: aws.String(d.Get("release_label").(string)), + AzMode: types.KxAzMode(d.Get("az_mode").(string)), + CapacityConfiguration: expandCapacityConfiguration(d.Get("capacity_configuration").([]interface{})), + ClientToken: aws.String(id.UniqueId()), + Tags: GetTagsIn(ctx), + } + + if v, ok := d.GetOk("description"); ok { + in.ClusterDescription = aws.String(v.(string)) + } + + if v, ok := d.GetOk("initialization_script"); ok { + in.InitializationScript = aws.String(v.(string)) + } + + if v, ok := d.GetOk("execution_role"); ok { + in.ExecutionRole = aws.String(v.(string)) + } + + if v, ok := d.GetOk("availability_zone_id"); ok { + in.AvailabilityZoneId = aws.String(v.(string)) + } + + if v, ok := d.GetOk("command_line_arguments"); ok && len(v.(map[string]interface{})) > 0 { + in.CommandLineArguments = expandCommandLineArguments(v.(map[string]interface{})) + } + + if v, ok := d.GetOk("vpc_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.VpcConfiguration = expandVpcConfiguration(v.([]interface{})) + } + + if v, ok := d.GetOk("auto_scaling_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.AutoScalingConfiguration = expandAutoScalingConfiguration(v.([]interface{})) + } + + if v, ok := d.GetOk("database"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.Databases = expandDatabases(v.([]interface{})) + } + + if v, ok := d.GetOk("savedown_storage_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.SavedownStorageConfiguration = expandSavedownStorageConfiguration(v.([]interface{})) + } + + if v, ok := d.GetOk("cache_storage_configurations"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.CacheStorageConfigurations = expandCacheStorageConfigurations(v.([]interface{})) + } + + if v, ok := d.GetOk("code"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.Code = expandCode(v.([]interface{})) + } + + out, err := conn.CreateKxCluster(ctx, in) + if err != nil { + return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), err) + } + + if out == nil { + return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), errors.New("empty output")) + } + + d.SetId(aws.ToString(out.EnvironmentId) + "," + aws.ToString(out.ClusterName)) + + if _, err := waitKxClusterCreated(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string), d.Timeout(schema.TimeoutCreate)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxCluster, d.Id(), err) + } + + return resourceKxClusterRead(ctx, d, meta) +} + +func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).FinSpaceClient() + + out, err := findKxClusterByID(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string)) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] FinSpace KxCluster (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return create.DiagError(names.FinSpace, create.ErrActionReading, ResNameKxCluster, d.Id(), err) + } + + 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.ClusterName) + d.Set("type", out.ClusterType) + d.Set("release_label", out.ReleaseLabel) + d.Set("description", out.ClusterDescription) + d.Set("az_mode", out.AzMode) + d.Set("availability_zone_id", out.AvailabilityZoneId) + d.Set("execution_role", out.ExecutionRole) + d.Set("initialization_script", out.InitializationScript) + + env, err := findKxEnvironmentByID(ctx, conn, d.Get("environment_id").(string)) + d.Set("arn", *env.EnvironmentArn+"/kxCluster/"+*out.ClusterName) + + if err := d.Set("capacity_configuration", flattenCapacityConfiguration(out.CapacityConfiguration)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + if err := d.Set("vpc_configuration", flattenVpcConfiguration(out.VpcConfiguration)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + if err := d.Set("code", flattenCode(out.Code)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + if err := d.Set("auto_scaling_configuration", flattenAutoScalingConfiguration(out.AutoScalingConfiguration)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + if err := d.Set("savedown_storage_configuration", flattenSavedownStorageConfiguration( + out.SavedownStorageConfiguration)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + if err := d.Set("cache_storage_configurations", flattenCacheStorageConfigurations( + out.CacheStorageConfigurations)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + if d.IsNewResource() { + if err := d.Set("database", flattenDatabases(out.Databases)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + } + + if err := d.Set("command_line_arguments", flattenCommandLineArguments(out.CommandLineArguments)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + } + + return nil +} + +func resourceKxClusterDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).FinSpaceClient() + + log.Printf("[INFO] Deleting FinSpace KxCluster %s", d.Id()) + + _, err := conn.DeleteKxCluster(ctx, &finspace.DeleteKxClusterInput{ + ClusterName: 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 nil + } + + return create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxCluster, d.Id(), err) + } + + _, err = waitKxClusterDeleted(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string), d.Timeout(schema.TimeoutDelete)) + + if err != nil && !tfresource.NotFound(err) { + return create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxCluster, d.Id(), err) + } + return nil +} + +func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{string(types.KxClusterStatusPending), string(types.KxClusterStatusCreating)}, + Target: []string{string(types.KxClusterStatusRunning)}, + Refresh: statusKxCluster(ctx, conn, clusterName, environmentId), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*finspace.GetKxClusterOutput); ok { + return out, err + } + + return nil, err +} + +func waitKxClusterDeleted(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{string(types.KxClusterStatusDeleting)}, + Target: []string{string(types.KxClusterStatusDeleted)}, + Refresh: statusKxCluster(ctx, conn, clusterName, environmentId), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*finspace.GetKxClusterOutput); ok { + return out, err + } + + return nil, err +} + +func statusKxCluster(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findKxClusterByID(ctx, conn, clusterName, environmentId) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, string(out.Status), nil + } +} + +func findKxClusterByID(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string) (*finspace.GetKxClusterOutput, error) { + in := &finspace.GetKxClusterInput{ + ClusterName: aws.String(clusterName), + EnvironmentId: aws.String(environmentId), + } + + out, err := conn.GetKxCluster(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.ClusterName == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func expandCapacityConfiguration(tfList []interface{}) *types.CapacityConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + + a := &types.CapacityConfiguration{} + + if v, ok := tfMap["node_type"].(string); ok && v != "" { + a.NodeType = aws.String(v) + } + + if v, ok := tfMap["node_count"].(int); ok && v != 0 { + a.NodeCount = aws.Int32(int32(v)) + } + + return a +} + +func expandAutoScalingConfiguration(tfList []interface{}) *types.AutoScalingConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + + a := &types.AutoScalingConfiguration{} + + if v, ok := tfMap["auto_scaling_metric"].(string); ok && v != "" { + a.AutoScalingMetric = types.AutoScalingMetric(v) + } + + if v, ok := tfMap["min_node_count"].(int); ok && v != 0 { + a.MinNodeCount = aws.Int32(int32(v)) + } + + if v, ok := tfMap["max_node_count"].(int); ok && v != 0 { + a.MaxNodeCount = aws.Int32(int32(v)) + } + + if v, ok := tfMap["metric_target"].(float64); ok && v != 0 { + a.MetricTarget = aws.Float64(v) + } + + if v, ok := tfMap["scale_in_cooldown_seconds"].(float64); ok && v != 0 { + a.ScaleInCooldownSeconds = aws.Float64(v) + } + + if v, ok := tfMap["scale_out_cooldown_seconds"].(float64); ok && v != 0 { + a.ScaleOutCooldownSeconds = aws.Float64(v) + } + + return a +} + +func expandSavedownStorageConfiguration(tfList []interface{}) *types.KxSavedownStorageConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + + a := &types.KxSavedownStorageConfiguration{} + + if v, ok := tfMap["type"].(string); ok && v != "" { + a.Type = types.KxSavedownStorageType(v) + } + + if v, ok := tfMap["size"].(int); ok && v != 0 { + a.Size = int32(v) + } + + return a +} + +func expandVpcConfiguration(tfList []interface{}) *types.VpcConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + + a := &types.VpcConfiguration{} + + if v, ok := tfMap["vpc_id"].(string); ok && v != "" { + a.VpcId = aws.String(v) + } + + if v, ok := tfMap["security_group_ids"].(*schema.Set); ok && v.Len() > 0 { + a.SecurityGroupIds = flex.ExpandStringValueSet(v) + } + + if v, ok := tfMap["subnet_ids"].(*schema.Set); ok && v.Len() > 0 { + a.SubnetIds = flex.ExpandStringValueSet(v) + } + + if v, ok := tfMap["ip_address_type"].(string); ok && v != "" { + a.IpAddressType = types.IPAddressType(v) + } + + return a +} + +func expandCacheStorageConfiguration(tfMap map[string]interface{}) *types.KxCacheStorageConfiguration { + if tfMap == nil { + return nil + } + + a := &types.KxCacheStorageConfiguration{} + + if v, ok := tfMap["type"].(string); ok && v != "" { + a.Type = &v + } + + if v, ok := tfMap["size"].(int); ok { + a.Size = aws.Int32(int32(v)) + } + + return a +} + +func expandCacheStorageConfigurations(tfList []interface{}) []types.KxCacheStorageConfiguration { + if len(tfList) == 0 { + return nil + } + + var s []types.KxCacheStorageConfiguration + + for _, r := range tfList { + m, ok := r.(map[string]interface{}) + + if !ok { + continue + } + + a := expandCacheStorageConfiguration(m) + + if a == nil { + continue + } + + s = append(s, *a) + } + + return s +} + +func expandDatabases(tfList []interface{}) []types.KxDatabaseConfiguration { + if len(tfList) == 0 { + return nil + } + + var s []types.KxDatabaseConfiguration + + for _, r := range tfList { + m, ok := r.(map[string]interface{}) + + if !ok { + continue + } + + a := expandDatabase(m) + + if a == nil { + continue + } + + s = append(s, *a) + } + + return s +} + +func expandDatabase(tfMap map[string]interface{}) *types.KxDatabaseConfiguration { + if tfMap == nil { + return nil + } + + a := &types.KxDatabaseConfiguration{} + + if v, ok := tfMap["database_name"].(string); ok && v != "" { + a.DatabaseName = aws.String(v) + } + + if v, ok := tfMap["cache_configurations"]; ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + a.CacheConfigurations = expandCacheConfigurations(v.([]interface{})) + } + + if v, ok := tfMap["changeset_id"].(string); ok && v != "" { + a.ChangesetId = aws.String(v) + } + + return a +} + +func expandCacheConfigurations(tfList []interface{}) []types.KxDatabaseCacheConfiguration { + if len(tfList) == 0 { + return nil + } + + var s []types.KxDatabaseCacheConfiguration + + for _, r := range tfList { + m, ok := r.(map[string]interface{}) + + if !ok { + continue + } + + a := expandCacheConfiguration(m) + + if a == nil { + continue + } + + s = append(s, *a) + } + + return s +} + +func expandCacheConfiguration(tfMap map[string]interface{}) *types.KxDatabaseCacheConfiguration { + if tfMap == nil { + return nil + } + + a := &types.KxDatabaseCacheConfiguration{} + + if v, ok := tfMap["cache_type"].(string); ok && v != "" { + a.CacheType = &v + } + + if v, ok := tfMap["db_paths"].(*schema.Set); ok && v.Len() > 0 { + a.DbPaths = flex.ExpandStringValueSet(v) + } + + return a +} + +func expandCode(tfList []interface{}) *types.CodeConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + + a := &types.CodeConfiguration{} + + if v, ok := tfMap["s3_bucket"].(string); ok && v != "" { + a.S3Bucket = aws.String(v) + } + + if v, ok := tfMap["s3_key"].(string); ok && v != "" { + a.S3Key = aws.String(v) + } + + if v, ok := tfMap["s3_object_version"].(string); ok && v != "" { + a.S3ObjectVersion = aws.String(v) + } + + return a +} + +func expandCommandLineArgument(k string, v string) *types.KxCommandLineArgument { + if k == "" || v == "" { + return nil + } + + a := &types.KxCommandLineArgument{ + Key: aws.String(k), + Value: aws.String(v), + } + return a +} + +func expandCommandLineArguments(tfMap map[string]interface{}) []types.KxCommandLineArgument { + if tfMap == nil { + return nil + } + + var s []types.KxCommandLineArgument + + for k, v := range tfMap { + a := expandCommandLineArgument(k, v.(string)) + + if a == nil { + continue + } + + s = append(s, *a) + } + + return s +} + +func flattenCapacityConfiguration(apiObject *types.CapacityConfiguration) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.NodeType; v != nil { + m["node_type"] = aws.ToString(v) + } + + if v := apiObject.NodeCount; v != nil { + m["node_count"] = aws.ToInt32(v) + } + + return []interface{}{m} +} + +func flattenAutoScalingConfiguration(apiObject *types.AutoScalingConfiguration) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.AutoScalingMetric; v != "" { + m["auto_scaling_metric"] = types.AutoScalingMetric(v) + } + + if v := apiObject.MinNodeCount; v != nil { + m["min_node_count"] = aws.ToInt32(v) + } + + if v := apiObject.MaxNodeCount; v != nil { + m["max_node_count"] = aws.ToInt32(v) + } + + if v := apiObject.MetricTarget; v != nil { + m["metric_target"] = aws.ToFloat64(v) + } + + if v := apiObject.ScaleInCooldownSeconds; v != nil { + m["scale_in_cooldown_seconds"] = aws.ToFloat64(v) + } + + if v := apiObject.ScaleOutCooldownSeconds; v != nil { + m["scale_out_cooldown_seconds"] = aws.ToFloat64(v) + } + + return []interface{}{m} +} + +func flattenSavedownStorageConfiguration(apiObject *types.KxSavedownStorageConfiguration) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.Type; v != "" { + m["type"] = types.KxSavedownStorageType(v) + } + + if v := apiObject.Size; v >= 4 && v <= 16000 { + m["size"] = int32(v) + } + + return []interface{}{m} +} + +func flattenVpcConfiguration(apiObject *types.VpcConfiguration) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.VpcId; v != nil { + m["vpc_id"] = aws.ToString(v) + } + + if v := apiObject.SecurityGroupIds; v != nil { + m["security_group_ids"] = v + } + + if v := apiObject.SubnetIds; v != nil { + m["subnet_ids"] = v + } + + if v := apiObject.IpAddressType; v != "" { + m["ip_address_type"] = string(v) + } + + return []interface{}{m} +} + +func flattenCode(apiObject *types.CodeConfiguration) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.S3Bucket; v != nil { + m["s3_bucket"] = aws.ToString(v) + } + + if v := apiObject.S3Key; v != nil { + m["s3_key"] = aws.ToString(v) + } + + if v := apiObject.S3ObjectVersion; v != nil { + m["s3_object_version"] = aws.ToString(v) + } + + return []interface{}{m} +} + +func flattenCacheStorageConfiguration(apiObject *types.KxCacheStorageConfiguration) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.Type; *v != "" { + m["type"] = *v + } + + if v := apiObject.Size; v != nil { + m["size"] = aws.ToInt32(v) + } + + return m +} + +func flattenCacheStorageConfigurations(apiObjects []types.KxCacheStorageConfiguration) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var l []interface{} + + for _, apiObject := range apiObjects { + l = append(l, flattenCacheStorageConfiguration(&apiObject)) + } + + return l +} + +func flattenCacheConfiguration(apiObject *types.KxDatabaseCacheConfiguration) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.CacheType; aws.ToString(v) != "" { + m["cache_type"] = aws.ToString(v) + } + + if v := apiObject.DbPaths; v != nil { + m["db_paths"] = v + } + + return m +} + +func flattenCacheConfigurations(apiObjects []types.KxDatabaseCacheConfiguration) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var l []interface{} + + for _, apiObject := range apiObjects { + l = append(l, flattenCacheConfiguration(&apiObject)) + } + + return l +} + +func flattenDatabase(apiObject *types.KxDatabaseConfiguration) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.DatabaseName; v != nil { + m["database_name"] = aws.ToString(v) + } + + if v := apiObject.CacheConfigurations; v != nil { + m["cache_configurations"] = flattenCacheConfigurations(v) + } + + if v := apiObject.ChangesetId; v != nil { + m["changeset_id"] = aws.ToString(v) + } + + return m +} + +func flattenDatabases(apiObjects []types.KxDatabaseConfiguration) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var l []interface{} + + for _, apiObject := range apiObjects { + l = append(l, flattenDatabase(&apiObject)) + } + + return l +} + +func flattenCommandLineArguments(apiObjects []types.KxCommandLineArgument) map[string]string { + if len(apiObjects) == 0 { + return nil + } + + m := make(map[string]string) + + for _, apiObject := range apiObjects { + m[aws.ToString(apiObject.Key)] = aws.ToString(apiObject.Value) + } + + return m +} diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go new file mode 100644 index 000000000000..1b47dd904bd9 --- /dev/null +++ b/internal/service/finspace/kx_cluster_test.go @@ -0,0 +1,2195 @@ +package finspace_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "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" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tffinspace "github.com/hashicorp/terraform-provider-aws/internal/service/finspace" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccFinSpaceKxCluster_basic(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_disappears(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tffinspace.ResourceKxCluster(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_description(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_description(rName, "cluster description"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "description", "cluster description"), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_database(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_database(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_code(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + codePath := "code.zip" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_code(rName, codePath), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_multiAZ(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_multiAZ(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_rdb(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_rdb(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_executionRole(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_executionRole(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_autoScaling(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_autoScaling(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_initializationScript(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + // Need to set these to the bucket/key you want to use + codePath := "code.zip" + initScriptPath := "code/helloworld.q" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_initScript(rName, codePath, initScriptPath), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_commandLineArgs(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_commandLineArgs1(rName, "arg1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "command_line_arguments.%", "1"), + resource.TestCheckResourceAttr(resourceName, "command_line_arguments.arg1", "value1"), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxCluster_tags(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxcluster finspace.GetKxClusterOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKxClusterConfig_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + }, + }) +} + +func testAccCheckKxClusterDestroy(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() + ctx := context.Background() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_finspace_kx_cluster" { + continue + } + + input := &finspace.GetKxClusterInput{ + ClusterName: aws.String(rs.Primary.Attributes["name"]), + EnvironmentId: aws.String(rs.Primary.Attributes["environment_id"]), + } + _, err := conn.GetKxCluster(ctx, input) + if err != nil { + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + return nil + } + return err + } + + return create.Error(names.FinSpace, create.ErrActionCheckingDestroyed, tffinspace.ResNameKxCluster, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil +} + +func testAccCheckKxClusterExists(name string, kxcluster *finspace.GetKxClusterOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.FinSpace, create.ErrActionCheckingExistence, tffinspace.ResNameKxCluster, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.FinSpace, create.ErrActionCheckingExistence, tffinspace.ResNameKxCluster, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() + ctx := context.Background() + resp, err := conn.GetKxCluster(ctx, &finspace.GetKxClusterInput{ + ClusterName: aws.String(rs.Primary.Attributes["name"]), + EnvironmentId: aws.String(rs.Primary.Attributes["environment_id"]), + }) + + if err != nil { + return create.Error(names.FinSpace, create.ErrActionCheckingExistence, tffinspace.ResNameKxCluster, rs.Primary.ID, err) + } + + *kxcluster = *resp + + return nil + } +} + +func testAccKxClusterConfig_basic(rName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } +} +`, rName) +} + +func testAccKxClusterConfig_description(rName, description string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + description = %[2]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + type = "HDB" + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } +} +`, rName, description) +} + +func testAccKxClusterConfig_commandLineArgs1(rName, arg1, val1 string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.0.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + type = "HDB" + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + command_line_arguments = { + %[2]q = %[3]q + } +} +`, rName, arg1, val1) +} + +func testAccKxClusterConfig_tags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.0.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccKxClusterConfig_database(rName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_database" "test" { +name = %[1]q +environment_id =aws_finspace_kx_environment.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label ="1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + + cache_storage_configurations { + type = "CACHE_1000" + size = 1200 + } + + database { + database_name = aws_finspace_kx_database.test.name + cache_configurations { + cache_type = "CACHE_1000" + db_paths = ["/"] + } + } + + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } +} +`, rName) +} + +func testAccKxClusterConfig_code(rName, path string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +data "aws_iam_policy_document" "bucket_policy" { + + statement { + actions = [ + "s3:GetObject", + "s3:GetObjectTagging" + ] + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.test.id}/*", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "s3:ListBucket" + ] + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.test.id}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } +} + +resource "aws_s3_bucket_policy" "test" { + bucket = aws_s3_bucket.test.id + policy = data.aws_iam_policy_document.bucket_policy.json +} + +resource "aws_s3_object" "object" { + bucket = aws_s3_bucket.test.id + key = %[2]q + source = %[2]q +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label ="1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + code { + s3_bucket = aws_s3_bucket.test.id + s3_key = aws_s3_object.object.key + } +} +`, rName, path) +} + +func testAccKxClusterConfig_multiAZ(rName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test1" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.16.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_subnet" "test2" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[1] +} + +resource "aws_subnet" "test3" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.64.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[2] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label ="1.0" + az_mode ="MULTI" + capacity_configuration { + node_count = 3 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id, aws_subnet.test3.id] + ip_address_type = "IP_V4" + } +} +`, rName) +} + +func testAccKxClusterConfig_rdb(rName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "RDB" + release_label ="1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + + savedown_storage_configuration { + type = "SDS01" + size = 500 + } + + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } +} +`, rName) +} + +func testAccKxClusterConfig_executionRole(rName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_iam_policy" "test" { + name = %[1]q + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = ["finspace:ConnectKxCluster", "finspace:GetKxConnectionString"] + Effect = "Allow" + Resource = "*" + }, + ] + }) +} + +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "" + Principal = { + "Service": "prod.finspacekx.aws.internal", + "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + } + }, + ] + }) + + managed_policy_arns = [aws_iam_policy.test.arn] +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + execution_role = aws_iam_role.test.arn + + + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } +} +`, rName) +} + +func testAccKxClusterConfig_autoScaling(rName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { + node_count = 3 + node_type = "kx.s.xlarge" + } + + auto_scaling_configuration { + min_node_count = 3 + max_node_count = 5 + auto_scaling_metric = "CPU_UTILIZATION_PERCENTAGE" + metric_target = 25.0 + scale_in_cooldown_seconds = 30.0 + scale_out_cooldown_seconds = 30.0 + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } +} +`, rName) +} + +func testAccKxClusterConfig_initScript(rName, codePath, relPath string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +resource "aws_kms_key" "test" { +description = %[1]q +deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { +name = %[1]q +kms_key_id =aws_kms_key.test.arn +} + +data "aws_iam_policy_document" "key_policy" { + + statement { + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey" + ] + + resources = [ + "${aws_kms_key.test.arn}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "kms:*", + ] + + resources = [ + "*", + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_kms_key_policy" "test" { + key_id = aws_kms_key.test.id + policy = data.aws_iam_policy_document.key_policy.json +} + +resource "aws_vpc" "test" { + cidr_block = "172.31.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] +} + +resource "aws_security_group" "test" { + name = %[1]q + vpc_id = aws_vpc.test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +data "aws_route_tables" "rts" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "r" { + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +data "aws_iam_policy_document" "test" { + + statement { + actions = [ + "s3:GetObject", + "s3:GetObjectTagging" + ] + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.test.id}/*", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } + + statement { + actions = [ + "s3:ListBucket" + ] + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.test.id}", + ] + + principals { + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = ["${data.aws_caller_identity.current.account_id}"] + } + } +} + +resource "aws_s3_bucket_policy" "test" { + bucket = aws_s3_bucket.test.id + policy = data.aws_iam_policy_document.test.json +} + +resource "aws_s3_object" "object" { + bucket = aws_s3_bucket.test.id + key = %[2]q + source = %[2]q +} + +resource "aws_finspace_kx_database" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id +} + +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label ="1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + initialization_script = %[3]q + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + cache_storage_configurations { + type = "CACHE_1000" + size = 1200 + } + + database { + database_name = aws_finspace_kx_database.test.name + cache_configurations { + cache_type = "CACHE_1000" + db_paths = ["/"] + } + } + + code { + s3_bucket = aws_s3_bucket.test.id + s3_key = aws_s3_object.object.key + } +} +`, rName, codePath, relPath) +} diff --git a/internal/service/finspace/service_package_gen.go b/internal/service/finspace/service_package_gen.go index 774ce1af3cb6..dc6d1698e86b 100644 --- a/internal/service/finspace/service_package_gen.go +++ b/internal/service/finspace/service_package_gen.go @@ -24,7 +24,15 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac } func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { - return []*types.ServicePackageSDKResource{} + return []*types.ServicePackageSDKResource{ + { + Factory: ResourceKxCluster, + TypeName: "aws_finspace_kx_cluster", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: "arn", + }, + }, + } } func (p *servicePackage) ServicePackageName() string { diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown new file mode 100644 index 000000000000..cd9b48acc003 --- /dev/null +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -0,0 +1,169 @@ +--- +subcategory: "FinSpace" +layout: "aws" +page_title: "AWS: aws_finspace_kx_cluster" +description: |- + Terraform resource for managing an AWS FinSpace Kx Cluster. +--- + +# Resource: aws_finspace_kx_cluster + +Terraform resource for managing an AWS FinSpace Kx Cluster. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_finspace_kx_cluster" "example" { + name = "my-tf-kx-cluster" + environment_id = aws_finspace_kx_environment.example.id + type = "HDB" + release_label ="1.0" + az_mode = "SINGLE" + availability_zone_id = "use1-az2" + capacity_configuration { + node_type = "kx.s.2xlarge" + node_count = 2 + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.example.id] + subnet_ids = [aws_subnet.example.id] + ip_address_type = "IP_V4" + } + + cache_storage_configurations { + type = "CACHE_1000" + size = 1200 + } + + database { + database_name = aws_finspace_kx_database.example.name + cache_configuration { + cache_type = "CACHE_1000" + db_paths = "/" + } + } + + code { + s3_bucket = aws_s3_bucket.test.id + s3_key = aws_s3_object.object.key + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `environment_id` - (Required) Unique identifier for the KX environment. +* `name` - (Required) Unique name for the cluster that you want to create. +* `type` - (Required) Type of KDB database. The following types are available: + * HDB - Historical Database. The data is only accessible with read-only permissions from one of the FinSpace managed KX databases mounted to the cluster. + * RDB - Realtime Database. This type of database captures all the data from a ticker plant and stores it in memory until the end of day, after which it writes all of its data to a disk and reloads the HDB. This cluster type requires local storage for temporary storage of data during the savedown process. If you specify this field in your request, you must provide the `savedownStorageConfiguration` parameter. + * GATEWAY - A gateway cluster allows you to access data across processes in kdb systems. It allows you to create your own routing logic using the initialization scripts and custom code. This type of cluster does not require a writable local storage. +* `release_label` - (Required) Version of FinSpace Managed kdb to run. +* `az_mode` - (Required) The number of availability zones you want to assign per cluster. This can be one of the following: + * SINGLE - Assigns one availability zone per cluster. + * MULTI - Assigns all the availability zones per cluster. +* `capacity_configuration` - (Required) Structure for the metadata of a cluster. Includes information like the CPUs needed, memory of instances, number of instances, and the port used while establishing a connection. Defined below. +* `vpc_configuration` - (Required) Configuration details about the network where the Privatelink endpoint of the cluster resides. Defined below. + +The following arguments are optional: + +* `description` - (Optional) Description of the cluster. +* `availability_zone_id` - (Optional) The availability zone identifiers for the requested regions. Required when `az_mode` is set to SINGLE. +* `initialization_script` - (Optional) Path to Q program that will be run at launch of a cluster. This is a relative path within .zip file that contains the custom code, which will be loaded on the cluster. It must include the file name itself. For example, somedir/init.q. +* `execution_role` - (Optional) An IAM role that defines a set of permissions associated with a cluster. These permissions are assumed when a cluster attempts to access another cluster. +* `command_line_arguments` - (Optional) List of key-value pairs to make available inside the cluster. +* `database` - (Optional) KX database that will be available for querying. Defined below. +* `cache_storage_configurations` - (Optional) Configurations for a read only cache storage associated with a cluster. This cache will be stored as an FSx Lustre that reads from the S3 store. Defined below. +* `savedown_storage_configuration` - (Optional) Size and type of the temporary storage that is used to hold data during the savedown process. This parameter is required when you choose `type` as RDB. All the data written to this storage space is lost when the cluster node is restarted. Defined below. +* `auto_scaling_configuration` - (Optional) Configuration based on which FinSpace will scale in or scale out nodes in your cluster. Defined below. +* `code` - (Optional) Details of the custom code that you want to use inside a cluster when analyzing data. Consists of the S3 source bucket, location, object version, and the relative path from where the custom code is loaded into the cluster. Defined below. +* `tags` - (Optional) List of key-value pairs to label the cluster. + +### capacity_configuration +The capacity_configuration block supports the following arguments: + +* `node_type` - (Required) Determines the hardware of the host computer used for your cluster instance. Each node type offers different memory and storage capabilities. Choose a node type based on the requirements of the application or software that you plan to run on your instance. + + You can only specify one of the following values: + * kx.s.large – The node type with a configuration of 12 GiB memory and 2 vCPUs. + * kx.s.xlarge – The node type with a configuration of 27 GiB memory and 4 vCPUs. + * kx.s.2xlarge – The node type with a configuration of 54 GiB memory and 8 vCPUs. + * kx.s.4xlarge – The node type with a configuration of 108 GiB memory and 16 vCPUs. Confidential + * kx.s.8xlarge – The node type with a configuration of 216 GiB memory and 32 vCPUs. + * kx.s.16xlarge – The node type with a configuration of 432 GiB memory and 64 vCPUs. + * kx.s.32xlarge – The node type with a configuration of 864 GiB memory and 128 vCPUs. +* `node_count` - (Required) Number of instances running in a cluster. Must be at least 1 and at most 5. + +### vpc_configuration +The vpc_configuration block supports the following arguments: + +* `vpc_id` - (Required) Identifier of the VPC endpoint +* `security_group_ids` - (Required) Unique identifier of the VPC security group applied to the VPC endpoint ENI for the cluster. +* `subnet_ids `- (Required) Identifier of the subnet that the Privatelink VPC endpoint uses to connect to the cluster. +* `ip_address_type` - (Required) IP address type for cluster network configuration parameters. The following type is available: IP_V4 - IP address version 4. + +### code +The code block supports the following arguments: + +* `s3_bucket` - (Required) Unique name for the S3 bucket. +* `s3_key` - (Required) Full S3 path (excluding bucket) to the .zip file that contains the code to be loaded onto the cluster when it’s started. +* `s3_object_version` - (Optional) Version of an S3 Object. + +### database +The database block supports the following arguments: + +* `database_name` - (Required) Name of the KX database. +* `cache_configurations` - (Required) Configuration details for the disk cache to increase performance reading from a KX database mounted to the cluster. Detailed below. +* `changeset_id` - (Optional) A unique identifier of the changeset that is associated with the cluster. + +#### cache_configuration +The cache_configuration block supports the following arguments: + +* `cache_type` - (Required) Type of disk cache. +* `db_paths` - (Required) Paths within the database to cache. + +### cache_storage_configurations +The cache_storage_configurations block supports the following arguments: + +* `type` - (Required) Type of cache storage . The valid values are: + * CACHE_1000 - This type provides at least 1000 MB/s disk access throughput. +* `size` - (Required) Size of cache in Gigabytes. + +### savedown_storage_configuration +The savedown_storage_configuration block supports the following arguments: + +* `type` - (Required) Type of writeable storage space for temporarily storing your savedown data. The valid values are: + * SDS01 - This type represents 3000 IOPS and io2 ebs volume type. +* `size` - (Required) Size of temporary storage in bytes. + +### auto_scaling_configuration +The auto_scaling_configuration block supports the following arguments: + +* `auto_scaling_metric` - (Required) Metric your cluster will track in order to scale in and out. For example, CPU_UTILIZATION_PERCENTAGE is the average CPU usage across all nodes in a cluster. +* `min_node_count` - (Required) Lowest number of nodes to scale. Must be at least 1 and less than the `max_node_count`. If nodes in cluster belong to multiple availability zones, then `min_node_count` must be at least 3. +* `max_node_count` - (Required) Highest number of nodes to scale. Cannot be greater than 5 +* `metric_target` - (Required) Desired value of chosen `auto_scaling_metric`. When metric drops below this value, cluster will scale in. When metric goes above this value, cluster will scale out. Can be set between 0 and 100 percent. +* `scale_in_cooldown_seconds` - (Required) Duration in seconds that FinSpace will wait after a scale in event before initiating another scaling event. +* `scale_out_cooldown_seconds` - (Required) Duration in seconds that FinSpace will wait after a scale out event before initiating another scaling event. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `arn` - Amazon Resource Name (ARN) identifier of the KX cluster. +* `created_timestamp` - Timestamp at which the cluster is created in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. +* `last_modified_timestamp` - Last timestamp at which the cluster was updated in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. +* `tags_all` - Map of tags assigned to the resource. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `delete` - (Default `40m`) From 884db48fed8a860497c2e27bd9d5ffef65cee516 Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Wed, 7 Jun 2023 01:29:57 -0400 Subject: [PATCH 02/26] Formatting fixes to cluster --- internal/service/finspace/kx_cluster.go | 8 +- internal/service/finspace/kx_cluster_test.go | 516 +++++++++--------- .../docs/r/finspace_kx_cluster.html.markdown | 22 +- 3 files changed, 267 insertions(+), 279 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 8aa7ff214c4e..88f810bf0a23 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -538,8 +538,8 @@ func resourceKxClusterDelete(ctx context.Context, d *schema.ResourceData, meta i func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{string(types.KxClusterStatusPending), string(types.KxClusterStatusCreating)}, - Target: []string{string(types.KxClusterStatusRunning)}, + Pending: enum.Slice(types.KxClusterStatusPending, types.KxClusterStatusCreating), + Target: enum.Slice(types.KxClusterStatusRunning), Refresh: statusKxCluster(ctx, conn, clusterName, environmentId), Timeout: timeout, NotFoundChecks: 20, @@ -556,8 +556,8 @@ func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, clusterNam func waitKxClusterDeleted(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{string(types.KxClusterStatusDeleting)}, - Target: []string{string(types.KxClusterStatusDeleted)}, + Pending: enum.Slice(types.KxClusterStatusDeleting), + Target: enum.Slice(types.KxClusterStatusDeleted), Refresh: statusKxCluster(ctx, conn, clusterName, environmentId), Timeout: timeout, } diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index 1b47dd904bd9..3bc1f2ca8c8f 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -450,17 +450,16 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id =aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -479,13 +478,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -511,18 +510,18 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q + name = %[1]q vpc_id = aws_vpc.test.id ingress { @@ -549,28 +548,28 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } } `, rName) @@ -591,11 +590,10 @@ deletion_window_in_days = 7 resource "aws_finspace_kx_environment" "test" { name = %[1]q -kms_key_id =aws_kms_key.test.arn +kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -614,13 +612,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -646,18 +644,18 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q + name = %[1]q vpc_id = aws_vpc.test.id ingress { @@ -685,28 +683,28 @@ data "aws_route_tables" "rts" { resource "aws_route" "r" { route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - description = %[2]q - environment_id = aws_finspace_kx_environment.test.id - az_mode = "SINGLE" + name = %[1]q + description = %[2]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - type = "HDB" - release_label = "1.0" + type = "HDB" + release_label = "1.0" capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } } `, rName, description) @@ -727,11 +725,10 @@ deletion_window_in_days = 7 resource "aws_finspace_kx_environment" "test" { name = %[1]q -kms_key_id =aws_kms_key.test.arn +kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -756,7 +753,7 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -782,18 +779,18 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.0.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.0.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q + name = %[1]q vpc_id = aws_vpc.test.id ingress { @@ -820,28 +817,28 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - type = "HDB" - release_label = "1.0" + type = "HDB" + release_label = "1.0" capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } command_line_arguments = { @@ -860,17 +857,16 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id =aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -889,13 +885,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -921,19 +917,19 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.0.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.0.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { from_port = 0 @@ -959,28 +955,28 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - release_label = "1.0" + release_label = "1.0" capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } tags = { @@ -1005,11 +1001,10 @@ deletion_window_in_days = 7 resource "aws_finspace_kx_environment" "test" { name = %[1]q -kms_key_id =aws_kms_key.test.arn +kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -1028,13 +1023,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1060,18 +1055,18 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q + name = %[1]q vpc_id = aws_vpc.test.id ingress { @@ -1098,22 +1093,22 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_database" "test" { name = %[1]q -environment_id =aws_finspace_kx_environment.test.id +environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label ="1.0" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] cache_storage_configurations { @@ -1125,20 +1120,20 @@ resource "aws_finspace_kx_cluster" "test" { database_name = aws_finspace_kx_database.test.name cache_configurations { cache_type = "CACHE_1000" - db_paths = ["/"] + db_paths = ["/"] } } capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } } `, rName) @@ -1153,17 +1148,16 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id =aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -1182,13 +1176,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1214,19 +1208,19 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { from_port = 0 @@ -1252,9 +1246,9 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_s3_bucket" "test" { @@ -1281,13 +1275,13 @@ data "aws_iam_policy_document" "bucket_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1308,13 +1302,13 @@ data "aws_iam_policy_document" "bucket_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } } @@ -1331,27 +1325,27 @@ resource "aws_s3_object" "object" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label ="1.0" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } code { s3_bucket = aws_s3_bucket.test.id - s3_key = aws_s3_object.object.key + s3_key = aws_s3_object.object.key } } `, rName, path) @@ -1371,12 +1365,11 @@ deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id =aws_kms_key.test.arn +name = %[1]q +kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -1395,13 +1388,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1427,31 +1420,31 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test1" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.16.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.16.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_subnet" "test2" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[1] } resource "aws_subnet" "test3" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.64.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.64.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[2] } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { from_port = 0 @@ -1477,27 +1470,27 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { name = %[1]q environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label ="1.0" - az_mode ="MULTI" + type = "HDB" + release_label = "1.0" + az_mode = "MULTI" capacity_configuration { node_count = 3 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id, aws_subnet.test3.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id, aws_subnet.test3.id] + ip_address_type = "IP_V4" } } `, rName) @@ -1518,11 +1511,10 @@ deletion_window_in_days = 7 resource "aws_finspace_kx_environment" "test" { name = %[1]q -kms_key_id =aws_kms_key.test.arn +kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -1541,13 +1533,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1573,19 +1565,19 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { from_port = 0 @@ -1617,11 +1609,11 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "RDB" - release_label ="1.0" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "RDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] savedown_storage_configuration { @@ -1631,14 +1623,14 @@ resource "aws_finspace_kx_cluster" "test" { capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } } `, rName) @@ -1653,17 +1645,16 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id =aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -1682,13 +1673,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1714,18 +1705,18 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q + name = %[1]q vpc_id = aws_vpc.test.id ingress { @@ -1752,9 +1743,9 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_iam_policy" "test" { @@ -1776,17 +1767,17 @@ resource "aws_iam_role" "test" { name = %[1]q assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Sid = "" - Principal = { - "Service": "prod.finspacekx.aws.internal", - "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" - } - }, + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "" + Principal = { + "Service": "prod.finspacekx.aws.internal", + "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + } + }, ] }) @@ -1794,25 +1785,25 @@ resource "aws_iam_role" "test" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - execution_role = aws_iam_role.test.arn + execution_role = aws_iam_role.test.arn capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } } `, rName) @@ -1827,17 +1818,16 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id =aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -1856,13 +1846,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -1888,18 +1878,18 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q + name = %[1]q vpc_id = aws_vpc.test.id ingress { @@ -1926,37 +1916,37 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - capacity_configuration { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { node_count = 3 node_type = "kx.s.xlarge" - } + } auto_scaling_configuration { - min_node_count = 3 - max_node_count = 5 - auto_scaling_metric = "CPU_UTILIZATION_PERCENTAGE" - metric_target = 25.0 - scale_in_cooldown_seconds = 30.0 + min_node_count = 3 + max_node_count = 5 + auto_scaling_metric = "CPU_UTILIZATION_PERCENTAGE" + metric_target = 25.0 + scale_in_cooldown_seconds = 30.0 scale_out_cooldown_seconds = 30.0 } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } } `, rName) @@ -1977,11 +1967,10 @@ deletion_window_in_days = 7 resource "aws_finspace_kx_environment" "test" { name = %[1]q -kms_key_id =aws_kms_key.test.arn +kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { - statement { actions = [ "kms:Decrypt", @@ -2000,13 +1989,13 @@ data "aws_iam_policy_document" "key_policy" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -2032,19 +2021,19 @@ resource "aws_kms_key_policy" "test" { } resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" + cidr_block = "172.31.0.0/16" enable_dns_hostnames = true } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" + vpc_id = aws_vpc.test.id + cidr_block = "172.31.32.0/20" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { from_port = 0 @@ -2070,9 +2059,9 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_s3_bucket" "test" { @@ -2080,7 +2069,6 @@ resource "aws_s3_bucket" "test" { } data "aws_iam_policy_document" "test" { - statement { actions = [ "s3:GetObject", @@ -2099,13 +2087,13 @@ data "aws_iam_policy_document" "test" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } @@ -2126,13 +2114,13 @@ data "aws_iam_policy_document" "test" { condition { test = "ArnLike" variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { test = "StringEquals" variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] + values = ["${data.aws_caller_identity.current.account_id}"] } } } @@ -2150,27 +2138,27 @@ resource "aws_s3_object" "object" { resource "aws_finspace_kx_database" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label ="1.0" - az_mode = "SINGLE" + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] capacity_configuration { node_count = 2 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } initialization_script = %[3]q vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } cache_storage_configurations { @@ -2182,13 +2170,13 @@ resource "aws_finspace_kx_cluster" "test" { database_name = aws_finspace_kx_database.test.name cache_configurations { cache_type = "CACHE_1000" - db_paths = ["/"] + db_paths = ["/"] } } code { s3_bucket = aws_s3_bucket.test.id - s3_key = aws_s3_object.object.key + s3_key = aws_s3_object.object.key } } `, rName, codePath, relPath) diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown index cd9b48acc003..c8ebeff206a4 100644 --- a/website/docs/r/finspace_kx_cluster.html.markdown +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -16,22 +16,22 @@ Terraform resource for managing an AWS FinSpace Kx Cluster. ```terraform resource "aws_finspace_kx_cluster" "example" { - name = "my-tf-kx-cluster" - environment_id = aws_finspace_kx_environment.example.id - type = "HDB" - release_label ="1.0" - az_mode = "SINGLE" + name = "my-tf-kx-cluster" + environment_id = aws_finspace_kx_environment.example.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = "use1-az2" capacity_configuration { - node_type = "kx.s.2xlarge" + node_type = "kx.s.2xlarge" node_count = 2 } vpc_configuration { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.example.id] - subnet_ids = [aws_subnet.example.id] - ip_address_type = "IP_V4" + subnet_ids = [aws_subnet.example.id] + ip_address_type = "IP_V4" } cache_storage_configurations { @@ -43,13 +43,13 @@ resource "aws_finspace_kx_cluster" "example" { database_name = aws_finspace_kx_database.example.name cache_configuration { cache_type = "CACHE_1000" - db_paths = "/" + db_paths = "/" } } code { s3_bucket = aws_s3_bucket.test.id - s3_key = aws_s3_object.object.key + s3_key = aws_s3_object.object.key } } ``` From b48b61a77ea6d1499f5192cf3a0ae003daeb2d57 Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Wed, 7 Jun 2023 17:47:55 -0400 Subject: [PATCH 03/26] Formatting fixes for kx cluster --- internal/service/finspace/kx_cluster.go | 32 +- internal/service/finspace/kx_cluster_test.go | 1137 +++++++++--------- 2 files changed, 580 insertions(+), 589 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 88f810bf0a23..9ba70b38d31e 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -175,12 +175,10 @@ func ResourceKxCluster() *schema.Resource { }, }, "ip_address_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - string(types.IPAddressTypeIpV4), - }, true), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(enum.Slice(types.IPAddressTypeIpV4), true), }, }, }, @@ -196,9 +194,8 @@ func ResourceKxCluster() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - string(types.AutoScalingMetricCpuUtilizationPercentage), - }, true), + ValidateFunc: validation.StringInSlice( + enum.Slice(types.AutoScalingMetricCpuUtilizationPercentage), true), }, "min_node_count": { Type: schema.TypeInt, @@ -244,9 +241,8 @@ func ResourceKxCluster() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - string(types.KxSavedownStorageTypeSds01), - }, true), + ValidateFunc: validation.StringInSlice( + enum.Slice(types.KxSavedownStorageTypeSds01), true), }, "size": { Type: schema.TypeInt, @@ -398,7 +394,7 @@ func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta i } if v, ok := d.GetOk("vpc_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { - in.VpcConfiguration = expandVpcConfiguration(v.([]interface{})) + in.VpcConfiguration = expandVPCConfiguration(v.([]interface{})) } if v, ok := d.GetOk("auto_scaling_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { @@ -474,7 +470,7 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) } - if err := d.Set("vpc_configuration", flattenVpcConfiguration(out.VpcConfiguration)); err != nil { + if err := d.Set("vpc_configuration", flattenVPCConfiguration(out.VpcConfiguration)); err != nil { return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) } @@ -687,7 +683,7 @@ func expandSavedownStorageConfiguration(tfList []interface{}) *types.KxSavedownS return a } -func expandVpcConfiguration(tfList []interface{}) *types.VpcConfiguration { +func expandVPCConfiguration(tfList []interface{}) *types.VpcConfiguration { if len(tfList) == 0 || tfList[0] == nil { return nil } @@ -977,7 +973,7 @@ func flattenSavedownStorageConfiguration(apiObject *types.KxSavedownStorageConfi return []interface{}{m} } -func flattenVpcConfiguration(apiObject *types.VpcConfiguration) []interface{} { +func flattenVPCConfiguration(apiObject *types.VpcConfiguration) []interface{} { if apiObject == nil { return nil } @@ -1032,8 +1028,8 @@ func flattenCacheStorageConfiguration(apiObject *types.KxCacheStorageConfigurati m := map[string]interface{}{} - if v := apiObject.Type; *v != "" { - m["type"] = *v + if v := apiObject.Type; aws.ToString(v) != "" { + m["type"] = aws.ToString(v) } if v := apiObject.Size; v != nil { diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index 3bc1f2ca8c8f..c5e2168053f7 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -455,37 +455,37 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -497,7 +497,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -521,21 +521,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -554,23 +554,23 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } `, rName) } @@ -584,42 +584,42 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -631,7 +631,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -655,21 +655,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -682,30 +682,30 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - description = %[2]q - environment_id = aws_finspace_kx_environment.test.id - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - type = "HDB" - release_label = "1.0" - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + name = %[1]q + description = %[2]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + type = "HDB" + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } `, rName, description) } @@ -719,42 +719,42 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -766,7 +766,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -790,21 +790,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -823,27 +823,27 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - type = "HDB" - release_label = "1.0" - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } - - command_line_arguments = { - %[2]q = %[3]q - } + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + type = "HDB" + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + command_line_arguments = { + %[2]q = %[3]q + } } `, rName, arg1, val1) } @@ -862,37 +862,37 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -904,7 +904,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -928,21 +928,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -961,27 +961,27 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - release_label = "1.0" - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } - - tags = { - %[2]q = %[3]q - } + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + tags = { + %[2]q = %[3]q + } } `, rName, tagKey1, tagValue1) } @@ -995,42 +995,42 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -1042,7 +1042,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -1066,21 +1066,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -1099,17 +1099,17 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_database" "test" { -name = %[1]q -environment_id = aws_finspace_kx_environment.test.id + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] cache_storage_configurations { type = "CACHE_1000" @@ -1117,24 +1117,24 @@ resource "aws_finspace_kx_cluster" "test" { } database { - database_name = aws_finspace_kx_database.test.name - cache_configurations { + database_name = aws_finspace_kx_database.test.name + cache_configurations { cache_type = "CACHE_1000" - db_paths = ["/"] - } + db_paths = ["/"] + } } - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } `, rName) } @@ -1153,37 +1153,37 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -1195,7 +1195,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -1219,21 +1219,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -1256,60 +1256,59 @@ resource "aws_s3_bucket" "test" { } data "aws_iam_policy_document" "bucket_policy" { - statement { actions = [ "s3:GetObject", - "s3:GetObjectTagging" + "s3:GetObjectTagging" ] resources = [ "arn:aws:s3:::${aws_s3_bucket.test.id}/*", ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { actions = [ - "s3:ListBucket" + "s3:ListBucket" ] resources = [ "arn:aws:s3:::${aws_s3_bucket.test.id}", ] - - principals { + + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } } @@ -1319,33 +1318,33 @@ resource "aws_s3_bucket_policy" "test" { } resource "aws_s3_object" "object" { - bucket = aws_s3_bucket.test.id - key = %[2]q - source = %[2]q + bucket = aws_s3_bucket.test.id + key = %[2]q + source = %[2]q } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } code { - s3_bucket = aws_s3_bucket.test.id - s3_key = aws_s3_object.object.key + s3_bucket = aws_s3_bucket.test.id + s3_key = aws_s3_object.object.key } } `, rName, path) @@ -1360,42 +1359,42 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -1407,7 +1406,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -1447,17 +1446,17 @@ resource "aws_security_group" "test" { vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -1476,22 +1475,22 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "MULTI" - capacity_configuration { - node_count = 3 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id, aws_subnet.test3.id] - ip_address_type = "IP_V4" - } + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "MULTI" + capacity_configuration { + node_count = 3 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id, aws_subnet.test3.id] + ip_address_type = "IP_V4" + } } `, rName) } @@ -1505,42 +1504,42 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -1552,7 +1551,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -1576,21 +1575,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -1603,9 +1602,9 @@ data "aws_route_tables" "rts" { } resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] + route_table_id = tolist(data.aws_route_tables.rts.ids)[0] destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id + gateway_id = aws_internet_gateway.test.id } resource "aws_finspace_kx_cluster" "test" { @@ -1621,17 +1620,17 @@ resource "aws_finspace_kx_cluster" "test" { size = 500 } - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } `, rName) } @@ -1650,37 +1649,37 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -1692,7 +1691,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -1716,21 +1715,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -1749,10 +1748,9 @@ resource "aws_route" "r" { } resource "aws_iam_policy" "test" { - name = %[1]q - + name = %[1]q policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17" Statement = [ { Action = ["finspace:ConnectKxCluster", "finspace:GetKxConnectionString"] @@ -1764,9 +1762,9 @@ resource "aws_iam_policy" "test" { } resource "aws_iam_role" "test" { - name = %[1]q - - assume_role_policy = jsonencode({ + name = %[1]q + managed_policy_arns = [aws_iam_policy.test.arn] + assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { @@ -1775,36 +1773,33 @@ resource "aws_iam_role" "test" { Sid = "" Principal = { "Service": "prod.finspacekx.aws.internal", - "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" } }, ] }) - - managed_policy_arns = [aws_iam_policy.test.arn] } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - execution_role = aws_iam_role.test.arn - - - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + execution_role = aws_iam_role.test.arn + + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } `, rName) } @@ -1823,37 +1818,37 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -1865,7 +1860,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -1889,21 +1884,21 @@ resource "aws_subnet" "test" { } resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id + name = %[1]q + vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -1929,25 +1924,25 @@ resource "aws_finspace_kx_cluster" "test" { az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] capacity_configuration { - node_count = 3 - node_type = "kx.s.xlarge" + node_count = 3 + node_type = "kx.s.xlarge" } - auto_scaling_configuration { - min_node_count = 3 + auto_scaling_configuration { + min_node_count = 3 max_node_count = 5 - auto_scaling_metric = "CPU_UTILIZATION_PERCENTAGE" - metric_target = 25.0 - scale_in_cooldown_seconds = 30.0 - scale_out_cooldown_seconds = 30.0 - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } + auto_scaling_metric = "CPU_UTILIZATION_PERCENTAGE" + metric_target = 25.0 + scale_in_cooldown_seconds = 30.0 + scale_out_cooldown_seconds = 30.0 + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } `, rName) } @@ -1961,42 +1956,42 @@ output "account_id" { } resource "aws_kms_key" "test" { -description = %[1]q -deletion_window_in_days = 7 + description = %[1]q + deletion_window_in_days = 7 } resource "aws_finspace_kx_environment" "test" { -name = %[1]q -kms_key_id = aws_kms_key.test.arn + name = %[1]q + kms_key_id = aws_kms_key.test.arn } data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ - "${aws_kms_key.test.arn}", + aws_kms_key.test.arn, ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { @@ -2008,7 +2003,7 @@ data "aws_iam_policy_document" "key_policy" { "*", ] - principals { + principals { type = "AWS" identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] } @@ -2036,17 +2031,17 @@ resource "aws_security_group" "test" { vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } } @@ -2065,63 +2060,63 @@ resource "aws_route" "r" { } resource "aws_s3_bucket" "test" { - bucket = %[1]q + bucket = %[1]q } data "aws_iam_policy_document" "test" { statement { actions = [ "s3:GetObject", - "s3:GetObjectTagging" + "s3:GetObjectTagging" ] resources = [ "arn:aws:s3:::${aws_s3_bucket.test.id}/*", ] - principals { + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } statement { actions = [ - "s3:ListBucket" + "s3:ListBucket" ] resources = [ "arn:aws:s3:::${aws_s3_bucket.test.id}", ] - - principals { + + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = ["${data.aws_caller_identity.current.account_id}"] - } + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } } } @@ -2137,46 +2132,46 @@ resource "aws_s3_object" "object" { } resource "aws_finspace_kx_database" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - initialization_script = %[3]q - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } - - cache_storage_configurations { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + initialization_script = %[3]q + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + cache_storage_configurations { type = "CACHE_1000" size = 1200 } database { - database_name = aws_finspace_kx_database.test.name - cache_configurations { + database_name = aws_finspace_kx_database.test.name + cache_configurations { cache_type = "CACHE_1000" - db_paths = ["/"] - } + db_paths = ["/"] + } } code { - s3_bucket = aws_s3_bucket.test.id - s3_key = aws_s3_object.object.key + s3_bucket = aws_s3_bucket.test.id + s3_key = aws_s3_object.object.key } } `, rName, codePath, relPath) From 045b1f36b75d01960546545e5f8a8d91acf5a2db Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Thu, 8 Jun 2023 01:36:21 -0400 Subject: [PATCH 04/26] Formatting fixes for kx cluster tests and docs --- internal/service/finspace/kx_cluster_test.go | 176 +++++++++--------- .../docs/r/finspace_kx_cluster.html.markdown | 36 ++-- 2 files changed, 110 insertions(+), 102 deletions(-) diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index c5e2168053f7..e9428c9cece3 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -476,13 +476,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -555,7 +555,7 @@ resource "aws_route" "r" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "HDB" release_label = "1.0" az_mode = "SINGLE" @@ -610,13 +610,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -689,8 +689,8 @@ resource "aws_route" "r" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - description = %[2]q - environment_id = aws_finspace_kx_environment.test.id + description = %[2]q + environment_id = aws_finspace_kx_environment.test.id az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] type = "HDB" @@ -724,7 +724,7 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q + name = %[1]q kms_key_id = aws_kms_key.test.arn } @@ -745,13 +745,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -824,11 +824,11 @@ resource "aws_route" "r" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] type = "HDB" - release_label = "1.0" + release_label = "1.0" capacity_configuration { node_count = 2 node_type = "kx.s.xlarge" @@ -862,7 +862,7 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q + name = %[1]q kms_key_id = aws_kms_key.test.arn } @@ -883,13 +883,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -962,11 +962,11 @@ resource "aws_route" "r" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "HDB" az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - release_label = "1.0" + release_label = "1.0" capacity_configuration { node_count = 2 node_type = "kx.s.xlarge" @@ -1021,14 +1021,14 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" - variable = "aws:SourceArn" + test = "ArnLike" + variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" - variable = "aws:SourceAccount" + test = "StringEquals" + variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } } @@ -1099,15 +1099,15 @@ resource "aws_route" "r" { } resource "aws_finspace_kx_database" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "HDB" - release_label = "1.0" + release_label = "1.0" az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] @@ -1153,7 +1153,7 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q + name = %[1]q kms_key_id = aws_kms_key.test.arn } @@ -1174,13 +1174,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -1252,7 +1252,7 @@ resource "aws_route" "r" { } resource "aws_s3_bucket" "test" { - bucket = %[1]q + bucket = %[1]q } data "aws_iam_policy_document" "bucket_policy" { @@ -1272,13 +1272,13 @@ data "aws_iam_policy_document" "bucket_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -1292,20 +1292,20 @@ data "aws_iam_policy_document" "bucket_policy" { resources = [ "arn:aws:s3:::${aws_s3_bucket.test.id}", ] - + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -1325,9 +1325,9 @@ resource "aws_s3_object" "object" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "HDB" - release_label = "1.0" + release_label = "1.0" az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] capacity_configuration { @@ -1385,13 +1385,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -1478,8 +1478,8 @@ resource "aws_finspace_kx_cluster" "test" { name = %[1]q environment_id = aws_finspace_kx_environment.test.id type = "HDB" - release_label = "1.0" - az_mode = "MULTI" + release_label = "1.0" + az_mode = "MULTI" capacity_configuration { node_count = 3 node_type = "kx.s.xlarge" @@ -1530,14 +1530,14 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" - variable = "aws:SourceArn" + test = "ArnLike" + variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" - variable = "aws:SourceAccount" + test = "StringEquals" + variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } } @@ -1609,9 +1609,9 @@ resource "aws_route" "r" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "RDB" - release_label = "1.0" + release_label = "1.0" az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] @@ -1649,7 +1649,7 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q + name = %[1]q kms_key_id = aws_kms_key.test.arn } @@ -1670,13 +1670,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -1748,9 +1748,9 @@ resource "aws_route" "r" { } resource "aws_iam_policy" "test" { - name = %[1]q + name = %[1]q policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17" Statement = [ { Action = ["finspace:ConnectKxCluster", "finspace:GetKxConnectionString"] @@ -1764,25 +1764,25 @@ resource "aws_iam_policy" "test" { resource "aws_iam_role" "test" { name = %[1]q managed_policy_arns = [aws_iam_policy.test.arn] - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ { - Action = "sts:AssumeRole" - Effect = "Allow" - Sid = "" + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "" Principal = { - "Service": "prod.finspacekx.aws.internal", - "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + "Service" : "prod.finspacekx.aws.internal", + "AWS" : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" } }, ] - }) + }) } resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "HDB" release_label = "1.0" az_mode = "SINGLE" @@ -1818,7 +1818,7 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[1]q + name = %[1]q kms_key_id = aws_kms_key.test.arn } @@ -1826,7 +1826,7 @@ data "aws_iam_policy_document" "key_policy" { statement { actions = [ "kms:Decrypt", - "kms:GenerateDataKey" + "kms:GenerateDataKey" ] resources = [ @@ -1839,13 +1839,13 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -1918,14 +1918,14 @@ resource "aws_route" "r" { resource "aws_finspace_kx_cluster" "test" { name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + environment_id = aws_finspace_kx_environment.test.id type = "HDB" release_label = "1.0" az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] capacity_configuration { node_count = 3 - node_type = "kx.s.xlarge" + node_type = "kx.s.xlarge" } auto_scaling_configuration { @@ -1982,15 +1982,15 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] } } @@ -2031,10 +2031,10 @@ resource "aws_security_group" "test" { vpc_id = aws_vpc.test.id ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] } egress { @@ -2080,13 +2080,13 @@ data "aws_iam_policy_document" "test" { } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -2100,20 +2100,20 @@ data "aws_iam_policy_document" "test" { resources = [ "arn:aws:s3:::${aws_s3_bucket.test.id}", ] - + principals { type = "Service" identifiers = ["finspace.amazonaws.com"] } condition { - test = "ArnLike" + test = "ArnLike" variable = "aws:SourceArn" values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" + test = "StringEquals" variable = "aws:SourceAccount" values = [data.aws_caller_identity.current.account_id] } @@ -2126,21 +2126,21 @@ resource "aws_s3_bucket_policy" "test" { } resource "aws_s3_object" "object" { - bucket = aws_s3_bucket.test.id - key = %[2]q - source = %[2]q + bucket = aws_s3_bucket.test.id + key = %[2]q + source = %[2]q } resource "aws_finspace_kx_database" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { name = %[1]q environment_id = aws_finspace_kx_environment.test.id type = "HDB" - release_label = "1.0" + release_label = "1.0" az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] initialization_script = %[3]q diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown index c8ebeff206a4..927a11590493 100644 --- a/website/docs/r/finspace_kx_cluster.html.markdown +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -61,13 +61,13 @@ The following arguments are required: * `environment_id` - (Required) Unique identifier for the KX environment. * `name` - (Required) Unique name for the cluster that you want to create. * `type` - (Required) Type of KDB database. The following types are available: - * HDB - Historical Database. The data is only accessible with read-only permissions from one of the FinSpace managed KX databases mounted to the cluster. - * RDB - Realtime Database. This type of database captures all the data from a ticker plant and stores it in memory until the end of day, after which it writes all of its data to a disk and reloads the HDB. This cluster type requires local storage for temporary storage of data during the savedown process. If you specify this field in your request, you must provide the `savedownStorageConfiguration` parameter. - * GATEWAY - A gateway cluster allows you to access data across processes in kdb systems. It allows you to create your own routing logic using the initialization scripts and custom code. This type of cluster does not require a writable local storage. + * HDB - Historical Database. The data is only accessible with read-only permissions from one of the FinSpace managed KX databases mounted to the cluster. + * RDB - Realtime Database. This type of database captures all the data from a ticker plant and stores it in memory until the end of day, after which it writes all of its data to a disk and reloads the HDB. This cluster type requires local storage for temporary storage of data during the savedown process. If you specify this field in your request, you must provide the `savedownStorageConfiguration` parameter. + * GATEWAY - A gateway cluster allows you to access data across processes in kdb systems. It allows you to create your own routing logic using the initialization scripts and custom code. This type of cluster does not require a writable local storage. * `release_label` - (Required) Version of FinSpace Managed kdb to run. * `az_mode` - (Required) The number of availability zones you want to assign per cluster. This can be one of the following: - * SINGLE - Assigns one availability zone per cluster. - * MULTI - Assigns all the availability zones per cluster. + * SINGLE - Assigns one availability zone per cluster. + * MULTI - Assigns all the availability zones per cluster. * `capacity_configuration` - (Required) Structure for the metadata of a cluster. Includes information like the CPUs needed, memory of instances, number of instances, and the port used while establishing a connection. Defined below. * `vpc_configuration` - (Required) Configuration details about the network where the Privatelink endpoint of the cluster resides. Defined below. @@ -86,21 +86,23 @@ The following arguments are optional: * `tags` - (Optional) List of key-value pairs to label the cluster. ### capacity_configuration + The capacity_configuration block supports the following arguments: * `node_type` - (Required) Determines the hardware of the host computer used for your cluster instance. Each node type offers different memory and storage capabilities. Choose a node type based on the requirements of the application or software that you plan to run on your instance. You can only specify one of the following values: - * kx.s.large – The node type with a configuration of 12 GiB memory and 2 vCPUs. - * kx.s.xlarge – The node type with a configuration of 27 GiB memory and 4 vCPUs. - * kx.s.2xlarge – The node type with a configuration of 54 GiB memory and 8 vCPUs. - * kx.s.4xlarge – The node type with a configuration of 108 GiB memory and 16 vCPUs. Confidential - * kx.s.8xlarge – The node type with a configuration of 216 GiB memory and 32 vCPUs. - * kx.s.16xlarge – The node type with a configuration of 432 GiB memory and 64 vCPUs. - * kx.s.32xlarge – The node type with a configuration of 864 GiB memory and 128 vCPUs. + * kx.s.large – The node type with a configuration of 12 GiB memory and 2 vCPUs. + * kx.s.xlarge – The node type with a configuration of 27 GiB memory and 4 vCPUs. + * kx.s.2xlarge – The node type with a configuration of 54 GiB memory and 8 vCPUs. + * kx.s.4xlarge – The node type with a configuration of 108 GiB memory and 16 vCPUs. + * kx.s.8xlarge – The node type with a configuration of 216 GiB memory and 32 vCPUs. + * kx.s.16xlarge – The node type with a configuration of 432 GiB memory and 64 vCPUs. + * kx.s.32xlarge – The node type with a configuration of 864 GiB memory and 128 vCPUs. * `node_count` - (Required) Number of instances running in a cluster. Must be at least 1 and at most 5. ### vpc_configuration + The vpc_configuration block supports the following arguments: * `vpc_id` - (Required) Identifier of the VPC endpoint @@ -109,6 +111,7 @@ The vpc_configuration block supports the following arguments: * `ip_address_type` - (Required) IP address type for cluster network configuration parameters. The following type is available: IP_V4 - IP address version 4. ### code + The code block supports the following arguments: * `s3_bucket` - (Required) Unique name for the S3 bucket. @@ -116,6 +119,7 @@ The code block supports the following arguments: * `s3_object_version` - (Optional) Version of an S3 Object. ### database + The database block supports the following arguments: * `database_name` - (Required) Name of the KX database. @@ -123,26 +127,30 @@ The database block supports the following arguments: * `changeset_id` - (Optional) A unique identifier of the changeset that is associated with the cluster. #### cache_configuration + The cache_configuration block supports the following arguments: * `cache_type` - (Required) Type of disk cache. * `db_paths` - (Required) Paths within the database to cache. ### cache_storage_configurations + The cache_storage_configurations block supports the following arguments: * `type` - (Required) Type of cache storage . The valid values are: - * CACHE_1000 - This type provides at least 1000 MB/s disk access throughput. + * CACHE_1000 - This type provides at least 1000 MB/s disk access throughput. * `size` - (Required) Size of cache in Gigabytes. ### savedown_storage_configuration + The savedown_storage_configuration block supports the following arguments: * `type` - (Required) Type of writeable storage space for temporarily storing your savedown data. The valid values are: - * SDS01 - This type represents 3000 IOPS and io2 ebs volume type. + * SDS01 - This type represents 3000 IOPS and io2 ebs volume type. * `size` - (Required) Size of temporary storage in bytes. ### auto_scaling_configuration + The auto_scaling_configuration block supports the following arguments: * `auto_scaling_metric` - (Required) Metric your cluster will track in order to scale in and out. For example, CPU_UTILIZATION_PERCENTAGE is the average CPU usage across all nodes in a cluster. From 4c0555f197a56d3f8cf94662626775efcd6be141 Mon Sep 17 00:00:00 2001 From: Kavan Bansal <124836223+kavan-aws@users.noreply.github.com> Date: Thu, 8 Jun 2023 11:23:23 -0400 Subject: [PATCH 05/26] Update kx_cluster_test.go --- internal/service/finspace/kx_cluster_test.go | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index e9428c9cece3..d651c1c2726c 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -1021,15 +1021,15 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] } } @@ -1530,15 +1530,15 @@ data "aws_iam_policy_document" "key_policy" { } condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] } condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] } } @@ -1765,7 +1765,7 @@ resource "aws_iam_role" "test" { name = %[1]q managed_policy_arns = [aws_iam_policy.test.arn] assume_role_policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" From a7a6009a72c3b466341af8fb28d48439bce5ce9a Mon Sep 17 00:00:00 2001 From: Kavan Bansal <124836223+kavan-aws@users.noreply.github.com> Date: Thu, 8 Jun 2023 11:24:18 -0400 Subject: [PATCH 06/26] Update finspace_kx_cluster.html.markdown --- website/docs/r/finspace_kx_cluster.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown index 927a11590493..4877aebbf6f2 100644 --- a/website/docs/r/finspace_kx_cluster.html.markdown +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -92,7 +92,7 @@ The capacity_configuration block supports the following arguments: * `node_type` - (Required) Determines the hardware of the host computer used for your cluster instance. Each node type offers different memory and storage capabilities. Choose a node type based on the requirements of the application or software that you plan to run on your instance. You can only specify one of the following values: - * kx.s.large – The node type with a configuration of 12 GiB memory and 2 vCPUs. + * kx.s.large – The node type with a configuration of 12 GiB memory and 2 vCPUs. * kx.s.xlarge – The node type with a configuration of 27 GiB memory and 4 vCPUs. * kx.s.2xlarge – The node type with a configuration of 54 GiB memory and 8 vCPUs. * kx.s.4xlarge – The node type with a configuration of 108 GiB memory and 16 vCPUs. From 892f0eef9a7af921877b2759a6b4f35d42eb2211 Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Thu, 8 Jun 2023 12:18:00 -0400 Subject: [PATCH 07/26] Resolve merge conflicts --- .changelog/31802.txt | 3 + internal/service/finspace/generate.go | 2 +- internal/service/finspace/kx_environment.go | 592 ++++++++++++++++++ .../service/finspace/kx_environment_test.go | 441 +++++++++++++ .../service/finspace/service_package_gen.go | 7 + internal/service/finspace/tags_gen.go | 57 ++ .../r/finspace_kx_environment.html.markdown | 113 ++++ 7 files changed, 1214 insertions(+), 1 deletion(-) create mode 100644 .changelog/31802.txt create mode 100644 internal/service/finspace/kx_environment.go create mode 100644 internal/service/finspace/kx_environment_test.go create mode 100644 website/docs/r/finspace_kx_environment.html.markdown diff --git a/.changelog/31802.txt b/.changelog/31802.txt new file mode 100644 index 000000000000..d811382f06fa --- /dev/null +++ b/.changelog/31802.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_finspace_kx_environment +``` diff --git a/internal/service/finspace/generate.go b/internal/service/finspace/generate.go index f366292b6910..9258825e3654 100644 --- a/internal/service/finspace/generate.go +++ b/internal/service/finspace/generate.go @@ -1,4 +1,4 @@ -//go:generate go run ../../generate/tags/main.go -ServiceTagsMap -AWSSDKVersion=2 -KVTValues -ListTags -SkipTypesImp +//go:generate go run ../../generate/tags/main.go -ServiceTagsMap -AWSSDKVersion=2 -KVTValues -ListTags -CreateTags -UpdateTags -SkipTypesImp // ONLY generate directives and package declaration! Do not add anything else to this file. package finspace diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go new file mode 100644 index 000000000000..234a47f3b15a --- /dev/null +++ b/internal/service/finspace/kx_environment.go @@ -0,0 +1,592 @@ +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/id" + "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/errs" + 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_environment", name="Kx Environment") +// @Tags(identifierAttribute="arn") +func ResourceKxEnvironment() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceKxEnvironmentCreate, + ReadWithoutTimeout: resourceKxEnvironmentRead, + UpdateWithoutTimeout: resourceKxEnvironmentUpdate, + DeleteWithoutTimeout: resourceKxEnvironmentDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "availability_zones": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + }, + "created_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "custom_dns_configuration": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "custom_dns_server_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(3, 255), + }, + "custom_dns_server_ip": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsIPAddress, + }, + }, + }, + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 1000), + }, + "id": { + Type: schema.TypeString, + Computed: true, + }, + "infrastructure_account_id": { + Type: schema.TypeString, + Computed: true, + }, + "kms_key_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, + "last_modified_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), + "transit_gateway_configuration": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "transit_gateway_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 32), + }, + "routable_cidr_space": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsCIDR, + }, + }, + }, + }, + }, + CustomizeDiff: verify.SetTagsDiff, + } +} + +const ( + ResNameKxEnvironment = "Kx Environment" +) + +func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).FinSpaceClient() + + in := &finspace.CreateKxEnvironmentInput{ + Name: aws.String(d.Get("name").(string)), + ClientToken: aws.String(id.UniqueId()), + } + + if v, ok := d.GetOk("description"); ok { + in.Description = aws.String(v.(string)) + } + + if v, ok := d.GetOk("kms_key_id"); ok { + in.KmsKeyId = aws.String(v.(string)) + } + + out, err := conn.CreateKxEnvironment(ctx, in) + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), err)...) + } + + if out == nil || out.EnvironmentId == nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), errors.New("empty output"))...) + } + + d.SetId(aws.ToString(out.EnvironmentId)) + + if _, err := waitKxEnvironmentCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxEnvironment, d.Id(), err)...) + } + + if err := updateKxEnvironmentNetwork(ctx, d, conn); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Id(), err)...) + } + + // The CreateKxEnvironment API currently fails to tag the environment when the + // Tags field is set. Until the API is fixed, tag after creation instead. + if err := createTags(ctx, conn, aws.ToString(out.EnvironmentArn), GetTagsIn(ctx)); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Id(), err)...) + } + + return append(diags, resourceKxEnvironmentRead(ctx, d, meta)...) +} + +func resourceKxEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).FinSpaceClient() + + out, err := findKxEnvironmentByID(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] FinSpace KxEnvironment (%s) not found, removing from state", d.Id()) + d.SetId("") + return diags + } + + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionReading, ResNameKxEnvironment, d.Id(), err)...) + } + + d.Set("id", out.EnvironmentId) + d.Set("arn", out.EnvironmentArn) + d.Set("name", out.Name) + d.Set("description", out.Description) + d.Set("kms_key_id", out.KmsKeyId) + d.Set("status", out.Status) + d.Set("availability_zones", out.AvailabilityZoneIds) + d.Set("infrastructure_account_id", out.DedicatedServiceAccountId) + d.Set("created_timestamp", out.CreationTimestamp.String()) + d.Set("last_modified_timestamp", out.UpdateTimestamp.String()) + + if err := d.Set("transit_gateway_configuration", flattenTransitGatewayConfiguration(out.TransitGatewayConfiguration)); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err)...) + } + + if err := d.Set("custom_dns_configuration", flattenCustomDNSConfigurations(out.CustomDNSConfiguration)); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err)...) + } + + return diags +} + +func resourceKxEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).FinSpaceClient() + + update := false + + in := &finspace.UpdateKxEnvironmentInput{ + EnvironmentId: aws.String(d.Id()), + Name: aws.String(d.Get("name").(string)), + } + + if d.HasChanges("description") { + in.Description = aws.String(d.Get("description").(string)) + } + + if d.HasChanges("name") || d.HasChanges("description") { + update = true + log.Printf("[DEBUG] Updating FinSpace KxEnvironment (%s): %#v", d.Id(), in) + _, err := conn.UpdateKxEnvironment(ctx, in) + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err)...) + } + } + + if d.HasChanges("transit_gateway_configuration") || d.HasChanges("custom_dns_configuration") { + update = true + if err := updateKxEnvironmentNetwork(ctx, d, conn); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err)...) + } + } + + if !update { + return diags + } + return append(diags, resourceKxEnvironmentRead(ctx, d, meta)...) +} + +func resourceKxEnvironmentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).FinSpaceClient() + + log.Printf("[INFO] Deleting FinSpace KxEnvironment %s", d.Id()) + + _, err := conn.DeleteKxEnvironment(ctx, &finspace.DeleteKxEnvironmentInput{ + EnvironmentId: aws.String(d.Id()), + }) + if errs.IsA[*types.ResourceNotFoundException](err) || + errs.IsAErrorMessageContains[*types.ValidationException](err, "The Environment is in DELETED state") { + log.Printf("[DEBUG] FinSpace KxEnvironment %s already deleted. Nothing to delete.", d.Id()) + return diags + } + + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxEnvironment, d.Id(), err)...) + } + + if _, err := waitKxEnvironmentDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxEnvironment, d.Id(), err)...) + } + + return diags +} + +// As of 2023-02-09, updating network configuration requires 2 separate requests if both DNS +// and transit gateway configurationtions are set. +func updateKxEnvironmentNetwork(ctx context.Context, d *schema.ResourceData, client *finspace.Client) error { + transitGatewayConfigIn := &finspace.UpdateKxEnvironmentNetworkInput{ + EnvironmentId: aws.String(d.Id()), + ClientToken: aws.String(id.UniqueId()), + } + + customDnsConfigIn := &finspace.UpdateKxEnvironmentNetworkInput{ + EnvironmentId: aws.String(d.Id()), + ClientToken: aws.String(id.UniqueId()), + } + + updateTransitGatewayConfig := false + updateCustomDnsConfig := false + + if v, ok := d.GetOk("transit_gateway_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil && + d.HasChanges("transit_gateway_configuration") { + transitGatewayConfigIn.TransitGatewayConfiguration = expandTransitGatewayConfiguration(v.([]interface{})) + updateTransitGatewayConfig = true + } + + if v, ok := d.GetOk("custom_dns_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil && + d.HasChanges("custom_dns_configuration") { + customDnsConfigIn.CustomDNSConfiguration = expandCustomDNSConfigurations(v.([]interface{})) + updateCustomDnsConfig = true + } + + if updateTransitGatewayConfig { + if _, err := client.UpdateKxEnvironmentNetwork(ctx, transitGatewayConfigIn); err != nil { + return err + } + + if _, err := waitTransitGatewayConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { + return err + } + } + + if updateCustomDnsConfig { + if _, err := client.UpdateKxEnvironmentNetwork(ctx, customDnsConfigIn); err != nil { + return err + } + + if _, err := waitCustomDNSConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { + return err + } + } + + return nil +} + +func waitKxEnvironmentCreated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(types.EnvironmentStatusCreateRequested, types.EnvironmentStatusCreating), + Target: enum.Slice(types.EnvironmentStatusCreated), + Refresh: statusKxEnvironment(ctx, conn, id), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*finspace.GetKxEnvironmentOutput); ok { + return out, err + } + + return nil, err +} + +func waitTransitGatewayConfigurationUpdated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(types.TgwStatusUpdateRequested, types.TgwStatusUpdating), + Target: enum.Slice(types.TgwStatusSuccessfullyUpdated), + Refresh: statusTransitGatewayConfiguration(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*finspace.GetKxEnvironmentOutput); ok { + return out, err + } + + return nil, err +} + +func waitCustomDNSConfigurationUpdated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(types.DnsStatusUpdateRequested, types.DnsStatusUpdating), + Target: enum.Slice(types.DnsStatusSuccessfullyUpdated), + Refresh: statusCustomDNSConfiguration(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*finspace.GetKxEnvironmentOutput); ok { + return out, err + } + + return nil, err +} + +func waitKxEnvironmentDeleted(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(types.EnvironmentStatusDeleteRequested, types.EnvironmentStatusDeleting), + Target: []string{}, + Refresh: statusKxEnvironment(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*finspace.GetKxEnvironmentOutput); ok { + return out, err + } + + return nil, err +} + +func statusKxEnvironment(ctx context.Context, conn *finspace.Client, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findKxEnvironmentByID(ctx, conn, id) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, string(out.Status), nil + } +} + +func statusTransitGatewayConfiguration(ctx context.Context, conn *finspace.Client, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findKxEnvironmentByID(ctx, conn, id) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, string(out.TgwStatus), nil + } +} + +func statusCustomDNSConfiguration(ctx context.Context, conn *finspace.Client, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findKxEnvironmentByID(ctx, conn, id) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, string(out.DnsStatus), nil + } +} + +func findKxEnvironmentByID(ctx context.Context, conn *finspace.Client, id string) (*finspace.GetKxEnvironmentOutput, error) { + in := &finspace.GetKxEnvironmentInput{ + EnvironmentId: aws.String(id), + } + out, err := conn.GetKxEnvironment(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 + } + // Treat DELETED status as NotFound + if out != nil && out.Status == types.EnvironmentStatusDeleted { + return nil, &retry.NotFoundError{ + LastError: errors.New("status is deleted"), + LastRequest: in, + } + } + + if out == nil || out.EnvironmentArn == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func expandTransitGatewayConfiguration(tfList []interface{}) *types.TransitGatewayConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + + a := &types.TransitGatewayConfiguration{} + + if v, ok := tfMap["transit_gateway_id"].(string); ok && v != "" { + a.TransitGatewayID = aws.String(v) + } + + if v, ok := tfMap["routable_cidr_space"].(string); ok && v != "" { + a.RoutableCIDRSpace = aws.String(v) + } + + return a +} + +func expandCustomDNSConfiguration(tfMap map[string]interface{}) *types.CustomDNSServer { + if tfMap == nil { + return nil + } + + a := &types.CustomDNSServer{} + + if v, ok := tfMap["custom_dns_server_name"].(string); ok && v != "" { + a.CustomDNSServerName = aws.String(v) + } + + if v, ok := tfMap["custom_dns_server_ip"].(string); ok && v != "" { + a.CustomDNSServerIP = aws.String(v) + } + + return a +} + +func expandCustomDNSConfigurations(tfList []interface{}) []types.CustomDNSServer { + if len(tfList) == 0 { + return nil + } + + var s []types.CustomDNSServer + + for _, r := range tfList { + m, ok := r.(map[string]interface{}) + + if !ok { + continue + } + + a := expandCustomDNSConfiguration(m) + + if a == nil { + continue + } + + s = append(s, *a) + } + + return s +} + +func flattenTransitGatewayConfiguration(apiObject *types.TransitGatewayConfiguration) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.TransitGatewayID; v != nil { + m["transit_gateway_id"] = aws.ToString(v) + } + + if v := apiObject.RoutableCIDRSpace; v != nil { + m["routable_cidr_space"] = aws.ToString(v) + } + + return []interface{}{m} +} + +func flattenCustomDNSConfiguration(apiObject *types.CustomDNSServer) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.CustomDNSServerName; v != nil { + m["custom_dns_server_name"] = aws.ToString(v) + } + + if v := apiObject.CustomDNSServerIP; v != nil { + m["custom_dns_server_ip"] = aws.ToString(v) + } + + return m +} + +func flattenCustomDNSConfigurations(apiObjects []types.CustomDNSServer) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var l []interface{} + + for _, apiObject := range apiObjects { + l = append(l, flattenCustomDNSConfiguration(&apiObject)) + } + + return l +} diff --git a/internal/service/finspace/kx_environment_test.go b/internal/service/finspace/kx_environment_test.go new file mode 100644 index 000000000000..088f1f565e1e --- /dev/null +++ b/internal/service/finspace/kx_environment_test.go @@ -0,0 +1,441 @@ +package finspace_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "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" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tffinspace "github.com/hashicorp/terraform-provider-aws/internal/service/finspace" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccFinSpaceKxEnvironment_basic(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + kmsKeyResourceName := "aws_kms_key.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", kmsKeyResourceName, "arn"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccFinSpaceKxEnvironment_disappears(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tffinspace.ResourceKxEnvironment(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccFinSpaceKxEnvironment_updateName(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + Config: testAccKxEnvironmentConfig_basic(rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxEnvironment_description(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_description(rName, "description 1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "description", "description 1"), + ), + }, + { + Config: testAccKxEnvironmentConfig_description(rName, "description 2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "description", "description 2"), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxEnvironment_customDNS(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_dnsConfig(rName, "example.finspace.amazon.aws.com", "10.0.0.76"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "custom_dns_configuration.*", map[string]string{ + "custom_dns_server_name": "example.finspace.amazon.aws.com", + "custom_dns_server_ip": "10.0.0.76", + }), + ), + }, + { + Config: testAccKxEnvironmentConfig_dnsConfig(rName, "updated.finspace.amazon.com", "10.0.0.24"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "custom_dns_configuration.*", map[string]string{ + "custom_dns_server_name": "updated.finspace.amazon.com", + "custom_dns_server_ip": "10.0.0.24", + }), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxEnvironment_transitGateway(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_tgwConfig(rName, "100.64.0.0/26"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "transit_gateway_configuration.*", map[string]string{ + "routable_cidr_space": "100.64.0.0/26", + }), + ), + }, + }, + }) +} + +func TestAccFinSpaceKxEnvironment_tags(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + ctx := acctest.Context(t) + var kxenvironment finspace.GetKxEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_finspace_kx_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, finspace.ServiceID) + }, + ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + Config: testAccKxEnvironmentConfig_tags2(rName, "key1", "value1", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccKxEnvironmentConfig_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func testAccCheckKxEnvironmentDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() + ctx := context.Background() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_finspace_kx_environment" { + continue + } + + input := &finspace.GetKxEnvironmentInput{ + EnvironmentId: aws.String(rs.Primary.ID), + } + out, err := conn.GetKxEnvironment(ctx, input) + if err != nil { + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + return nil + } + return err + } + if out.Status == types.EnvironmentStatusDeleted { + return nil + } + return create.Error(names.FinSpace, create.ErrActionCheckingDestroyed, tffinspace.ResNameKxEnvironment, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckKxEnvironmentExists(ctx context.Context, name string, kxenvironment *finspace.GetKxEnvironmentOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.FinSpace, create.ErrActionCheckingExistence, tffinspace.ResNameKxEnvironment, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.FinSpace, create.ErrActionCheckingExistence, tffinspace.ResNameKxEnvironment, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() + resp, err := conn.GetKxEnvironment(ctx, &finspace.GetKxEnvironmentInput{ + EnvironmentId: aws.String(rs.Primary.ID), + }) + + if err != nil { + return create.Error(names.FinSpace, create.ErrActionCheckingExistence, tffinspace.ResNameKxEnvironment, rs.Primary.ID, err) + } + + *kxenvironment = *resp + + return nil + } +} + +func testAccKxEnvironmentConfigBase() string { + return ` +resource "aws_kms_key" "test" { + deletion_window_in_days = 7 +} +` +} + +func testAccKxEnvironmentConfig_basic(rName string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` +resource "aws_finspace_kx_environment" "test" { + name = %[1]q + kms_key_id = aws_kms_key.test.arn +} +`, rName)) +} + +func testAccKxEnvironmentConfig_description(rName, desc string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` +resource "aws_finspace_kx_environment" "test" { + name = %[1]q + kms_key_id = aws_kms_key.test.arn + description = %[2]q +} +`, rName, desc)) +} + +func testAccKxEnvironmentConfig_tgwConfig(rName, cidr string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` +resource "aws_ec2_transit_gateway" "test" { + description = "test" +} + +resource "aws_finspace_kx_environment" "test" { + name = %[1]q + kms_key_id = aws_kms_key.test.arn + + transit_gateway_configuration { + transit_gateway_id = aws_ec2_transit_gateway.test.id + routable_cidr_space = %[2]q + } +} +`, rName, cidr)) +} + +func testAccKxEnvironmentConfig_dnsConfig(rName, serverName, serverIP string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` +resource "aws_finspace_kx_environment" "test" { + name = %[1]q + kms_key_id = aws_kms_key.test.arn + + custom_dns_configuration { + custom_dns_server_name = %[2]q + custom_dns_server_ip = %[3]q + } +} +`, rName, serverName, serverIP)) +} + +func testAccKxEnvironmentConfig_tags1(rName, tagKey1, tagValue1 string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` +resource "aws_finspace_kx_environment" "test" { + name = %[1]q + kms_key_id = aws_kms_key.test.arn + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1)) +} + +func testAccKxEnvironmentConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` +resource "aws_finspace_kx_environment" "test" { + name = %[1]q + kms_key_id = aws_kms_key.test.arn + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) +} diff --git a/internal/service/finspace/service_package_gen.go b/internal/service/finspace/service_package_gen.go index dc6d1698e86b..97536f838f54 100644 --- a/internal/service/finspace/service_package_gen.go +++ b/internal/service/finspace/service_package_gen.go @@ -32,6 +32,13 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka IdentifierAttribute: "arn", }, }, + { + Factory: ResourceKxEnvironment, + TypeName: "aws_finspace_kx_environment", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: "arn", + }, + }, } } diff --git a/internal/service/finspace/tags_gen.go b/internal/service/finspace/tags_gen.go index de42795bd345..b69b7447c2c8 100644 --- a/internal/service/finspace/tags_gen.go +++ b/internal/service/finspace/tags_gen.go @@ -3,12 +3,14 @@ package finspace import ( "context" + "fmt" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/finspace" "github.com/hashicorp/terraform-provider-aws/internal/conns" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/types" + "github.com/hashicorp/terraform-provider-aws/names" ) // ListTags lists finspace service tags. @@ -74,3 +76,58 @@ func SetTagsOut(ctx context.Context, tags map[string]string) { inContext.TagsOut = types.Some(KeyValueTags(ctx, tags)) } } + +// createTags creates finspace service tags for new resources. +func createTags(ctx context.Context, conn *finspace.Client, identifier string, tags map[string]string) error { + if len(tags) == 0 { + return nil + } + + return UpdateTags(ctx, conn, identifier, nil, tags) +} + +// UpdateTags updates finspace service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func UpdateTags(ctx context.Context, conn *finspace.Client, identifier string, oldTagsMap, newTagsMap any) error { + oldTags := tftags.New(ctx, oldTagsMap) + newTags := tftags.New(ctx, newTagsMap) + + removedTags := oldTags.Removed(newTags) + removedTags = removedTags.IgnoreSystem(names.FinSpace) + if len(removedTags) > 0 { + input := &finspace.UntagResourceInput{ + ResourceArn: aws.String(identifier), + TagKeys: removedTags.Keys(), + } + + _, err := conn.UntagResource(ctx, input) + + if err != nil { + return fmt.Errorf("untagging resource (%s): %w", identifier, err) + } + } + + updatedTags := oldTags.Updated(newTags) + updatedTags = updatedTags.IgnoreSystem(names.FinSpace) + if len(updatedTags) > 0 { + input := &finspace.TagResourceInput{ + ResourceArn: aws.String(identifier), + Tags: Tags(updatedTags), + } + + _, err := conn.TagResource(ctx, input) + + if err != nil { + return fmt.Errorf("tagging resource (%s): %w", identifier, err) + } + } + + return nil +} + +// UpdateTags updates finspace service tags. +// It is called from outside this package. +func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { + return UpdateTags(ctx, meta.(*conns.AWSClient).FinSpaceClient(), identifier, oldTags, newTags) +} diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown new file mode 100644 index 000000000000..e6d5b1532cad --- /dev/null +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -0,0 +1,113 @@ +--- +subcategory: "FinSpace" +layout: "aws" +page_title: "AWS: aws_finspace_kx_environment" +description: |- + Terraform resource for managing an AWS FinSpace Kx Environment. +--- + +# Resource: aws_finspace_kx_environment + +Terraform resource for managing an AWS FinSpace Kx Environment. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_kms_key" "example" { + description = "Sample KMS Key" + deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "example" { + name = "my-tf-kx-environment" + kms_key_id = aws_kms_key.example.arn +} +``` + +### With Network Setup + +```terraform +resource "aws_kms_key" "example" { + description = "Sample KMS Key" + deletion_window_in_days = 7 +} + +resource "aws_ec2_transit_gateway" "example" { + description = "example" +} + +resource "aws_finspace_kx_environment" "example_env" { + name = "my-tf-kx-environment" + description = "Environment description" + kms_key_id = aws_kms_key.example.arn + + transit_gateway_configuration { + transit_gateway_id = aws_ec2_transit_gateway.example.id + routable_cidr_space = "100.64.0.0/26" + } + + custom_dns_configuration { + custom_dns_server_name = "example.finspace.amazonaws.com" + custom_dns_server_ip = "10.0.0.76" + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required) Name of the KX environment that you want to create. +* `kms_key_id` - (Required) KMS key ID to encrypt your data in the FinSpace environment. + +The following arguments are optional: + +* `custom_dns_configuration` - (Optional) List of DNS server name and server IP. This is used to set up Route-53 outbound resolvers. Defined below. +* `description` - (Optional) Description for the KX environment. +* `tags` - (Optional) Key-value mapping of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. +* `transit_gateway_configuration` - (Optional) Transit gateway and network configuration that is used to connect the KX environment to an internal network. Defined below. + +### custom_dns_configuration + +The custom_dns_configuration block supports the following arguments: + +* `custom_dns_server_ip` - (Required) IP address of the DNS server. +* `custom_dns_server_name` - (Required) Name of the DNS server. + +### transit_gateway_configuration + +The transit_gateway_configuration block supports the following arguments: + +* `routable_cidr_space` - (Required) Routing CIDR on behalf of KX environment. It could be any “/26 range in the 100.64.0.0 CIDR space. After providing, it will be added to the customer’s transit gateway routing table so that the traffics could be routed to KX network. +* `transit_gateway_id` - (Required) Identifier of the transit gateway created by the customer to connect outbound traffics from KX network to your internal network. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `arn` - Amazon Resource Name (ARN) identifier of the KX environment. +* `availability_zones` - AWS Availability Zone IDs that this environment is available in. Important when selecting VPC subnets to use in cluster creation. +* `created_timestamp` - Timestamp at which the environment is created in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. +* `id` - Unique identifier for the KX environment. +* `infrastructure_account_id` - Unique identifier for the AWS environment infrastructure account. +* `last_modified_timestamp` - Last timestamp at which the environment was updated in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. +* `status` - Status of environment creation +* `tags_all` - Map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) + +## Import + +An AWS FinSpace Kx Environment can be imported using the `id`, e.g., + +``` +$ terraform import aws_finspace_kx_environment.example n3ceo7wqxoxcti5tujqwzs +``` From e118041de58845ff5d04bd56ffd87e8059113cac Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Thu, 8 Jun 2023 12:30:50 -0400 Subject: [PATCH 08/26] Ran generate.go --- internal/service/finspace/service_package_gen.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/service/finspace/service_package_gen.go b/internal/service/finspace/service_package_gen.go index 8d807f4fd5b0..77a53b693729 100644 --- a/internal/service/finspace/service_package_gen.go +++ b/internal/service/finspace/service_package_gen.go @@ -25,6 +25,13 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ + { + Factory: ResourceKxCluster, + TypeName: "aws_finspace_kx_cluster", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: "arn", + }, + }, { Factory: ResourceKxEnvironment, TypeName: "aws_finspace_kx_environment", From 2ebbd1412598638584bbed2a07e7c06d98f16699 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 11:34:39 -0400 Subject: [PATCH 09/26] chore: changelog --- .changelog/31806.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/31806.txt diff --git a/.changelog/31806.txt b/.changelog/31806.txt new file mode 100644 index 000000000000..c467564e0d00 --- /dev/null +++ b/.changelog/31806.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_finspace_kx_cluster +``` From 7d4447f4d5bec8fda3899bd33edb5308f30ea865 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 13:43:38 -0400 Subject: [PATCH 10/26] r/aws_finspace_kx_cluster: alphabetize attributes --- internal/service/finspace/kx_cluster.go | 357 ++++++++++++------------ 1 file changed, 179 insertions(+), 178 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index df4a0a32d23a..0c58dec034f8 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -38,151 +38,10 @@ func ResourceKxCluster() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "status": { - Type: schema.TypeString, - Computed: true, - }, - "status_reason": { - Type: schema.TypeString, - Computed: true, - }, - "created_timestamp": { - Type: schema.TypeString, - Computed: true, - }, - "last_modified_timestamp": { - Type: schema.TypeString, - Computed: true, - }, "arn": { Type: schema.TypeString, Computed: 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), - }, - "type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateDiagFunc: enum.Validate[types.KxClusterType](), - }, - "release_label": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 16), - }, - "az_mode": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateDiagFunc: enum.Validate[types.KxAzMode](), - }, - "availability_zone_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "description": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 1000), - }, - "initialization_script": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 255), - }, - "execution_role": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 1024), - }, - "command_line_arguments": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - ForceNew: true, - ValidateDiagFunc: verify.ValidAllDiag( - validation.MapKeyLenBetween(1, 50), - validation.MapValueLenBetween(1, 50), - ), - }, - "capacity_configuration": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "node_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 32), - }, - "node_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - ValidateFunc: validation.IntBetween(1, 5), - }, - }, - }, - }, - "vpc_configuration": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vpc_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 1024), - }, - "security_group_ids": { - Type: schema.TypeSet, - Required: true, - ForceNew: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringLenBetween(1, 1024), - }, - }, - "subnet_ids": { - Type: schema.TypeSet, - Required: true, - ForceNew: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringLenBetween(1, 1024), - }, - }, - "ip_address_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice(enum.Slice(types.IPAddressTypeIpV4), true), - }, - }, - }, - }, "auto_scaling_configuration": { Type: schema.TypeList, Optional: true, @@ -197,12 +56,6 @@ func ResourceKxCluster() *schema.Resource { ValidateFunc: validation.StringInSlice( enum.Slice(types.AutoScalingMetricCpuUtilizationPercentage), true), }, - "min_node_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - ValidateFunc: validation.IntBetween(1, 5), - }, "max_node_count": { Type: schema.TypeInt, Required: true, @@ -215,6 +68,12 @@ func ResourceKxCluster() *schema.Resource { ForceNew: true, ValidateFunc: validation.FloatBetween(0, 100), }, + "min_node_count": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 5), + }, "scale_in_cooldown_seconds": { Type: schema.TypeFloat, Required: true, @@ -230,62 +89,108 @@ func ResourceKxCluster() *schema.Resource { }, }, }, - "savedown_storage_configuration": { + "availability_zone_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "az_mode": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.KxAzMode](), + }, + "cache_storage_configurations": { Type: schema.TypeList, Optional: true, ForceNew: true, - MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice( - enum.Slice(types.KxSavedownStorageTypeSds01), true), - }, "size": { Type: schema.TypeInt, Required: true, ForceNew: true, - ValidateFunc: validation.IntBetween(4, 16000), + ValidateFunc: validation.IntBetween(1200, 33600), + }, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(8, 10), }, }, }, }, - "cache_storage_configurations": { + "capacity_configuration": { Type: schema.TypeList, - Optional: true, + Required: true, ForceNew: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "type": { - Type: schema.TypeString, + "node_count": { + Type: schema.TypeInt, Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(8, 10), + ValidateFunc: validation.IntBetween(1, 5), }, - "size": { - Type: schema.TypeInt, + "node_type": { + Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.IntBetween(1200, 33600), + ValidateFunc: validation.StringLenBetween(1, 32), }, }, }, }, - "database": { + "code": { Type: schema.TypeList, Optional: true, ForceNew: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "database_name": { + "s3_bucket": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 255), + }, + "s3_key": { Type: schema.TypeString, Required: true, ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 1024), + }, + "s3_object_version": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, ValidateFunc: validation.StringLenBetween(3, 63), }, + }, + }, + }, + "command_line_arguments": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + ValidateDiagFunc: verify.ValidAllDiag( + validation.MapKeyLenBetween(1, 50), + validation.MapValueLenBetween(1, 50), + ), + }, + "created_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "database": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ "cache_configurations": { Type: schema.TypeList, Required: true, @@ -317,40 +222,136 @@ func ResourceKxCluster() *schema.Resource { ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 26), }, + "database_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 63), + }, }, }, }, - "code": { + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1000), + }, + "environment_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 32), + }, + "execution_role": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + "initialization_script": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + "last_modified_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 63), + }, + "release_label": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 16), + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "savedown_storage_configuration": { Type: schema.TypeList, Optional: true, ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "s3_bucket": { - Type: schema.TypeString, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice( + enum.Slice(types.KxSavedownStorageTypeSds01), true), + }, + "size": { + Type: schema.TypeInt, Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(3, 255), + ValidateFunc: validation.IntBetween(4, 16000), }, - "s3_key": { + }, + }, + }, + "status_reason": { + Type: schema.TypeString, + Computed: true, + }, + names.AttrTags: tftags.TagsSchemaForceNew(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.KxClusterType](), + }, + "vpc_configuration": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address_type": { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(3, 1024), + ValidateFunc: validation.StringInSlice(enum.Slice(types.IPAddressTypeIpV4), true), }, - "s3_object_version": { + "security_group_ids": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + }, + "subnet_ids": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + }, + "vpc_id": { Type: schema.TypeString, - Optional: true, + Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(3, 63), + ValidateFunc: validation.StringLenBetween(1, 1024), }, }, }, }, - "tags": tftags.TagsSchemaForceNew(), - "tags_all": tftags.TagsSchemaComputed(), }, + CustomizeDiff: verify.SetTagsDiff, } } From 6bb4317e16e913aa65145739507599f36e9852bc Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 13:54:30 -0400 Subject: [PATCH 11/26] r/aws_finspace_kx_cluster: crud handlers return diags --- internal/service/finspace/kx_cluster.go | 45 +++++++++++++------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 0c58dec034f8..9f7ae8432308 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -361,6 +361,7 @@ const ( ) func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FinSpaceClient() in := &finspace.CreateKxClusterInput{ @@ -420,23 +421,24 @@ func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta i out, err := conn.CreateKxCluster(ctx, in) if err != nil { - return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), err)...) } if out == nil { - return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), errors.New("empty output")) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), errors.New("empty output"))...) } d.SetId(aws.ToString(out.EnvironmentId) + "," + aws.ToString(out.ClusterName)) if _, err := waitKxClusterCreated(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string), d.Timeout(schema.TimeoutCreate)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxCluster, d.Id(), err)...) } - return resourceKxClusterRead(ctx, d, meta) + return append(diags, resourceKxClusterRead(ctx, d, meta)...) } func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FinSpaceClient() out, err := findKxClusterByID(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string)) @@ -444,11 +446,11 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] FinSpace KxCluster (%s) not found, removing from state", d.Id()) d.SetId("") - return nil + return diags } if err != nil { - return create.DiagError(names.FinSpace, create.ErrActionReading, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionReading, ResNameKxCluster, d.Id(), err)...) } d.Set("status", out.Status) @@ -468,69 +470,68 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int d.Set("arn", *env.EnvironmentArn+"/kxCluster/"+*out.ClusterName) if err := d.Set("capacity_configuration", flattenCapacityConfiguration(out.CapacityConfiguration)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } if err := d.Set("vpc_configuration", flattenVPCConfiguration(out.VpcConfiguration)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } if err := d.Set("code", flattenCode(out.Code)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } if err := d.Set("auto_scaling_configuration", flattenAutoScalingConfiguration(out.AutoScalingConfiguration)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } if err := d.Set("savedown_storage_configuration", flattenSavedownStorageConfiguration( out.SavedownStorageConfiguration)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } if err := d.Set("cache_storage_configurations", flattenCacheStorageConfigurations( out.CacheStorageConfigurations)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } if d.IsNewResource() { if err := d.Set("database", flattenDatabases(out.Databases)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } } if err := d.Set("command_line_arguments", flattenCommandLineArguments(out.CommandLineArguments)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } - return nil + return diags } func resourceKxClusterDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FinSpaceClient() log.Printf("[INFO] Deleting FinSpace KxCluster %s", d.Id()) - _, err := conn.DeleteKxCluster(ctx, &finspace.DeleteKxClusterInput{ ClusterName: 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 nil + return diags } - return create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxCluster, d.Id(), err)...) } _, err = waitKxClusterDeleted(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string), d.Timeout(schema.TimeoutDelete)) - if err != nil && !tfresource.NotFound(err) { - return create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxCluster, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxCluster, d.Id(), err)...) } - return nil + + return diags } func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { From 283da0834cde70ed847cf3a20dd5bb62ecfcce22 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 13:56:26 -0400 Subject: [PATCH 12/26] r/aws_finspace_kx_cluster: allow tag only updates --- internal/service/finspace/kx_cluster.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 9f7ae8432308..ed46d7b16ca5 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -30,10 +30,12 @@ func ResourceKxCluster() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceKxClusterCreate, ReadWithoutTimeout: resourceKxClusterRead, + UpdateWithoutTimeout: resourceKxClusterUpdate, DeleteWithoutTimeout: resourceKxClusterDelete, Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(2 * time.Minute), // Tags only Delete: schema.DefaultTimeout(40 * time.Minute), }, @@ -508,6 +510,12 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int return diags } +func resourceKxClusterUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + // Tags only. + return append(diags, resourceKxClusterRead(ctx, d, meta)...) +} + func resourceKxClusterDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FinSpaceClient() From fc661788da9680facd3b9a586e1aed9461bd5db0 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 14:35:39 -0400 Subject: [PATCH 13/26] r/aws_finspace_kx_cluster: find by id to support import --- internal/service/finspace/kx_cluster.go | 53 +++++++++++++++++-------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index ed46d7b16ca5..a5fecdeecc38 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -3,6 +3,7 @@ package finspace import ( "context" "errors" + "fmt" "log" "time" @@ -360,6 +361,8 @@ func ResourceKxCluster() *schema.Resource { const ( ResNameKxCluster = "Kx Cluster" + + kxClusterIDPartCount = 2 ) func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { @@ -430,9 +433,17 @@ func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta i return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), errors.New("empty output"))...) } - d.SetId(aws.ToString(out.EnvironmentId) + "," + aws.ToString(out.ClusterName)) + idParts := []string{ + aws.ToString(out.EnvironmentId), + aws.ToString(out.ClusterName), + } + id, err := flex.FlattenResourceId(idParts, kxClusterIDPartCount, false) + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionFlatteningResourceId, ResNameKxCluster, d.Get("name").(string), err)...) + } + d.SetId(id) - if _, err := waitKxClusterCreated(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string), d.Timeout(schema.TimeoutCreate)); err != nil { + if _, err := waitKxClusterCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxCluster, d.Id(), err)...) } @@ -443,8 +454,7 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FinSpaceClient() - out, err := findKxClusterByID(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string)) - + out, err := findKxClusterByID(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] FinSpace KxCluster (%s) not found, removing from state", d.Id()) d.SetId("") @@ -468,9 +478,6 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int d.Set("execution_role", out.ExecutionRole) d.Set("initialization_script", out.InitializationScript) - env, err := findKxEnvironmentByID(ctx, conn, d.Get("environment_id").(string)) - d.Set("arn", *env.EnvironmentArn+"/kxCluster/"+*out.ClusterName) - if err := d.Set("capacity_configuration", flattenCapacityConfiguration(out.CapacityConfiguration)); err != nil { return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } @@ -507,6 +514,14 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } + // compose cluster ARN using environment ARN + env, err := findKxEnvironmentByID(ctx, conn, d.Get("environment_id").(string)) + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) + } + arn := fmt.Sprintf("%s/kxCluster/%s", aws.ToString(env.EnvironmentArn), aws.ToString(out.ClusterName)) + d.Set("arn", arn) + return diags } @@ -534,7 +549,7 @@ func resourceKxClusterDelete(ctx context.Context, d *schema.ResourceData, meta i return append(diags, create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxCluster, d.Id(), err)...) } - _, err = waitKxClusterDeleted(ctx, conn, d.Get("name").(string), d.Get("environment_id").(string), d.Timeout(schema.TimeoutDelete)) + _, err = waitKxClusterDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)) if err != nil && !tfresource.NotFound(err) { return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxCluster, d.Id(), err)...) } @@ -542,11 +557,11 @@ func resourceKxClusterDelete(ctx context.Context, d *schema.ResourceData, meta i return diags } -func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { +func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { stateConf := &retry.StateChangeConf{ Pending: enum.Slice(types.KxClusterStatusPending, types.KxClusterStatusCreating), Target: enum.Slice(types.KxClusterStatusRunning), - Refresh: statusKxCluster(ctx, conn, clusterName, environmentId), + Refresh: statusKxCluster(ctx, conn, id), Timeout: timeout, NotFoundChecks: 20, ContinuousTargetOccurence: 2, @@ -560,11 +575,11 @@ func waitKxClusterCreated(ctx context.Context, conn *finspace.Client, clusterNam return nil, err } -func waitKxClusterDeleted(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { +func waitKxClusterDeleted(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxClusterOutput, error) { stateConf := &retry.StateChangeConf{ Pending: enum.Slice(types.KxClusterStatusDeleting), Target: enum.Slice(types.KxClusterStatusDeleted), - Refresh: statusKxCluster(ctx, conn, clusterName, environmentId), + Refresh: statusKxCluster(ctx, conn, id), Timeout: timeout, } @@ -576,9 +591,9 @@ func waitKxClusterDeleted(ctx context.Context, conn *finspace.Client, clusterNam return nil, err } -func statusKxCluster(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string) retry.StateRefreshFunc { +func statusKxCluster(ctx context.Context, conn *finspace.Client, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - out, err := findKxClusterByID(ctx, conn, clusterName, environmentId) + out, err := findKxClusterByID(ctx, conn, id) if tfresource.NotFound(err) { return nil, "", nil } @@ -591,10 +606,14 @@ func statusKxCluster(ctx context.Context, conn *finspace.Client, clusterName str } } -func findKxClusterByID(ctx context.Context, conn *finspace.Client, clusterName string, environmentId string) (*finspace.GetKxClusterOutput, error) { +func findKxClusterByID(ctx context.Context, conn *finspace.Client, id string) (*finspace.GetKxClusterOutput, error) { + parts, err := flex.ExpandResourceId(id, kxUserIDPartCount, false) + if err != nil { + return nil, err + } in := &finspace.GetKxClusterInput{ - ClusterName: aws.String(clusterName), - EnvironmentId: aws.String(environmentId), + EnvironmentId: aws.String(parts[0]), + ClusterName: aws.String(parts[1]), } out, err := conn.GetKxCluster(ctx, in) From 1c9ffbcaf223b998dbb5296d1fc7559442615355 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 14:48:24 -0400 Subject: [PATCH 14/26] r/aws_finspace_kx_cluster: import support --- internal/service/finspace/kx_cluster.go | 4 ++++ internal/service/finspace/kx_cluster_test.go | 5 +++++ website/docs/r/finspace_kx_cluster.html.markdown | 11 +++++++++++ 3 files changed, 20 insertions(+) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index a5fecdeecc38..8f78e878a1a1 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -34,6 +34,10 @@ func ResourceKxCluster() *schema.Resource { UpdateWithoutTimeout: resourceKxClusterUpdate, DeleteWithoutTimeout: resourceKxClusterDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), Update: schema.DefaultTimeout(2 * time.Minute), // Tags only diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index d651c1c2726c..eb982bb84327 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -46,6 +46,11 @@ func TestAccFinSpaceKxCluster_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown index 4877aebbf6f2..5877ee552745 100644 --- a/website/docs/r/finspace_kx_cluster.html.markdown +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -22,6 +22,7 @@ resource "aws_finspace_kx_cluster" "example" { release_label = "1.0" az_mode = "SINGLE" availability_zone_id = "use1-az2" + capacity_configuration { node_type = "kx.s.2xlarge" node_count = 2 @@ -166,6 +167,7 @@ In addition to all arguments above, the following attributes are exported: * `arn` - Amazon Resource Name (ARN) identifier of the KX cluster. * `created_timestamp` - Timestamp at which the cluster is created in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. +* `id` - A comma-delimited string joining environment ID and cluster name. * `last_modified_timestamp` - Last timestamp at which the cluster was updated in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. * `tags_all` - Map of tags assigned to the resource. @@ -174,4 +176,13 @@ In addition to all arguments above, the following attributes are exported: [Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): * `create` - (Default `30m`) +* `update` - (Default `2m`) * `delete` - (Default `40m`) + +## Import + +An AWS FinSpace Kx Cluster can be imported using the `id` (environment ID and cluster name, comma-delimited), e.g., + +``` +$ terraform import aws_finspace_kx_cluster.example n3ceo7wqxoxcti5tujqwzs,my-tf-kx-cluster +``` From 04fea0fccfd9a0ac6b313f74120aa0e5492c795b Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 14:49:38 -0400 Subject: [PATCH 15/26] r/aws_finspace_kx_cluster(docs): use standard tags/tags_all descriptions --- website/docs/r/finspace_kx_cluster.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown index 5877ee552745..abc5933fa70c 100644 --- a/website/docs/r/finspace_kx_cluster.html.markdown +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -84,7 +84,7 @@ The following arguments are optional: * `savedown_storage_configuration` - (Optional) Size and type of the temporary storage that is used to hold data during the savedown process. This parameter is required when you choose `type` as RDB. All the data written to this storage space is lost when the cluster node is restarted. Defined below. * `auto_scaling_configuration` - (Optional) Configuration based on which FinSpace will scale in or scale out nodes in your cluster. Defined below. * `code` - (Optional) Details of the custom code that you want to use inside a cluster when analyzing data. Consists of the S3 source bucket, location, object version, and the relative path from where the custom code is loaded into the cluster. Defined below. -* `tags` - (Optional) List of key-value pairs to label the cluster. +* `tags` - (Optional) Key-value mapping of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ### capacity_configuration @@ -169,7 +169,7 @@ In addition to all arguments above, the following attributes are exported: * `created_timestamp` - Timestamp at which the cluster is created in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. * `id` - A comma-delimited string joining environment ID and cluster name. * `last_modified_timestamp` - Last timestamp at which the cluster was updated in FinSpace. Value determined as epoch time in seconds. For example, the value for Monday, November 1, 2021 12:00:00 PM UTC is specified as 1635768000. -* `tags_all` - Map of tags assigned to the resource. +* `tags_all` - Map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). ## Timeouts From 06656470b9c2de7c9c299e89e8fcad784efe8c65 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 14:58:26 -0400 Subject: [PATCH 16/26] r/aws_finspace_kx_cluster(docs): alphabetize --- .../docs/r/finspace_kx_cluster.html.markdown | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/website/docs/r/finspace_kx_cluster.html.markdown b/website/docs/r/finspace_kx_cluster.html.markdown index abc5933fa70c..2032b73d5c49 100644 --- a/website/docs/r/finspace_kx_cluster.html.markdown +++ b/website/docs/r/finspace_kx_cluster.html.markdown @@ -59,33 +59,44 @@ resource "aws_finspace_kx_cluster" "example" { The following arguments are required: +* `az_mode` - (Required) The number of availability zones you want to assign per cluster. This can be one of the following: + * SINGLE - Assigns one availability zone per cluster. + * MULTI - Assigns all the availability zones per cluster. +* `capacity_configuration` - (Required) Structure for the metadata of a cluster. Includes information like the CPUs needed, memory of instances, number of instances, and the port used while establishing a connection. See [capacity_configuration](#capacity_configuration). * `environment_id` - (Required) Unique identifier for the KX environment. * `name` - (Required) Unique name for the cluster that you want to create. +* `release_label` - (Required) Version of FinSpace Managed kdb to run. * `type` - (Required) Type of KDB database. The following types are available: * HDB - Historical Database. The data is only accessible with read-only permissions from one of the FinSpace managed KX databases mounted to the cluster. * RDB - Realtime Database. This type of database captures all the data from a ticker plant and stores it in memory until the end of day, after which it writes all of its data to a disk and reloads the HDB. This cluster type requires local storage for temporary storage of data during the savedown process. If you specify this field in your request, you must provide the `savedownStorageConfiguration` parameter. * GATEWAY - A gateway cluster allows you to access data across processes in kdb systems. It allows you to create your own routing logic using the initialization scripts and custom code. This type of cluster does not require a writable local storage. -* `release_label` - (Required) Version of FinSpace Managed kdb to run. -* `az_mode` - (Required) The number of availability zones you want to assign per cluster. This can be one of the following: - * SINGLE - Assigns one availability zone per cluster. - * MULTI - Assigns all the availability zones per cluster. -* `capacity_configuration` - (Required) Structure for the metadata of a cluster. Includes information like the CPUs needed, memory of instances, number of instances, and the port used while establishing a connection. Defined below. -* `vpc_configuration` - (Required) Configuration details about the network where the Privatelink endpoint of the cluster resides. Defined below. +* `vpc_configuration` - (Required) Configuration details about the network where the Privatelink endpoint of the cluster resides. See [vpc_configuration](#vpc_configuration). The following arguments are optional: -* `description` - (Optional) Description of the cluster. +* `auto_scaling_configuration` - (Optional) Configuration based on which FinSpace will scale in or scale out nodes in your cluster. See [auto_scaling_configuration](#auto_scaling_configuration). * `availability_zone_id` - (Optional) The availability zone identifiers for the requested regions. Required when `az_mode` is set to SINGLE. -* `initialization_script` - (Optional) Path to Q program that will be run at launch of a cluster. This is a relative path within .zip file that contains the custom code, which will be loaded on the cluster. It must include the file name itself. For example, somedir/init.q. -* `execution_role` - (Optional) An IAM role that defines a set of permissions associated with a cluster. These permissions are assumed when a cluster attempts to access another cluster. +* `cache_storage_configurations` - (Optional) Configurations for a read only cache storage associated with a cluster. This cache will be stored as an FSx Lustre that reads from the S3 store. See [cache_storage_configuration](#cache_storage_configuration). +* `code` - (Optional) Details of the custom code that you want to use inside a cluster when analyzing data. Consists of the S3 source bucket, location, object version, and the relative path from where the custom code is loaded into the cluster. See [code](#code). * `command_line_arguments` - (Optional) List of key-value pairs to make available inside the cluster. * `database` - (Optional) KX database that will be available for querying. Defined below. -* `cache_storage_configurations` - (Optional) Configurations for a read only cache storage associated with a cluster. This cache will be stored as an FSx Lustre that reads from the S3 store. Defined below. -* `savedown_storage_configuration` - (Optional) Size and type of the temporary storage that is used to hold data during the savedown process. This parameter is required when you choose `type` as RDB. All the data written to this storage space is lost when the cluster node is restarted. Defined below. -* `auto_scaling_configuration` - (Optional) Configuration based on which FinSpace will scale in or scale out nodes in your cluster. Defined below. -* `code` - (Optional) Details of the custom code that you want to use inside a cluster when analyzing data. Consists of the S3 source bucket, location, object version, and the relative path from where the custom code is loaded into the cluster. Defined below. +* `description` - (Optional) Description of the cluster. +* `execution_role` - (Optional) An IAM role that defines a set of permissions associated with a cluster. These permissions are assumed when a cluster attempts to access another cluster. +* `initialization_script` - (Optional) Path to Q program that will be run at launch of a cluster. This is a relative path within .zip file that contains the custom code, which will be loaded on the cluster. It must include the file name itself. For example, somedir/init.q. +* `savedown_storage_configuration` - (Optional) Size and type of the temporary storage that is used to hold data during the savedown process. This parameter is required when you choose `type` as RDB. All the data written to this storage space is lost when the cluster node is restarted. See [savedown_storage_configuration](#savedown_storage_configuration). * `tags` - (Optional) Key-value mapping of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. +### auto_scaling_configuration + +The auto_scaling_configuration block supports the following arguments: + +* `auto_scaling_metric` - (Required) Metric your cluster will track in order to scale in and out. For example, CPU_UTILIZATION_PERCENTAGE is the average CPU usage across all nodes in a cluster. +* `min_node_count` - (Required) Lowest number of nodes to scale. Must be at least 1 and less than the `max_node_count`. If nodes in cluster belong to multiple availability zones, then `min_node_count` must be at least 3. +* `max_node_count` - (Required) Highest number of nodes to scale. Cannot be greater than 5 +* `metric_target` - (Required) Desired value of chosen `auto_scaling_metric`. When metric drops below this value, cluster will scale in. When metric goes above this value, cluster will scale out. Can be set between 0 and 100 percent. +* `scale_in_cooldown_seconds` - (Required) Duration in seconds that FinSpace will wait after a scale in event before initiating another scaling event. +* `scale_out_cooldown_seconds` - (Required) Duration in seconds that FinSpace will wait after a scale out event before initiating another scaling event. + ### capacity_configuration The capacity_configuration block supports the following arguments: @@ -102,14 +113,13 @@ The capacity_configuration block supports the following arguments: * kx.s.32xlarge – The node type with a configuration of 864 GiB memory and 128 vCPUs. * `node_count` - (Required) Number of instances running in a cluster. Must be at least 1 and at most 5. -### vpc_configuration +### cache_storage_configuration -The vpc_configuration block supports the following arguments: +The cache_storage_configuration block supports the following arguments: -* `vpc_id` - (Required) Identifier of the VPC endpoint -* `security_group_ids` - (Required) Unique identifier of the VPC security group applied to the VPC endpoint ENI for the cluster. -* `subnet_ids `- (Required) Identifier of the subnet that the Privatelink VPC endpoint uses to connect to the cluster. -* `ip_address_type` - (Required) IP address type for cluster network configuration parameters. The following type is available: IP_V4 - IP address version 4. +* `type` - (Required) Type of cache storage . The valid values are: + * CACHE_1000 - This type provides at least 1000 MB/s disk access throughput. +* `size` - (Required) Size of cache in Gigabytes. ### code @@ -124,24 +134,16 @@ The code block supports the following arguments: The database block supports the following arguments: * `database_name` - (Required) Name of the KX database. -* `cache_configurations` - (Required) Configuration details for the disk cache to increase performance reading from a KX database mounted to the cluster. Detailed below. +* `cache_configurations` - (Required) Configuration details for the disk cache to increase performance reading from a KX database mounted to the cluster. See [cache_configurations](#cache_configurations). * `changeset_id` - (Optional) A unique identifier of the changeset that is associated with the cluster. -#### cache_configuration +#### cache_configurations The cache_configuration block supports the following arguments: * `cache_type` - (Required) Type of disk cache. * `db_paths` - (Required) Paths within the database to cache. -### cache_storage_configurations - -The cache_storage_configurations block supports the following arguments: - -* `type` - (Required) Type of cache storage . The valid values are: - * CACHE_1000 - This type provides at least 1000 MB/s disk access throughput. -* `size` - (Required) Size of cache in Gigabytes. - ### savedown_storage_configuration The savedown_storage_configuration block supports the following arguments: @@ -150,16 +152,14 @@ The savedown_storage_configuration block supports the following arguments: * SDS01 - This type represents 3000 IOPS and io2 ebs volume type. * `size` - (Required) Size of temporary storage in bytes. -### auto_scaling_configuration +### vpc_configuration -The auto_scaling_configuration block supports the following arguments: +The vpc_configuration block supports the following arguments: -* `auto_scaling_metric` - (Required) Metric your cluster will track in order to scale in and out. For example, CPU_UTILIZATION_PERCENTAGE is the average CPU usage across all nodes in a cluster. -* `min_node_count` - (Required) Lowest number of nodes to scale. Must be at least 1 and less than the `max_node_count`. If nodes in cluster belong to multiple availability zones, then `min_node_count` must be at least 3. -* `max_node_count` - (Required) Highest number of nodes to scale. Cannot be greater than 5 -* `metric_target` - (Required) Desired value of chosen `auto_scaling_metric`. When metric drops below this value, cluster will scale in. When metric goes above this value, cluster will scale out. Can be set between 0 and 100 percent. -* `scale_in_cooldown_seconds` - (Required) Duration in seconds that FinSpace will wait after a scale in event before initiating another scaling event. -* `scale_out_cooldown_seconds` - (Required) Duration in seconds that FinSpace will wait after a scale out event before initiating another scaling event. +* `vpc_id` - (Required) Identifier of the VPC endpoint +* `security_group_ids` - (Required) Unique identifier of the VPC security group applied to the VPC endpoint ENI for the cluster. +* `subnet_ids `- (Required) Identifier of the subnet that the Privatelink VPC endpoint uses to connect to the cluster. +* `ip_address_type` - (Required) IP address type for cluster network configuration parameters. The following type is available: IP_V4 - IP address version 4. ## Attributes Reference From 7c3cc445b01eb16b312d32456c98ab22102fcda8 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 15:04:13 -0400 Subject: [PATCH 17/26] r/aws_finspace_kx_cluster(test): add ctx to check funcs --- internal/service/finspace/kx_cluster_test.go | 92 ++++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index eb982bb84327..2e4e7271cde9 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -36,12 +36,12 @@ func TestAccFinSpaceKxCluster_basic(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), @@ -72,12 +72,12 @@ func TestAccFinSpaceKxCluster_disappears(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), acctest.CheckResourceDisappears(ctx, acctest.Provider, tffinspace.ResourceKxCluster(), resourceName), ), ExpectNonEmptyPlan: true, @@ -103,12 +103,12 @@ func TestAccFinSpaceKxCluster_description(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_description(rName, "cluster description"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "description", "cluster description"), ), }, @@ -133,12 +133,12 @@ func TestAccFinSpaceKxCluster_database(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_database(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), }, @@ -164,12 +164,12 @@ func TestAccFinSpaceKxCluster_code(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_code(rName, codePath), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), ), }, }, @@ -193,12 +193,12 @@ func TestAccFinSpaceKxCluster_multiAZ(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_multiAZ(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), }, @@ -223,12 +223,12 @@ func TestAccFinSpaceKxCluster_rdb(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_rdb(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), }, @@ -253,12 +253,12 @@ func TestAccFinSpaceKxCluster_executionRole(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_executionRole(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), }, @@ -283,12 +283,12 @@ func TestAccFinSpaceKxCluster_autoScaling(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_autoScaling(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "status", string(types.KxClusterStatusRunning)), ), }, @@ -316,12 +316,12 @@ func TestAccFinSpaceKxCluster_initializationScript(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_initScript(rName, codePath, initScriptPath), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), ), }, }, @@ -345,12 +345,12 @@ func TestAccFinSpaceKxCluster_commandLineArgs(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_commandLineArgs1(rName, "arg1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "command_line_arguments.%", "1"), resource.TestCheckResourceAttr(resourceName, "command_line_arguments.arg1", "value1"), ), @@ -376,12 +376,12 @@ func TestAccFinSpaceKxCluster_tags(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxClusterDestroy, + CheckDestroy: testAccCheckKxClusterDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxClusterConfig_tags1(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxClusterExists(resourceName, &kxcluster), + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), @@ -390,35 +390,36 @@ func TestAccFinSpaceKxCluster_tags(t *testing.T) { }) } -func testAccCheckKxClusterDestroy(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() - ctx := context.Background() +func testAccCheckKxClusterDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() - for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_finspace_kx_cluster" { - continue - } + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_finspace_kx_cluster" { + continue + } - input := &finspace.GetKxClusterInput{ - ClusterName: aws.String(rs.Primary.Attributes["name"]), - EnvironmentId: aws.String(rs.Primary.Attributes["environment_id"]), - } - _, err := conn.GetKxCluster(ctx, input) - if err != nil { - var nfe *types.ResourceNotFoundException - if errors.As(err, &nfe) { - return nil + input := &finspace.GetKxClusterInput{ + ClusterName: aws.String(rs.Primary.Attributes["name"]), + EnvironmentId: aws.String(rs.Primary.Attributes["environment_id"]), + } + _, err := conn.GetKxCluster(ctx, input) + if err != nil { + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + return nil + } + return err } - return err + + return create.Error(names.FinSpace, create.ErrActionCheckingDestroyed, tffinspace.ResNameKxCluster, rs.Primary.ID, errors.New("not destroyed")) } - return create.Error(names.FinSpace, create.ErrActionCheckingDestroyed, tffinspace.ResNameKxCluster, rs.Primary.ID, errors.New("not destroyed")) + return nil } - - return nil } -func testAccCheckKxClusterExists(name string, kxcluster *finspace.GetKxClusterOutput) resource.TestCheckFunc { +func testAccCheckKxClusterExists(ctx context.Context, name string, kxcluster *finspace.GetKxClusterOutput) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] if !ok { @@ -430,7 +431,6 @@ func testAccCheckKxClusterExists(name string, kxcluster *finspace.GetKxClusterOu } conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() - ctx := context.Background() resp, err := conn.GetKxCluster(ctx, &finspace.GetKxClusterInput{ ClusterName: aws.String(rs.Primary.Attributes["name"]), EnvironmentId: aws.String(rs.Primary.Attributes["environment_id"]), From ebffb85c0db3905d5476484b99b29d208f37caaf Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 15:32:35 -0400 Subject: [PATCH 18/26] r/aws_finspace_kx_cluster(test): add base config --- internal/service/finspace/kx_cluster_test.go | 1471 +++--------------- 1 file changed, 198 insertions(+), 1273 deletions(-) diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index 2e4e7271cde9..d0c1f96cf441 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -446,7 +446,7 @@ func testAccCheckKxClusterExists(ctx context.Context, name string, kxcluster *fi } } -func testAccKxClusterConfig_basic(rName string) string { +func testAccKxClusterConfigBase(rName string) string { return fmt.Sprintf(` data "aws_caller_identity" "current" {} @@ -455,7 +455,6 @@ output "account_id" { } resource "aws_kms_key" "test" { - description = %[1]q deletion_window_in_days = 7 } @@ -557,7 +556,13 @@ resource "aws_route" "r" { destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.test.id } +`, rName) +} +func testAccKxClusterConfig_basic(rName string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` resource "aws_finspace_kx_cluster" "test" { name = %[1]q environment_id = aws_finspace_kx_environment.test.id @@ -577,129 +582,126 @@ resource "aws_finspace_kx_cluster" "test" { ip_address_type = "IP_V4" } } -`, rName) +`, rName)) } func testAccKxClusterConfig_description(rName, description string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + description = %[2]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + type = "HDB" + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn +`, rName, description)) } -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } +func testAccKxClusterConfig_commandLineArgs1(rName, arg1, val1 string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + type = "HDB" + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" } - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } -} -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json + command_line_arguments = { + %[2]q = %[3]q + } } - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true +`, rName, arg1, val1)) } -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" +func testAccKxClusterConfig_tags1(rName, tagKey1, tagValue1 string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" } - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } -} -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id + tags = { + %[2]q = %[3]q + } } - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id +`, rName, tagKey1, tagValue1)) } -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id +func testAccKxClusterConfig_database(rName string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_finspace_kx_database" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id } resource "aws_finspace_kx_cluster" "test" { name = %[1]q - description = %[2]q environment_id = aws_finspace_kx_environment.test.id - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] type = "HDB" release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + + cache_storage_configurations { + type = "CACHE_1000" + size = 1200 + } + + database { + database_name = aws_finspace_kx_database.test.name + cache_configurations { + cache_type = "CACHE_1000" + db_paths = ["/"] + } + } + capacity_configuration { node_count = 2 node_type = "kx.s.xlarge" @@ -712,36 +714,26 @@ resource "aws_finspace_kx_cluster" "test" { ip_address_type = "IP_V4" } } -`, rName, description) -} - -func testAccKxClusterConfig_commandLineArgs1(rName, arg1, val1 string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 +`, rName)) } -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn +func testAccKxClusterConfig_code(rName, path string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q } -data "aws_iam_policy_document" "key_policy" { +data "aws_iam_policy_document" "bucket_policy" { statement { actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" + "s3:GetObject", + "s3:GetObjectTagging" ] resources = [ - aws_kms_key.test.arn, + "arn:aws:s3:::${aws_s3_bucket.test.id}/*", ] principals { @@ -764,719 +756,84 @@ data "aws_iam_policy_document" "key_policy" { statement { actions = [ - "kms:*", + "s3:ListBucket" ] resources = [ - "*", + "arn:aws:s3:::${aws_s3_bucket.test.id}", ] principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + type = "Service" + identifiers = ["finspace.amazonaws.com"] + } + + condition { + test = "ArnLike" + variable = "aws:SourceArn" + values = ["${aws_finspace_kx_environment.test.arn}/*"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] } } } -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json +resource "aws_s3_bucket_policy" "test" { + bucket = aws_s3_bucket.test.id + policy = data.aws_iam_policy_document.bucket_policy.json } -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true +resource "aws_s3_object" "object" { + bucket = aws_s3_bucket.test.id + key = %[2]q + source = %[2]q } -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.0.0/20" +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + release_label = "1.0" + az_mode = "SINGLE" availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" } - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - -resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - type = "HDB" - release_label = "1.0" - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } - - command_line_arguments = { - %[2]q = %[3]q - } -} -`, rName, arg1, val1) -} - -func testAccKxClusterConfig_tags1(rName, tagKey1, tagValue1 string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.0.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - -resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - release_label = "1.0" - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } - - tags = { - %[2]q = %[3]q - } -} -`, rName, tagKey1, tagValue1) -} - -func testAccKxClusterConfig_database(rName string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - -resource "aws_finspace_kx_database" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id -} - -resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - - cache_storage_configurations { - type = "CACHE_1000" - size = 1200 - } - - database { - database_name = aws_finspace_kx_database.test.name - cache_configurations { - cache_type = "CACHE_1000" - db_paths = ["/"] - } - } - - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } -} -`, rName) -} - -func testAccKxClusterConfig_code(rName, path string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - -resource "aws_s3_bucket" "test" { - bucket = %[1]q -} - -data "aws_iam_policy_document" "bucket_policy" { - statement { - actions = [ - "s3:GetObject", - "s3:GetObjectTagging" - ] - - resources = [ - "arn:aws:s3:::${aws_s3_bucket.test.id}/*", - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "s3:ListBucket" - ] - - resources = [ - "arn:aws:s3:::${aws_s3_bucket.test.id}", - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } -} - -resource "aws_s3_bucket_policy" "test" { - bucket = aws_s3_bucket.test.id - policy = data.aws_iam_policy_document.bucket_policy.json -} - -resource "aws_s3_object" "object" { - bucket = aws_s3_bucket.test.id - key = %[2]q - source = %[2]q -} - -resource "aws_finspace_kx_cluster" "test" { - name = %[1]q - environment_id = aws_finspace_kx_environment.test.id - type = "HDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } - - code { - s3_bucket = aws_s3_bucket.test.id - s3_key = aws_s3_object.object.key - } -} -`, rName, path) -} - -func testAccKxClusterConfig_multiAZ(rName string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test1" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.16.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_subnet" "test2" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[1] -} - -resource "aws_subnet" "test3" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.64.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[2] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" } - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + code { + s3_bucket = aws_s3_bucket.test.id + s3_key = aws_s3_object.object.key } } - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +`, rName, path)) } -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id +func testAccKxClusterConfig_multiAZ(rName string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_subnet" "test2" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.16.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[1] } -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id +resource "aws_subnet" "test3" { + vpc_id = aws_vpc.test.id + cidr_block = "172.31.64.0/20" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[2] } resource "aws_finspace_kx_cluster" "test" { @@ -1493,265 +850,49 @@ resource "aws_finspace_kx_cluster" "test" { vpc_configuration { vpc_id = aws_vpc.test.id security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id, aws_subnet.test3.id] + subnet_ids = [aws_subnet.test.id, aws_subnet.test2.id, aws_subnet.test3.id] ip_address_type = "IP_V4" } } -`, rName) +`, rName)) } func testAccKxClusterConfig_rdb(rName string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` resource "aws_finspace_kx_cluster" "test" { name = %[1]q environment_id = aws_finspace_kx_environment.test.id - type = "RDB" - release_label = "1.0" - az_mode = "SINGLE" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - - savedown_storage_configuration { - type = "SDS01" - size = 500 - } - - capacity_configuration { - node_count = 2 - node_type = "kx.s.xlarge" - } - - vpc_configuration { - vpc_id = aws_vpc.test.id - security_group_ids = [aws_security_group.test.id] - subnet_ids = [aws_subnet.test.id] - ip_address_type = "IP_V4" - } -} -`, rName) -} - -func testAccKxClusterConfig_executionRole(rName string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } + type = "RDB" + release_label = "1.0" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + savedown_storage_configuration { + type = "SDS01" + size = 500 } -} -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } } - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id +`, rName)) } +func testAccKxClusterConfig_executionRole(rName string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` resource "aws_iam_policy" "test" { name = %[1]q policy = jsonencode({ @@ -1806,121 +947,13 @@ resource "aws_finspace_kx_cluster" "test" { ip_address_type = "IP_V4" } } -`, rName) +`, rName)) } func testAccKxClusterConfig_autoScaling(rName string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` resource "aws_finspace_kx_cluster" "test" { name = %[1]q environment_id = aws_finspace_kx_environment.test.id @@ -1949,121 +982,13 @@ resource "aws_finspace_kx_cluster" "test" { ip_address_type = "IP_V4" } } -`, rName) +`, rName)) } func testAccKxClusterConfig_initScript(rName, codePath, relPath string) string { - return fmt.Sprintf(` -data "aws_caller_identity" "current" {} - -output "account_id" { - value = data.aws_caller_identity.current.account_id -} - -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - -resource "aws_finspace_kx_environment" "test" { - name = %[1]q - kms_key_id = aws_kms_key.test.arn -} - -data "aws_iam_policy_document" "key_policy" { - statement { - actions = [ - "kms:Decrypt", - "kms:GenerateDataKey" - ] - - resources = [ - aws_kms_key.test.arn, - ] - - principals { - type = "Service" - identifiers = ["finspace.amazonaws.com"] - } - - condition { - test = "ArnLike" - variable = "aws:SourceArn" - values = ["${aws_finspace_kx_environment.test.arn}/*"] - } - - condition { - test = "StringEquals" - variable = "aws:SourceAccount" - values = [data.aws_caller_identity.current.account_id] - } - } - - statement { - actions = [ - "kms:*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} - -resource "aws_kms_key_policy" "test" { - key_id = aws_kms_key.test.id - policy = data.aws_iam_policy_document.key_policy.json -} - -resource "aws_vpc" "test" { - cidr_block = "172.31.0.0/16" - enable_dns_hostnames = true -} - -resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id - cidr_block = "172.31.32.0/20" - availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] -} - -resource "aws_security_group" "test" { - name = %[1]q - vpc_id = aws_vpc.test.id - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id -} - -data "aws_route_tables" "rts" { - vpc_id = aws_vpc.test.id -} - -resource "aws_route" "r" { - route_table_id = tolist(data.aws_route_tables.rts.ids)[0] - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.test.id -} - + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` resource "aws_s3_bucket" "test" { bucket = %[1]q } @@ -2179,5 +1104,5 @@ resource "aws_finspace_kx_cluster" "test" { s3_key = aws_s3_object.object.key } } -`, rName, codePath, relPath) +`, rName, codePath, relPath)) } From 2d1bff1bad64d41325f29d5ac3e79c63cb025485 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 15:34:39 -0400 Subject: [PATCH 19/26] r/aws_finspace_kx_cluster(lint): unconvert --- internal/service/finspace/kx_cluster.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 8f78e878a1a1..43b3a7e0ed4b 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -962,7 +962,7 @@ func flattenAutoScalingConfiguration(apiObject *types.AutoScalingConfiguration) m := map[string]interface{}{} if v := apiObject.AutoScalingMetric; v != "" { - m["auto_scaling_metric"] = types.AutoScalingMetric(v) + m["auto_scaling_metric"] = v } if v := apiObject.MinNodeCount; v != nil { @@ -996,11 +996,11 @@ func flattenSavedownStorageConfiguration(apiObject *types.KxSavedownStorageConfi m := map[string]interface{}{} if v := apiObject.Type; v != "" { - m["type"] = types.KxSavedownStorageType(v) + m["type"] = v } if v := apiObject.Size; v >= 4 && v <= 16000 { - m["size"] = int32(v) + m["size"] = v } return []interface{}{m} From 56775a6ce62f0d2ba1662cfc3cbe310e29ac4e8d Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 15:38:28 -0400 Subject: [PATCH 20/26] r/aws_finspace_kx_cluster(test): tags update --- internal/service/finspace/kx_cluster_test.go | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index d0c1f96cf441..75ca5df2a6f0 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -386,6 +386,23 @@ func TestAccFinSpaceKxCluster_tags(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), }, + { + Config: testAccKxClusterConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccKxClusterConfig_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxClusterExists(ctx, resourceName, &kxcluster), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, }, }) } @@ -672,6 +689,37 @@ resource "aws_finspace_kx_cluster" "test" { `, rName, tagKey1, tagValue1)) } +func testAccKxClusterConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return acctest.ConfigCompose( + testAccKxClusterConfigBase(rName), + fmt.Sprintf(` +resource "aws_finspace_kx_cluster" "test" { + name = %[1]q + environment_id = aws_finspace_kx_environment.test.id + type = "HDB" + az_mode = "SINGLE" + availability_zone_id = aws_finspace_kx_environment.test.availability_zones[0] + release_label = "1.0" + capacity_configuration { + node_count = 2 + node_type = "kx.s.xlarge" + } + + vpc_configuration { + vpc_id = aws_vpc.test.id + security_group_ids = [aws_security_group.test.id] + subnet_ids = [aws_subnet.test.id] + ip_address_type = "IP_V4" + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) +} + func testAccKxClusterConfig_database(rName string) string { return acctest.ConfigCompose( testAccKxClusterConfigBase(rName), From 46950692cf340a5b29dda71ddc8e305c904822c2 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 15:43:25 -0400 Subject: [PATCH 21/26] r/aws_finspace_kx_cluster(lint): avoid hardcoded partition --- internal/service/finspace/kx_cluster_test.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index 75ca5df2a6f0..41d21c526ba2 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -466,6 +466,7 @@ func testAccCheckKxClusterExists(ctx context.Context, name string, kxcluster *fi func testAccKxClusterConfigBase(rName string) string { return fmt.Sprintf(` data "aws_caller_identity" "current" {} +data "aws_partition" "current" {} output "account_id" { value = data.aws_caller_identity.current.account_id @@ -520,7 +521,7 @@ data "aws_iam_policy_document" "key_policy" { principals { type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + identifiers = ["arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:root"] } } } @@ -781,7 +782,7 @@ data "aws_iam_policy_document" "bucket_policy" { ] resources = [ - "arn:aws:s3:::${aws_s3_bucket.test.id}/*", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.test.id}/*", ] principals { @@ -808,7 +809,7 @@ data "aws_iam_policy_document" "bucket_policy" { ] resources = [ - "arn:aws:s3:::${aws_s3_bucket.test.id}", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.test.id}", ] principals { @@ -967,7 +968,7 @@ resource "aws_iam_role" "test" { Sid = "" Principal = { "Service" : "prod.finspacekx.aws.internal", - "AWS" : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + "AWS" : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:root" } }, ] @@ -1049,7 +1050,7 @@ data "aws_iam_policy_document" "test" { ] resources = [ - "arn:aws:s3:::${aws_s3_bucket.test.id}/*", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.test.id}/*", ] principals { @@ -1076,7 +1077,7 @@ data "aws_iam_policy_document" "test" { ] resources = [ - "arn:aws:s3:::${aws_s3_bucket.test.id}", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.test.id}", ] principals { From b464ae0f251fd90be83921443cfd80c8b0ee64f6 Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Thu, 8 Jun 2023 15:43:47 -0400 Subject: [PATCH 22/26] Add code.zip for customer code tests --- internal/service/finspace/kx_cluster_test.go | 4 ++-- internal/service/finspace/test-fixtures/code.zip | Bin 0 -> 769 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 internal/service/finspace/test-fixtures/code.zip diff --git a/internal/service/finspace/kx_cluster_test.go b/internal/service/finspace/kx_cluster_test.go index 75ca5df2a6f0..80246ef0a229 100644 --- a/internal/service/finspace/kx_cluster_test.go +++ b/internal/service/finspace/kx_cluster_test.go @@ -155,7 +155,7 @@ func TestAccFinSpaceKxCluster_code(t *testing.T) { var kxcluster finspace.GetKxClusterOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_finspace_kx_cluster.test" - codePath := "code.zip" + codePath := "test-fixtures/code.zip" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -306,7 +306,7 @@ func TestAccFinSpaceKxCluster_initializationScript(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_finspace_kx_cluster.test" // Need to set these to the bucket/key you want to use - codePath := "code.zip" + codePath := "test-fixtures/code.zip" initScriptPath := "code/helloworld.q" resource.ParallelTest(t, resource.TestCase{ diff --git a/internal/service/finspace/test-fixtures/code.zip b/internal/service/finspace/test-fixtures/code.zip new file mode 100644 index 0000000000000000000000000000000000000000..34a083bc499c33b85faad776235154f480dbce94 GIT binary patch literal 769 zcmWIWW@Zs#0Du7ulBypX!pp$URS}y4!lpo6TEWf0$nt}cfdQ;F z0Bi&Y0|$fBu2pa&1cAl~!i>mB&B@6x&o9bJ(JKTSXAl>YVgWSD8q>JTrXc~RJkFjx z8Ln|&|CDE72opnqH#-MId9ALM9s8+m{Zk^$NnAMfkv>>nJV4|cs?JWk6U zF)dF{5KT@`NJ{wN>l5~YKdd95foXySv$}vZ<40Wuwoj6k5*Hb?*FCZyk*jo>xzM>gZ|e`uTc#>Uf6oakQ=4%W%Yuhi4H-Y3tHX*Un1S znUyPfu8D5cRB%1byR4|;g;OmvGq-cLvGC=TU}k6K?B_j;{@e-4Ru1MaR!{a0jx`o% z7LFB8_hyb&cUDi1H5X4-7A|%U7Y^oTW&?*z`Q>``4Zx5A`9Hv$kx7IZcZ5RYmf@`< zh(%=dLX3n5H&R4^A{Yj?G&;kK#2MmPq8sL7nDNNI0mUW^Y-!vIWKt5h0p6@^Ak&zE NPzD%Q=Yg1k0RRwBvAzHR literal 0 HcmV?d00001 From fa8caca2e5c4e1583056620cfba0af6b1da47b3a Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Fri, 9 Jun 2023 02:15:44 -0400 Subject: [PATCH 23/26] Minor fix to set id --- internal/service/finspace/kx_cluster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 43b3a7e0ed4b..a7f801319907 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -438,8 +438,8 @@ func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta i } idParts := []string{ - aws.ToString(out.EnvironmentId), - aws.ToString(out.ClusterName), + aws.ToString(in.EnvironmentId), + aws.ToString(in.ClusterName), } id, err := flex.FlattenResourceId(idParts, kxClusterIDPartCount, false) if err != nil { From ad974f91fa57b1dba9df17ff1b06efdee6a721cc Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Fri, 9 Jun 2023 09:44:19 -0400 Subject: [PATCH 24/26] r/aws_finspace_kx_cluster: use environment id from resource id on read --- internal/service/finspace/kx_cluster.go | 32 +++++++++++++++---------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index a7f801319907..5c3d4b2fd38a 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -373,9 +373,21 @@ func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta i var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FinSpaceClient() + environmentId := d.Get("environment_id").(string) + clusterName := d.Get("name").(string) + idParts := []string{ + environmentId, + clusterName, + } + rID, err := flex.FlattenResourceId(idParts, kxClusterIDPartCount, false) + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionFlatteningResourceId, ResNameKxCluster, d.Get("name").(string), err)...) + } + d.SetId(rID) + in := &finspace.CreateKxClusterInput{ - EnvironmentId: aws.String(d.Get("environment_id").(string)), - ClusterName: aws.String(d.Get("name").(string)), + EnvironmentId: aws.String(environmentId), + ClusterName: aws.String(clusterName), ClusterType: types.KxClusterType(d.Get("type").(string)), ReleaseLabel: aws.String(d.Get("release_label").(string)), AzMode: types.KxAzMode(d.Get("az_mode").(string)), @@ -437,16 +449,6 @@ func resourceKxClusterCreate(ctx context.Context, d *schema.ResourceData, meta i return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxCluster, d.Get("name").(string), errors.New("empty output"))...) } - idParts := []string{ - aws.ToString(in.EnvironmentId), - aws.ToString(in.ClusterName), - } - id, err := flex.FlattenResourceId(idParts, kxClusterIDPartCount, false) - if err != nil { - return append(diags, create.DiagError(names.FinSpace, create.ErrActionFlatteningResourceId, ResNameKxCluster, d.Get("name").(string), err)...) - } - d.SetId(id) - if _, err := waitKxClusterCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxCluster, d.Id(), err)...) } @@ -519,7 +521,11 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int } // compose cluster ARN using environment ARN - env, err := findKxEnvironmentByID(ctx, conn, d.Get("environment_id").(string)) + parts, err := flex.ExpandResourceId(d.Id(), kxUserIDPartCount, false) + if err != nil { + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) + } + env, err := findKxEnvironmentByID(ctx, conn, parts[0]) if err != nil { return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxCluster, d.Id(), err)...) } From c4e8b6b9c1e44aa4f6ccf90b8ed1989ad8af86c2 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Fri, 9 Jun 2023 10:30:30 -0400 Subject: [PATCH 25/26] r/aws_finspace_kx_cluster: no force new on tag updates --- internal/service/finspace/kx_cluster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 5c3d4b2fd38a..71001b440d2e 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -309,7 +309,7 @@ func ResourceKxCluster() *schema.Resource { Type: schema.TypeString, Computed: true, }, - names.AttrTags: tftags.TagsSchemaForceNew(), + names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), "type": { Type: schema.TypeString, From 2b38493ecd357e410048698a4ac74360f6d0779e Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Fri, 9 Jun 2023 13:27:07 -0400 Subject: [PATCH 26/26] Set environment id in read function --- internal/service/finspace/kx_cluster.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/service/finspace/kx_cluster.go b/internal/service/finspace/kx_cluster.go index 71001b440d2e..e4748cd45b8d 100644 --- a/internal/service/finspace/kx_cluster.go +++ b/internal/service/finspace/kx_cluster.go @@ -531,6 +531,7 @@ func resourceKxClusterRead(ctx context.Context, d *schema.ResourceData, meta int } arn := fmt.Sprintf("%s/kxCluster/%s", aws.ToString(env.EnvironmentArn), aws.ToString(out.ClusterName)) d.Set("arn", arn) + d.Set("environment_id", parts[0]) return diags }