From 379c908caf26cee99c0b1fbd70dfa661ec248b27 Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Tue, 6 Jun 2023 15:57:32 -0400 Subject: [PATCH 01/19] Adds finspace_kx_environment resource --- internal/service/finspace/kx_environment.go | 587 ++++++++++++++++++ .../service/finspace/kx_environment_test.go | 461 ++++++++++++++ .../r/finspace_kx_environment.html.markdown | 113 ++++ 3 files changed, 1161 insertions(+) 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/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go new file mode 100644 index 000000000000..f96377ca9ac5 --- /dev/null +++ b/internal/service/finspace/kx_environment.go @@ -0,0 +1,587 @@ +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" + 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") +// @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{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "availability_zones": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + }, + "infrastructure_account_id": { + Type: schema.TypeString, + Computed: true, + }, + "created_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "last_modified_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 1000), + }, + "kms_key_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, + "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, + }, + }, + }, + }, + "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, + }, + }, + }, + }, + "tags": tftags.TagsSchema(), + "tags_all": tftags.TagsSchemaComputed(), + }, + CustomizeDiff: verify.SetTagsDiff, + } +} + +const ( + ResNameKxEnvironment = "Kx Environment" +) + +func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*conns.AWSClient).FinSpaceClient() + + in := &finspace.CreateKxEnvironmentInput{ + Name: aws.String(d.Get("name").(string)), + ClientToken: aws.String(id.UniqueId()), + Tags: GetTagsIn(ctx), + } + + 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 := client.CreateKxEnvironment(ctx, in) + if err != nil { + return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), err) + } + + if out == nil || out.EnvironmentId == nil { + return 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, client, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxEnvironment, d.Id(), err) + } + + if _, err := updateKxEnvironmentNetwork(ctx, d, client); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Id(), err) + } + + return resourceKxEnvironmentRead(ctx, d, meta) +} + +func resourceKxEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) 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 nil + } + + if err != nil { + return 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 create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err) + } + + if err := d.Set("custom_dns_configuration", flattenCustomDnsConfigurations(out.CustomDNSConfiguration)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err) + } + + return nil +} + +func resourceKxEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) 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 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 create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err) + } + } + + if !update { + return nil + } + return resourceKxEnvironmentRead(ctx, d, meta) +} + +func resourceKxEnvironmentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).FinSpaceClient() + + log.Printf("[INFO] Deleting FinSpace KxEnvironment %s", d.Id()) + + out, getErr := conn.GetKxEnvironment(ctx, &finspace.GetKxEnvironmentInput{ + EnvironmentId: aws.String(d.Id()), + }) + var nfe *types.ResourceNotFoundException + if (getErr != nil && errors.As(getErr, &nfe)) || out.Status == types.EnvironmentStatusDeleted { + log.Printf("[DEBUG] FinSpace KxEnvironment %s already deleted. Nothing to delete.", d.Id()) + return nil + } + _, err := conn.DeleteKxEnvironment(ctx, &finspace.DeleteKxEnvironmentInput{ + EnvironmentId: aws.String(d.Id()), + }) + + if err != nil { + return create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxEnvironment, d.Id(), err) + } + + if _, err := waitKxEnvironmentDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { + return create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxEnvironment, d.Id(), err) + } + + return nil +} + +/* +* + + As of 2023-02-09 updating network configuration requires 2 separate requests if both DNS and transit gateway + configuration is set. +*/ +func updateKxEnvironmentNetwork(ctx context.Context, d *schema.ResourceData, client *finspace.Client) (*finspace.UpdateKxEnvironmentNetworkOutput, 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 + } + + var out *finspace.UpdateKxEnvironmentNetworkOutput + var err error + + if updateTransitGatewayConfig { + out, err = client.UpdateKxEnvironmentNetwork(ctx, transitGatewayConfigIn) + if err != nil { + return nil, err + } + + if _, err := waitTransitGatewayConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { + return nil, err + } + } + + if updateCustomDnsConfig { + out, err = client.UpdateKxEnvironmentNetwork(ctx, customDnsConfigIn) + if err != nil { + return nil, err + } + + if _, err := waitCustomDnsConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { + return nil, err + } + } + + return out, nil +} + +func waitKxEnvironmentCreated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{string(types.EnvironmentStatusCreateRequested), string(types.EnvironmentStatusCreating)}, + Target: []string{string(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: []string{string(types.TgwStatusUpdateRequested), string(types.TgwStatusUpdating)}, + Target: []string{string(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: []string{string(types.DnsStatusUpdateRequested), string(types.DnsStatusUpdating)}, + Target: []string{string(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: []string{string(types.EnvironmentStatusDeleteRequested), string(types.EnvironmentStatusDeleting)}, + Target: []string{string(types.EnvironmentStatusDeleted)}, + 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 + } + + 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..359c4e93e32e --- /dev/null +++ b/internal/service/finspace/kx_environment_test.go @@ -0,0 +1,461 @@ +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" + + 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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + ), + }, + { + 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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + Config: testAccKxEnvironmentConfig_updateName(rName, rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_description(rName, "description 1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "description", "description 1"), + ), + }, + { + Config: testAccKxEnvironmentConfig_description(rName, "description 2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_dnsConfig(rName, "example.finspace.amazon.aws.com", "10.0.0.76"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(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(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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_tgwConfig(rName, "100.64.0.0/26"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(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, + Steps: []resource.TestStep{ + { + Config: testAccKxEnvironmentConfig_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckKxEnvironmentExists(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(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(resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func testAccCheckKxEnvironmentDestroy(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(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() + ctx := context.Background() + 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 testAccKxEnvironmentConfig_basic(rName string) string { + return fmt.Sprintf(` +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 +} +`, rName) +} + +func testAccKxEnvironmentConfig_updateName(rName, rName2 string) string { + return fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = %[1]q + deletion_window_in_days = 7 +} + +resource "aws_finspace_kx_environment" "test" { + name = %[2]q + kms_key_id =aws_kms_key.test.arn +} +`, rName, rName2) +} + +func testAccKxEnvironmentConfig_description(rName, desc string) string { + return fmt.Sprintf(` +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 + description = %[2]q +} +`, rName, desc) +} + +func testAccKxEnvironmentConfig_tgwConfig(rName, cidr string) string { + return fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = %[1]q + deletion_window_in_days = 7 +} + +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 fmt.Sprintf(` +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 + 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 fmt.Sprintf(` +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 + tags = { + %[2]q = %[3]q + } + +} +`, rName, tagKey1, tagValue1) +} + +func testAccKxEnvironmentConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +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 + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } + +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} 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..a8aaae35dd54 --- /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.test.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: + +* `description` - (Optional) Description for the KX environment. +* `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` - (Optional) List of DNS server name and server IP. This is used to set up Route-53 outbound resolvers. Defined below. +* `tags` - (Optional) List of key-value pairs to label the KX environment. + +### transit_gateway_configuration + +The transit_gateway_configuration block supports the following arguments: + +* `transit_gateway_id` - (Required) Identifier of the transit gateway created by the customer to connect outbound traffics from KX network to your internal network. +* `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. + +### custom_dns_configuration + +The custom_dns_configuration block supports the following arguments: + +* `custom_dns_server_name` - (Required) Name of the DNS server. +* `custom_dns_server_ip` - (Required) IP address of the DNS server. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `arn` - Amazon Resource Name (ARN) identifier of the KX environment. +* `id` - Unique identifier for 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. +* `infrastructure_account_id` - Unique identifier for the AWS environment infrastructure account. +* `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. +* `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. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) + +## Import + +FinSpace kdb environments can be imported using the `id`, e.g., + +``` +$ terraform import aws_finspace_kx_environment.a n3ceo7wqxoxcti5tujqwzs +``` From 820f89f161a3dacf7e1f41bb5e69348c87f620de Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Tue, 6 Jun 2023 16:24:02 -0400 Subject: [PATCH 02/19] Ran make servicepackages --- internal/service/finspace/service_package_gen.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/service/finspace/service_package_gen.go b/internal/service/finspace/service_package_gen.go index 774ce1af3cb6..38c1601591ca 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: ResourceKxEnvironment, + TypeName: "aws_finspace_kx_environment", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: "arn", + }, + }, + } } func (p *servicePackage) ServicePackageName() string { From b278925665a03a2bb8a58ae7055b5423f43547bc Mon Sep 17 00:00:00 2001 From: Kavan Bansal Date: Wed, 7 Jun 2023 01:35:57 -0400 Subject: [PATCH 03/19] Formatting fixes to environment --- internal/service/finspace/kx_environment.go | 41 ++++++++++--------- .../service/finspace/kx_environment_test.go | 34 +++++++-------- .../r/finspace_kx_environment.html.markdown | 12 +++--- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go index f96377ca9ac5..8d10eff33cf2 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -3,6 +3,7 @@ package finspace import ( "context" "errors" + "github.com/hashicorp/terraform-provider-aws/internal/enum" "log" "time" @@ -205,7 +206,7 @@ func resourceKxEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err) } - if err := d.Set("custom_dns_configuration", flattenCustomDnsConfigurations(out.CustomDNSConfiguration)); err != nil { + if err := d.Set("custom_dns_configuration", flattenCustomDNSConfigurations(out.CustomDNSConfiguration)); err != nil { return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err) } @@ -305,7 +306,7 @@ func updateKxEnvironmentNetwork(ctx context.Context, d *schema.ResourceData, cli 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{})) + customDnsConfigIn.CustomDNSConfiguration = expandCustomDNSConfigurations(v.([]interface{})) updateCustomDnsConfig = true } @@ -329,7 +330,7 @@ func updateKxEnvironmentNetwork(ctx context.Context, d *schema.ResourceData, cli return nil, err } - if _, err := waitCustomDnsConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { + if _, err := waitCustomDNSConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { return nil, err } } @@ -339,8 +340,8 @@ func updateKxEnvironmentNetwork(ctx context.Context, d *schema.ResourceData, cli func waitKxEnvironmentCreated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{string(types.EnvironmentStatusCreateRequested), string(types.EnvironmentStatusCreating)}, - Target: []string{string(types.EnvironmentStatusCreated)}, + Pending: enum.Slice(types.EnvironmentStatusCreateRequested, types.EnvironmentStatusCreating), + Target: enum.Slice(types.EnvironmentStatusCreated), Refresh: statusKxEnvironment(ctx, conn, id), Timeout: timeout, NotFoundChecks: 20, @@ -357,8 +358,8 @@ func waitKxEnvironmentCreated(ctx context.Context, conn *finspace.Client, id str func waitTransitGatewayConfigurationUpdated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{string(types.TgwStatusUpdateRequested), string(types.TgwStatusUpdating)}, - Target: []string{string(types.TgwStatusSuccessfullyUpdated)}, + Pending: enum.Slice(types.TgwStatusUpdateRequested, types.TgwStatusUpdating), + Target: enum.Slice(types.TgwStatusSuccessfullyUpdated), Refresh: statusTransitGatewayConfiguration(ctx, conn, id), Timeout: timeout, } @@ -371,11 +372,11 @@ func waitTransitGatewayConfigurationUpdated(ctx context.Context, conn *finspace. return nil, err } -func waitCustomDnsConfigurationUpdated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { +func waitCustomDNSConfigurationUpdated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{string(types.DnsStatusUpdateRequested), string(types.DnsStatusUpdating)}, - Target: []string{string(types.DnsStatusSuccessfullyUpdated)}, - Refresh: statusCustomDnsConfiguration(ctx, conn, id), + Pending: enum.Slice(types.DnsStatusUpdateRequested, types.DnsStatusUpdating), + Target: enum.Slice(types.DnsStatusSuccessfullyUpdated), + Refresh: statusCustomDNSConfiguration(ctx, conn, id), Timeout: timeout, } @@ -389,8 +390,8 @@ func waitCustomDnsConfigurationUpdated(ctx context.Context, conn *finspace.Clien func waitKxEnvironmentDeleted(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{string(types.EnvironmentStatusDeleteRequested), string(types.EnvironmentStatusDeleting)}, - Target: []string{string(types.EnvironmentStatusDeleted)}, + Pending: enum.Slice(types.EnvironmentStatusDeleteRequested, types.EnvironmentStatusDeleting), + Target: enum.Slice(types.EnvironmentStatusDeleted), Refresh: statusKxEnvironment(ctx, conn, id), Timeout: timeout, } @@ -433,7 +434,7 @@ func statusTransitGatewayConfiguration(ctx context.Context, conn *finspace.Clien } } -func statusCustomDnsConfiguration(ctx context.Context, conn *finspace.Client, id string) retry.StateRefreshFunc { +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) { @@ -492,7 +493,7 @@ func expandTransitGatewayConfiguration(tfList []interface{}) *types.TransitGatew return a } -func expandCustomDnsConfiguration(tfMap map[string]interface{}) *types.CustomDNSServer { +func expandCustomDNSConfiguration(tfMap map[string]interface{}) *types.CustomDNSServer { if tfMap == nil { return nil } @@ -510,7 +511,7 @@ func expandCustomDnsConfiguration(tfMap map[string]interface{}) *types.CustomDNS return a } -func expandCustomDnsConfigurations(tfList []interface{}) []types.CustomDNSServer { +func expandCustomDNSConfigurations(tfList []interface{}) []types.CustomDNSServer { if len(tfList) == 0 { return nil } @@ -524,7 +525,7 @@ func expandCustomDnsConfigurations(tfList []interface{}) []types.CustomDNSServer continue } - a := expandCustomDnsConfiguration(m) + a := expandCustomDNSConfiguration(m) if a == nil { continue @@ -554,7 +555,7 @@ func flattenTransitGatewayConfiguration(apiObject *types.TransitGatewayConfigura return []interface{}{m} } -func flattenCustomDnsConfiguration(apiObject *types.CustomDNSServer) map[string]interface{} { +func flattenCustomDNSConfiguration(apiObject *types.CustomDNSServer) map[string]interface{} { if apiObject == nil { return nil } @@ -572,7 +573,7 @@ func flattenCustomDnsConfiguration(apiObject *types.CustomDNSServer) map[string] return m } -func flattenCustomDnsConfigurations(apiObjects []types.CustomDNSServer) []interface{} { +func flattenCustomDNSConfigurations(apiObjects []types.CustomDNSServer) []interface{} { if len(apiObjects) == 0 { return nil } @@ -580,7 +581,7 @@ func flattenCustomDnsConfigurations(apiObjects []types.CustomDNSServer) []interf var l []interface{} for _, apiObject := range apiObjects { - l = append(l, flattenCustomDnsConfiguration(&apiObject)) + 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 index 359c4e93e32e..b8fccdf8355a 100644 --- a/internal/service/finspace/kx_environment_test.go +++ b/internal/service/finspace/kx_environment_test.go @@ -346,8 +346,8 @@ 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 } `, rName) } @@ -360,8 +360,8 @@ resource "aws_kms_key" "test" { } resource "aws_finspace_kx_environment" "test" { - name = %[2]q - kms_key_id =aws_kms_key.test.arn + name = %[2]q + kms_key_id = aws_kms_key.test.arn } `, rName, rName2) } @@ -374,8 +374,8 @@ 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 description = %[2]q } `, rName, desc) @@ -389,14 +389,14 @@ resource "aws_kms_key" "test" { } resource "aws_ec2_transit_gateway" "test" { - description = "test" + description = "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 transit_gateway_configuration { - transit_gateway_id = aws_ec2_transit_gateway.test.id + transit_gateway_id = aws_ec2_transit_gateway.test.id routable_cidr_space = %[2]q } @@ -412,11 +412,11 @@ 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 custom_dns_configuration { custom_dns_server_name = %[2]q - custom_dns_server_ip = %[3]q + custom_dns_server_ip = %[3]q } } @@ -431,8 +431,8 @@ 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 tags = { %[2]q = %[3]q } @@ -449,8 +449,8 @@ 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 tags = { %[2]q = %[3]q %[4]q = %[5]q diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown index a8aaae35dd54..d3085cd19543 100644 --- a/website/docs/r/finspace_kx_environment.html.markdown +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -21,8 +21,8 @@ resource "aws_kms_key" "example" { } resource "aws_finspace_kx_environment" "example" { - name = "my-tf-kx-environment" - kms_key_id =aws_kms_key.example.arn + name = "my-tf-kx-environment" + kms_key_id = aws_kms_key.example.arn } ``` @@ -39,18 +39,18 @@ resource "aws_ec2_transit_gateway" "example" { } resource "aws_finspace_kx_environment" "example_env" { - name = "my-tf-kx-environment" + name = "my-tf-kx-environment" description = "Environment description" - kms_key_id = aws_kms_key.test.arn + kms_key_id = aws_kms_key.test.arn transit_gateway_configuration { - transit_gateway_id = aws_ec2_transit_gateway.example.id + 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" + custom_dns_server_ip = "10.0.0.76" } } ``` From 731ccf0036a86194e0da6f5f53d18487ec2c183b Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 11:27:44 -0400 Subject: [PATCH 04/19] r/aws_finspace_kx_environment: alphabetize attributes --- internal/service/finspace/kx_environment.go | 80 ++++++++++----------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go index 8d10eff33cf2..bc8dee6736f5 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -3,7 +3,6 @@ package finspace import ( "context" "errors" - "github.com/hashicorp/terraform-provider-aws/internal/enum" "log" "time" @@ -17,6 +16,7 @@ import ( "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" 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" @@ -43,18 +43,10 @@ func ResourceKxEnvironment() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - }, "arn": { Type: schema.TypeString, Computed: true, }, - "status": { - Type: schema.TypeString, - Computed: true, - }, "availability_zones": { Type: schema.TypeList, Elem: &schema.Schema{ @@ -62,33 +54,61 @@ func ResourceKxEnvironment() *schema.Resource { }, Computed: true, }, - "infrastructure_account_id": { + "created_timestamp": { Type: schema.TypeString, Computed: true, }, - "created_timestamp": { + "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, }, - "last_modified_timestamp": { + "infrastructure_account_id": { Type: schema.TypeString, Computed: true, }, - "name": { + "kms_key_id": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringLenBetween(1, 255), + ValidateFunc: verify.ValidARN, }, - "description": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringLenBetween(1, 1000), + "last_modified_timestamp": { + Type: schema.TypeString, + Computed: true, }, - "kms_key_id": { + "name": { Type: schema.TypeString, Required: true, - ValidateFunc: verify.ValidARN, + 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, @@ -108,26 +128,6 @@ func ResourceKxEnvironment() *schema.Resource { }, }, }, - "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, - }, - }, - }, - }, - "tags": tftags.TagsSchema(), - "tags_all": tftags.TagsSchemaComputed(), }, CustomizeDiff: verify.SetTagsDiff, } From 7f59ba5cf4db3dd0e747692786360a97a18ae5b8 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 11:37:21 -0400 Subject: [PATCH 05/19] r/aws_finspace_kx_environment(docs): terrafmt --- website/docs/r/finspace_kx_environment.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown index d3085cd19543..402d382160d7 100644 --- a/website/docs/r/finspace_kx_environment.html.markdown +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -42,7 +42,7 @@ resource "aws_finspace_kx_environment" "example_env" { name = "my-tf-kx-environment" description = "Environment description" kms_key_id = aws_kms_key.test.arn - + transit_gateway_configuration { transit_gateway_id = aws_ec2_transit_gateway.example.id routable_cidr_space = "100.64.0.0/26" From 993cbd6f2532dd92fdaaf269b4c510521f9d94f8 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 14:57:30 -0400 Subject: [PATCH 06/19] r/aws_finspace_kx_environment(docs): tidy import, example sections --- website/docs/r/finspace_kx_environment.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown index 402d382160d7..6182dd379b80 100644 --- a/website/docs/r/finspace_kx_environment.html.markdown +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -41,7 +41,7 @@ resource "aws_ec2_transit_gateway" "example" { resource "aws_finspace_kx_environment" "example_env" { name = "my-tf-kx-environment" description = "Environment description" - kms_key_id = aws_kms_key.test.arn + kms_key_id = aws_kms_key.example.arn transit_gateway_configuration { transit_gateway_id = aws_ec2_transit_gateway.example.id @@ -106,8 +106,8 @@ In addition to all arguments above, the following attributes are exported: ## Import -FinSpace kdb environments can be imported using the `id`, e.g., +An AWS FinSpace Kx Environment can be imported using the `id`, e.g., ``` -$ terraform import aws_finspace_kx_environment.a n3ceo7wqxoxcti5tujqwzs +$ terraform import aws_finspace_kx_environment.example n3ceo7wqxoxcti5tujqwzs ``` From ead4c1fd1e78100fb198c17d342f84c0b5739df6 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 15:34:32 -0400 Subject: [PATCH 07/19] r/aws_finspace_kx_environment: handle deleted status in finder, update delete --- internal/service/finspace/kx_environment.go | 27 +++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go index bc8dee6736f5..effce0eeb969 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -17,6 +17,7 @@ import ( "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" @@ -254,17 +255,14 @@ func resourceKxEnvironmentDelete(ctx context.Context, d *schema.ResourceData, me log.Printf("[INFO] Deleting FinSpace KxEnvironment %s", d.Id()) - out, getErr := conn.GetKxEnvironment(ctx, &finspace.GetKxEnvironmentInput{ + _, err := conn.DeleteKxEnvironment(ctx, &finspace.DeleteKxEnvironmentInput{ EnvironmentId: aws.String(d.Id()), }) - var nfe *types.ResourceNotFoundException - if (getErr != nil && errors.As(getErr, &nfe)) || out.Status == types.EnvironmentStatusDeleted { + 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 nil } - _, err := conn.DeleteKxEnvironment(ctx, &finspace.DeleteKxEnvironmentInput{ - EnvironmentId: aws.String(d.Id()), - }) if err != nil { return create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxEnvironment, d.Id(), err) @@ -277,12 +275,8 @@ func resourceKxEnvironmentDelete(ctx context.Context, d *schema.ResourceData, me return nil } -/* -* - - As of 2023-02-09 updating network configuration requires 2 separate requests if both DNS and transit gateway - configuration is set. -*/ +// 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) (*finspace.UpdateKxEnvironmentNetworkOutput, error) { transitGatewayConfigIn := &finspace.UpdateKxEnvironmentNetworkInput{ @@ -391,7 +385,7 @@ func waitCustomDNSConfigurationUpdated(ctx context.Context, conn *finspace.Clien 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: enum.Slice(types.EnvironmentStatusDeleted), + Target: []string{}, Refresh: statusKxEnvironment(ctx, conn, id), Timeout: timeout, } @@ -465,6 +459,13 @@ func findKxEnvironmentByID(ctx context.Context, conn *finspace.Client, id string 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) From 653501e0f15e9e0a291c0a000938b0564b6c00ca Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 15:35:26 -0400 Subject: [PATCH 08/19] r/aws_finspace_kx_environment: simplify test configs --- .../service/finspace/kx_environment_test.go | 95 ++++++++----------- 1 file changed, 37 insertions(+), 58 deletions(-) diff --git a/internal/service/finspace/kx_environment_test.go b/internal/service/finspace/kx_environment_test.go index b8fccdf8355a..1ecfb6a5b675 100644 --- a/internal/service/finspace/kx_environment_test.go +++ b/internal/service/finspace/kx_environment_test.go @@ -28,6 +28,7 @@ func TestAccFinSpaceKxEnvironment_basic(t *testing.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() { @@ -42,6 +43,8 @@ func TestAccFinSpaceKxEnvironment_basic(t *testing.T) { Config: testAccKxEnvironmentConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", kmsKeyResourceName, "arn"), ), }, { @@ -112,7 +115,7 @@ func TestAccFinSpaceKxEnvironment_updateName(t *testing.T) { ), }, { - Config: testAccKxEnvironmentConfig_updateName(rName, rName2), + Config: testAccKxEnvironmentConfig_basic(rName2), Check: resource.ComposeTestCheckFunc( testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "name", rName2), @@ -338,56 +341,41 @@ func testAccCheckKxEnvironmentExists(name string, kxenvironment *finspace.GetKxE } } -func testAccKxEnvironmentConfig_basic(rName string) string { - return fmt.Sprintf(` +func testAccKxEnvironmentConfigBase() string { + return ` 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 -} -`, rName) -} - -func testAccKxEnvironmentConfig_updateName(rName, rName2 string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 +` } +func testAccKxEnvironmentConfig_basic(rName string) string { + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` resource "aws_finspace_kx_environment" "test" { - name = %[2]q + name = %[1]q kms_key_id = aws_kms_key.test.arn } -`, rName, rName2) +`, rName)) } func testAccKxEnvironmentConfig_description(rName, desc string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - + 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) +`, rName, desc)) } func testAccKxEnvironmentConfig_tgwConfig(rName, cidr string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - + return acctest.ConfigCompose( + testAccKxEnvironmentConfigBase(), + fmt.Sprintf(` resource "aws_ec2_transit_gateway" "test" { description = "test" } @@ -395,67 +383,58 @@ resource "aws_ec2_transit_gateway" "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) +`, rName, cidr)) } func testAccKxEnvironmentConfig_dnsConfig(rName, serverName, serverIP string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - + 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) +`, rName, serverName, serverIP)) } func testAccKxEnvironmentConfig_tags1(rName, tagKey1, tagValue1 string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - + 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) +`, rName, tagKey1, tagValue1)) } func testAccKxEnvironmentConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} - + 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) +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) } From ec5a6c8d4a1b3fc5f6cc0c0fea42c0660b868394 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 15:41:51 -0400 Subject: [PATCH 09/19] r/aws_finspace_kx_environment(lint): rm unused return arg --- internal/service/finspace/kx_environment.go | 26 ++++++++------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go index effce0eeb969..c7608311f60a 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -170,7 +170,7 @@ func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, me return create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxEnvironment, d.Id(), err) } - if _, err := updateKxEnvironmentNetwork(ctx, d, client); err != nil { + if err := updateKxEnvironmentNetwork(ctx, d, client); err != nil { return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Id(), err) } @@ -239,7 +239,7 @@ func resourceKxEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, me if d.HasChanges("transit_gateway_configuration") || d.HasChanges("custom_dns_configuration") { update = true - if _, err := updateKxEnvironmentNetwork(ctx, d, conn); err != nil { + if err := updateKxEnvironmentNetwork(ctx, d, conn); err != nil { return create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err) } } @@ -277,8 +277,7 @@ func resourceKxEnvironmentDelete(ctx context.Context, d *schema.ResourceData, me // 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) (*finspace.UpdateKxEnvironmentNetworkOutput, error) { - +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()), @@ -304,32 +303,27 @@ func updateKxEnvironmentNetwork(ctx context.Context, d *schema.ResourceData, cli updateCustomDnsConfig = true } - var out *finspace.UpdateKxEnvironmentNetworkOutput - var err error - if updateTransitGatewayConfig { - out, err = client.UpdateKxEnvironmentNetwork(ctx, transitGatewayConfigIn) - if err != nil { - return nil, err + if _, err := client.UpdateKxEnvironmentNetwork(ctx, transitGatewayConfigIn); err != nil { + return err } if _, err := waitTransitGatewayConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return nil, err + return err } } if updateCustomDnsConfig { - out, err = client.UpdateKxEnvironmentNetwork(ctx, customDnsConfigIn) - if err != nil { - return nil, err + if _, err := client.UpdateKxEnvironmentNetwork(ctx, customDnsConfigIn); err != nil { + return err } if _, err := waitCustomDNSConfigurationUpdated(ctx, client, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return nil, err + return err } } - return out, nil + return nil } func waitKxEnvironmentCreated(ctx context.Context, conn *finspace.Client, id string, timeout time.Duration) (*finspace.GetKxEnvironmentOutput, error) { From 32e7997cb26daf34c63248e472196198df73f877 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 16:11:18 -0400 Subject: [PATCH 10/19] r/aws_finspace_kx_environment: crud handlers return diags --- internal/service/finspace/kx_environment.go | 40 +++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go index c7608311f60a..f1baf81578fc 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -139,6 +139,7 @@ const ( ) func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics client := meta.(*conns.AWSClient).FinSpaceClient() in := &finspace.CreateKxEnvironmentInput{ @@ -157,27 +158,28 @@ func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, me out, err := client.CreateKxEnvironment(ctx, in) if err != nil { - return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), err)...) } if out == nil || out.EnvironmentId == nil { - return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), errors.New("empty output")) + 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, client, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxEnvironment, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForCreation, ResNameKxEnvironment, d.Id(), err)...) } if err := updateKxEnvironmentNetwork(ctx, d, client); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Id(), err)...) } - return resourceKxEnvironmentRead(ctx, d, meta) + 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()) @@ -185,11 +187,11 @@ func resourceKxEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] FinSpace KxEnvironment (%s) not found, removing from state", d.Id()) d.SetId("") - return nil + return diags } if err != nil { - return create.DiagError(names.FinSpace, create.ErrActionReading, ResNameKxEnvironment, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionReading, ResNameKxEnvironment, d.Id(), err)...) } d.Set("id", out.EnvironmentId) @@ -204,17 +206,18 @@ func resourceKxEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta d.Set("last_modified_timestamp", out.UpdateTimestamp.String()) if err := d.Set("transit_gateway_configuration", flattenTransitGatewayConfiguration(out.TransitGatewayConfiguration)); err != nil { - return create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err) + 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 create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionSetting, ResNameKxEnvironment, d.Id(), err)...) } - return nil + 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 @@ -233,24 +236,25 @@ func resourceKxEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, me log.Printf("[DEBUG] Updating FinSpace KxEnvironment (%s): %#v", d.Id(), in) _, err := conn.UpdateKxEnvironment(ctx, in) if err != nil { - return create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err) + 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 create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionUpdating, ResNameKxEnvironment, d.Id(), err)...) } } if !update { - return nil + return diags } - return resourceKxEnvironmentRead(ctx, d, meta) + 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()) @@ -261,18 +265,18 @@ func resourceKxEnvironmentDelete(ctx context.Context, d *schema.ResourceData, me 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 nil + return diags } if err != nil { - return create.DiagError(names.FinSpace, create.ErrActionDeleting, ResNameKxEnvironment, d.Id(), err) + 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 create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxEnvironment, d.Id(), err) + return append(diags, create.DiagError(names.FinSpace, create.ErrActionWaitingForDeletion, ResNameKxEnvironment, d.Id(), err)...) } - return nil + return diags } // As of 2023-02-09, updating network configuration requires 2 separate requests if both DNS From 1f492447eeb3a348f5de3a4fc1878e6f946484a4 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 16:15:23 -0400 Subject: [PATCH 11/19] r/aws_finspace_kx_environment: add name to registration --- internal/service/finspace/kx_environment.go | 2 +- internal/service/finspace/service_package_gen.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/service/finspace/kx_environment.go b/internal/service/finspace/kx_environment.go index f1baf81578fc..5932711898cb 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -24,7 +24,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKResource("aws_finspace_kx_environment") +// @SDKResource("aws_finspace_kx_environment", name="Kx Environment") // @Tags(identifierAttribute="arn") func ResourceKxEnvironment() *schema.Resource { return &schema.Resource{ diff --git a/internal/service/finspace/service_package_gen.go b/internal/service/finspace/service_package_gen.go index 38c1601591ca..8d807f4fd5b0 100644 --- a/internal/service/finspace/service_package_gen.go +++ b/internal/service/finspace/service_package_gen.go @@ -28,6 +28,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka { Factory: ResourceKxEnvironment, TypeName: "aws_finspace_kx_environment", + Name: "Kx Environment", Tags: &types.ServicePackageResourceTags{ IdentifierAttribute: "arn", }, From 04f1cdbcb00e9ad5174c9c7502fa3b3945529877 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Wed, 7 Jun 2023 16:15:53 -0400 Subject: [PATCH 12/19] r/aws_finspace_kx_environment: add UpdateTags flag --- internal/service/finspace/generate.go | 2 +- internal/service/finspace/tags_gen.go | 48 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/internal/service/finspace/generate.go b/internal/service/finspace/generate.go index f366292b6910..3a33d5aba8c5 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 -UpdateTags -SkipTypesImp // ONLY generate directives and package declaration! Do not add anything else to this file. package finspace diff --git a/internal/service/finspace/tags_gen.go b/internal/service/finspace/tags_gen.go index de42795bd345..82578e21d287 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,49 @@ func SetTagsOut(ctx context.Context, tags map[string]string) { inContext.TagsOut = types.Some(KeyValueTags(ctx, 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) +} From d3c6edae25c119dc250a49cafcb60395b41df9a2 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 09:57:21 -0400 Subject: [PATCH 13/19] r/aws_finspace_kx_environment: tag after creation this workaround avoids a confirmed bug in the CreateKxEnvironment API which does not properly apply tags when sent in the create request --- internal/service/finspace/generate.go | 2 +- internal/service/finspace/kx_environment.go | 15 ++++++++++----- internal/service/finspace/tags_gen.go | 9 +++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/internal/service/finspace/generate.go b/internal/service/finspace/generate.go index 3a33d5aba8c5..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 -UpdateTags -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 index 5932711898cb..234a47f3b15a 100644 --- a/internal/service/finspace/kx_environment.go +++ b/internal/service/finspace/kx_environment.go @@ -140,12 +140,11 @@ const ( func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - client := meta.(*conns.AWSClient).FinSpaceClient() + conn := meta.(*conns.AWSClient).FinSpaceClient() in := &finspace.CreateKxEnvironmentInput{ Name: aws.String(d.Get("name").(string)), ClientToken: aws.String(id.UniqueId()), - Tags: GetTagsIn(ctx), } if v, ok := d.GetOk("description"); ok { @@ -156,7 +155,7 @@ func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, me in.KmsKeyId = aws.String(v.(string)) } - out, err := client.CreateKxEnvironment(ctx, in) + out, err := conn.CreateKxEnvironment(ctx, in) if err != nil { return append(diags, create.DiagError(names.FinSpace, create.ErrActionCreating, ResNameKxEnvironment, d.Get("name").(string), err)...) } @@ -167,11 +166,17 @@ func resourceKxEnvironmentCreate(ctx context.Context, d *schema.ResourceData, me d.SetId(aws.ToString(out.EnvironmentId)) - if _, err := waitKxEnvironmentCreated(ctx, client, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + 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, client); err != nil { + 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)...) } diff --git a/internal/service/finspace/tags_gen.go b/internal/service/finspace/tags_gen.go index 82578e21d287..b69b7447c2c8 100644 --- a/internal/service/finspace/tags_gen.go +++ b/internal/service/finspace/tags_gen.go @@ -77,6 +77,15 @@ func SetTagsOut(ctx context.Context, tags map[string]string) { } } +// 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. From a55f9432cca4b35193a227cf9db656e2d0632a98 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 10:04:28 -0400 Subject: [PATCH 14/19] r/aws_finspace_kx_environment(docs): use standard tags, tags_all descriptions --- website/docs/r/finspace_kx_environment.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown index 6182dd379b80..ad3d2bfac563 100644 --- a/website/docs/r/finspace_kx_environment.html.markdown +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -67,7 +67,7 @@ The following arguments are optional: * `description` - (Optional) Description for the KX environment. * `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` - (Optional) List of DNS server name and server IP. This is used to set up Route-53 outbound resolvers. Defined below. -* `tags` - (Optional) List of key-value pairs to label 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 @@ -94,7 +94,7 @@ In addition to all arguments above, the following attributes are exported: * `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. * `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. +* `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 b4b2ed37e49ac962cbfbfca188f5b8d36edb2759 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 10:05:45 -0400 Subject: [PATCH 15/19] r/aws_finspace_kx_environment(docs): alphabetize --- .../r/finspace_kx_environment.html.markdown | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown index ad3d2bfac563..81e4c7cf2346 100644 --- a/website/docs/r/finspace_kx_environment.html.markdown +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -64,34 +64,35 @@ The following arguments are required: The following arguments are optional: -* `description` - (Optional) Description for the KX environment. -* `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` - (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: -* `transit_gateway_id` - (Required) Identifier of the transit gateway created by the customer to connect outbound traffics from KX network to your internal network. * `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. -### custom_dns_configuration - -The custom_dns_configuration block supports the following arguments: - -* `custom_dns_server_name` - (Required) Name of the DNS server. -* `custom_dns_server_ip` - (Required) IP address of the DNS server. ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `arn` - Amazon Resource Name (ARN) identifier of the KX environment. -* `id` - Unique identifier for 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. -* `infrastructure_account_id` - Unique identifier for the AWS environment infrastructure account. * `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). From 4855a5cfd14b29d21f7c6d871c0c13254c06b2cd Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 10:36:44 -0400 Subject: [PATCH 16/19] chore: mdlint --- website/docs/r/finspace_kx_environment.html.markdown | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/r/finspace_kx_environment.html.markdown b/website/docs/r/finspace_kx_environment.html.markdown index 81e4c7cf2346..e6d5b1532cad 100644 --- a/website/docs/r/finspace_kx_environment.html.markdown +++ b/website/docs/r/finspace_kx_environment.html.markdown @@ -83,7 +83,6 @@ 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: From 4782a6b4a3aae48637412adac688f01c675d817a Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 10:54:16 -0400 Subject: [PATCH 17/19] chore: changelog --- .changelog/31802.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/31802.txt 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 +``` From e78ede6ee902311563f57f7c95336735f2945bce Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 11:14:31 -0400 Subject: [PATCH 18/19] r/aws_finspace_kx_environment(test): add ctx to check funcs --- .../service/finspace/kx_environment_test.go | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/internal/service/finspace/kx_environment_test.go b/internal/service/finspace/kx_environment_test.go index 1ecfb6a5b675..678862910166 100644 --- a/internal/service/finspace/kx_environment_test.go +++ b/internal/service/finspace/kx_environment_test.go @@ -37,12 +37,12 @@ func TestAccFinSpaceKxEnvironment_basic(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", kmsKeyResourceName, "arn"), ), @@ -73,12 +73,12 @@ func TestAccFinSpaceKxEnvironment_disappears(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), acctest.CheckResourceDisappears(ctx, acctest.Provider, tffinspace.ResourceKxEnvironment(), resourceName), ), ExpectNonEmptyPlan: true, @@ -105,19 +105,19 @@ func TestAccFinSpaceKxEnvironment_updateName(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, { Config: testAccKxEnvironmentConfig_basic(rName2), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "name", rName2), ), }, @@ -142,19 +142,19 @@ func TestAccFinSpaceKxEnvironment_description(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_description(rName, "description 1"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "description", "description 1"), ), }, { Config: testAccKxEnvironmentConfig_description(rName, "description 2"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "description", "description 2"), ), }, @@ -179,12 +179,12 @@ func TestAccFinSpaceKxEnvironment_customDNS(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_dnsConfig(rName, "example.finspace.amazon.aws.com", "10.0.0.76"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + 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", @@ -194,7 +194,7 @@ func TestAccFinSpaceKxEnvironment_customDNS(t *testing.T) { { Config: testAccKxEnvironmentConfig_dnsConfig(rName, "updated.finspace.amazon.com", "10.0.0.24"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + 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", @@ -222,12 +222,12 @@ func TestAccFinSpaceKxEnvironment_transitGateway(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_tgwConfig(rName, "100.64.0.0/26"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "transit_gateway_configuration.*", map[string]string{ "routable_cidr_space": "100.64.0.0/26", }), @@ -254,12 +254,12 @@ func TestAccFinSpaceKxEnvironment_tags(t *testing.T) { }, ErrorCheck: acctest.ErrorCheck(t, finspace.ServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckKxEnvironmentDestroy, + CheckDestroy: testAccCheckKxEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccKxEnvironmentConfig_tags1(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), @@ -267,7 +267,7 @@ func TestAccFinSpaceKxEnvironment_tags(t *testing.T) { { Config: testAccKxEnvironmentConfig_tags2(rName, "key1", "value1", "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), @@ -276,7 +276,7 @@ func TestAccFinSpaceKxEnvironment_tags(t *testing.T) { { Config: testAccKxEnvironmentConfig_tags1(rName, "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckKxEnvironmentExists(resourceName, &kxenvironment), + testAccCheckKxEnvironmentExists(ctx, resourceName, &kxenvironment), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), @@ -285,36 +285,38 @@ func TestAccFinSpaceKxEnvironment_tags(t *testing.T) { }) } -func testAccCheckKxEnvironmentDestroy(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() - ctx := context.Background() +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 - } + 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) { + 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 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 create.Error(names.FinSpace, create.ErrActionCheckingDestroyed, tffinspace.ResNameKxEnvironment, rs.Primary.ID, errors.New("not destroyed")) - } - return nil + return nil + } } -func testAccCheckKxEnvironmentExists(name string, kxenvironment *finspace.GetKxEnvironmentOutput) resource.TestCheckFunc { +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 { From a4cf4fcd8ef9129853c295a1202cfdb8cc481767 Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Thu, 8 Jun 2023 11:29:57 -0400 Subject: [PATCH 19/19] r/aws_finspace_kx_environment(test): golangci-lint --- internal/service/finspace/kx_environment_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/finspace/kx_environment_test.go b/internal/service/finspace/kx_environment_test.go index 678862910166..088f1f565e1e 100644 --- a/internal/service/finspace/kx_environment_test.go +++ b/internal/service/finspace/kx_environment_test.go @@ -328,7 +328,6 @@ func testAccCheckKxEnvironmentExists(ctx context.Context, name string, kxenviron } conn := acctest.Provider.Meta().(*conns.AWSClient).FinSpaceClient() - ctx := context.Background() resp, err := conn.GetKxEnvironment(ctx, &finspace.GetKxEnvironmentInput{ EnvironmentId: aws.String(rs.Primary.ID), })