From aaee49675a6ee25eb26aa70090bf1b46342ec6c8 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Mon, 30 May 2022 09:01:19 +0300 Subject: [PATCH 1/8] redshiftdata stmt --- internal/provider/provider.go | 3 + internal/service/redshiftdata/find.go | 34 +++++ internal/service/redshiftdata/statement.go | 124 ++++++++++++++++++ .../service/redshiftdata/statement_test.go | 92 +++++++++++++ internal/service/redshiftdata/status.go | 24 ++++ internal/service/redshiftdata/wait.go | 38 ++++++ 6 files changed, 315 insertions(+) create mode 100644 internal/service/redshiftdata/find.go create mode 100644 internal/service/redshiftdata/statement.go create mode 100644 internal/service/redshiftdata/statement_test.go create mode 100644 internal/service/redshiftdata/status.go create mode 100644 internal/service/redshiftdata/wait.go diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 8c35210234d..a66a7a3f9cc 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -138,6 +138,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/service/ram" "github.com/hashicorp/terraform-provider-aws/internal/service/rds" "github.com/hashicorp/terraform-provider-aws/internal/service/redshift" + "github.com/hashicorp/terraform-provider-aws/internal/service/redshiftdata" "github.com/hashicorp/terraform-provider-aws/internal/service/resourcegroups" "github.com/hashicorp/terraform-provider-aws/internal/service/resourcegroupstaggingapi" "github.com/hashicorp/terraform-provider-aws/internal/service/route53" @@ -1778,6 +1779,8 @@ func Provider() *schema.Provider { "aws_redshift_subnet_group": redshift.ResourceSubnetGroup(), "aws_redshift_usage_limit": redshift.ResourceUsageLimit(), + "aws_redshiftdata_statement": redshiftdata.ResourceStatement(), + "aws_resourcegroups_group": resourcegroups.ResourceGroup(), "aws_route53_delegation_set": route53.ResourceDelegationSet(), diff --git a/internal/service/redshiftdata/find.go b/internal/service/redshiftdata/find.go new file mode 100644 index 00000000000..d07b61f5eaf --- /dev/null +++ b/internal/service/redshiftdata/find.go @@ -0,0 +1,34 @@ +package redshiftdata + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/redshiftdataapiservice" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func FindStatementById(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) (*redshiftdataapiservice.DescribeStatementOutput, error) { + input := &redshiftdataapiservice.DescribeStatementInput{ + Id: aws.String(id), + } + + output, err := conn.DescribeStatement(input) + + if tfawserr.ErrCodeEquals(err, redshiftdataapiservice.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} diff --git a/internal/service/redshiftdata/statement.go b/internal/service/redshiftdata/statement.go new file mode 100644 index 00000000000..c14c4e91d2a --- /dev/null +++ b/internal/service/redshiftdata/statement.go @@ -0,0 +1,124 @@ +package redshiftdata + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/redshiftdataapiservice" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" +) + +func ResourceStatement() *schema.Resource { + return &schema.Resource{ + Create: resourceStatementCreate, + Read: resourceStatementRead, + Delete: schema.Noop, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "cluster_identifier": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "database": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "db_user": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "secret_arn": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, + }, + "sql": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "statement_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "with_event": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, + }, + } +} + +func resourceStatementCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).RedshiftDataConn + + request := &redshiftdataapiservice.ExecuteStatementInput{ + ClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)), + Database: aws.String(d.Get("database").(string)), + Sql: aws.String(d.Get("sql").(string)), + WithEvent: aws.Bool(d.Get("with_event").(bool)), + } + + if v, ok := d.GetOk("secret_arn"); ok { + request.SecretArn = aws.String(v.(string)) + } + + if v, ok := d.GetOk("db_user"); ok { + request.DbUser = aws.String(v.(string)) + } + + if v, ok := d.GetOk("statement_name"); ok { + request.StatementName = aws.String(v.(string)) + } + + output, err := conn.ExecuteStatement(request) + if err != nil || output.Id == nil { + return fmt.Errorf("Error Executing Redshift Data Statement %s: %s", d.Get("cluster_identifier").(string), err) + } + + d.SetId(aws.StringValue(output.Id)) + + if _, err := waitStatementFinished(conn, d.Id()); err != nil { + return fmt.Errorf("error waiting for Redshift Data Statement (%s) to be finished: %w", d.Id(), err) + } + + return resourceStatementRead(d, meta) +} + +func resourceStatementRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).RedshiftDataConn + + sub, err := FindStatementById(conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Redshift Data Statement (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error reading Redshift Data Statement %s: %w", d.Id(), err) + } + + d.Set("cluster_identifier", sub.ClusterIdentifier) + d.Set("secret_arn", sub.SecretArn) + d.Set("database", sub.Database) + d.Set("db_user", sub.DbUser) + d.Set("sql", sub.QueryString) + + return nil +} diff --git a/internal/service/redshiftdata/statement_test.go b/internal/service/redshiftdata/statement_test.go new file mode 100644 index 00000000000..74189910763 --- /dev/null +++ b/internal/service/redshiftdata/statement_test.go @@ -0,0 +1,92 @@ +package redshiftdata_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/redshiftdataapiservice" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfredshiftdata "github.com/hashicorp/terraform-provider-aws/internal/service/redshiftdata" +) + +func TestAccRedshiftDataStatement_basic(t *testing.T) { + var v redshiftdataapiservice.DescribeStatementOutput + resourceName := "aws_redshiftdata_statement.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, redshiftdataapiservice.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccStatement_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStatementExists(resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, "cluster_identifier", "aws_redshift_cluster.test", "cluster_identifier"), + resource.TestCheckResourceAttrPair(resourceName, "db_user", "aws_redshift_cluster.test", "master_username"), + resource.TestCheckResourceAttr(resourceName, "sql", "CREATE GROUP group_name;"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"database"}, + }, + }, + }) +} + +func testAccCheckStatementExists(n string, v *redshiftdataapiservice.DescribeStatementOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No Redshift Data Statement is set") + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftDataConn + + out, err := tfredshiftdata.FindStatementById(conn, rs.Primary.ID) + + if err != nil { + return err + } + + *v = *out + + return nil + } +} + +func testAccStatement_basic(rName string) string { + return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptInExclude("usw2-az2"), fmt.Sprintf(` +resource "aws_redshift_cluster" "test" { + cluster_identifier = %[1]q + availability_zone = data.aws_availability_zones.available.names[0] + database_name = "mydb" + master_username = "foo_test" + master_password = "Mustbe8characters" + node_type = "dc2.large" + automated_snapshot_retention_period = 0 + allow_version_upgrade = false + skip_final_snapshot = true +} + +resource "aws_redshiftdata_statement" "test" { + cluster_identifier = aws_redshift_cluster.test.cluster_identifier + database = aws_redshift_cluster.test.database_name + db_user = aws_redshift_cluster.test.master_username + sql = "CREATE GROUP group_name;" +} +`, rName)) +} diff --git a/internal/service/redshiftdata/status.go b/internal/service/redshiftdata/status.go new file mode 100644 index 00000000000..852b8dc5b47 --- /dev/null +++ b/internal/service/redshiftdata/status.go @@ -0,0 +1,24 @@ +package redshiftdata + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/redshiftdataapiservice" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func statusStatement(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := FindStatementById(conn, id) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, aws.StringValue(output.Status), nil + } +} diff --git a/internal/service/redshiftdata/wait.go b/internal/service/redshiftdata/wait.go new file mode 100644 index 00000000000..686ca7491ff --- /dev/null +++ b/internal/service/redshiftdata/wait.go @@ -0,0 +1,38 @@ +package redshiftdata + +import ( + "errors" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/redshiftdataapiservice" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func waitStatementFinished(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) (*redshiftdataapiservice.DescribeStatementOutput, error) { //nolint:unparam + stateConf := &resource.StateChangeConf{ + Pending: []string{ + redshiftdataapiservice.StatusStringPicked, + redshiftdataapiservice.StatusStringStarted, + redshiftdataapiservice.StatusStringSubmitted, + }, + Target: []string{redshiftdataapiservice.StatusStringFinished}, + Refresh: statusStatement(conn, id), + Timeout: 10 * time.Minute, + MinTimeout: 10 * time.Second, + Delay: 30 * time.Second, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*redshiftdataapiservice.DescribeStatementOutput); ok { + if status := aws.StringValue(output.Status); status == redshiftdataapiservice.StatusStringFailed { + tfresource.SetLastError(err, errors.New(aws.StringValue(output.Error))) + } + + return output, err + } + + return nil, err +} From 7c3d0dcd910382381f0f9b071ac67c27fd6c8f49 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Mon, 30 May 2022 10:32:23 +0300 Subject: [PATCH 2/8] import tests --- internal/service/redshiftdata/statement.go | 4 ++-- internal/service/redshiftdata/statement_test.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/service/redshiftdata/statement.go b/internal/service/redshiftdata/statement.go index c14c4e91d2a..b594e37155c 100644 --- a/internal/service/redshiftdata/statement.go +++ b/internal/service/redshiftdata/statement.go @@ -116,8 +116,8 @@ func resourceStatementRead(d *schema.ResourceData, meta interface{}) error { d.Set("cluster_identifier", sub.ClusterIdentifier) d.Set("secret_arn", sub.SecretArn) - d.Set("database", sub.Database) - d.Set("db_user", sub.DbUser) + d.Set("database", d.Get("database").(string)) + d.Set("db_user", d.Get("db_user").(string)) d.Set("sql", sub.QueryString) return nil diff --git a/internal/service/redshiftdata/statement_test.go b/internal/service/redshiftdata/statement_test.go index 74189910763..b49307115cb 100644 --- a/internal/service/redshiftdata/statement_test.go +++ b/internal/service/redshiftdata/statement_test.go @@ -29,7 +29,6 @@ func TestAccRedshiftDataStatement_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckStatementExists(resourceName, &v), resource.TestCheckResourceAttrPair(resourceName, "cluster_identifier", "aws_redshift_cluster.test", "cluster_identifier"), - resource.TestCheckResourceAttrPair(resourceName, "db_user", "aws_redshift_cluster.test", "master_username"), resource.TestCheckResourceAttr(resourceName, "sql", "CREATE GROUP group_name;"), ), }, @@ -37,7 +36,7 @@ func TestAccRedshiftDataStatement_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"database"}, + ImportStateVerifyIgnore: []string{"database", "db_user"}, }, }, }) From bbd075c3d62c1cf1d375cf64c671f8c91b7a7a40 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Mon, 30 May 2022 13:08:16 +0300 Subject: [PATCH 3/8] docs + params --- internal/service/redshiftdata/statement.go | 107 ++++++++++++++++++ .../service/redshiftdata/statement_test.go | 1 + .../r/redshiftdata_statement.html.markdown | 48 ++++++++ 3 files changed, 156 insertions(+) create mode 100644 website/docs/r/redshiftdata_statement.html.markdown diff --git a/internal/service/redshiftdata/statement.go b/internal/service/redshiftdata/statement.go index b594e37155c..cb55021642e 100644 --- a/internal/service/redshiftdata/statement.go +++ b/internal/service/redshiftdata/statement.go @@ -38,6 +38,26 @@ func ResourceStatement() *schema.Resource { Optional: true, ForceNew: true, }, + "parameters": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + }, + }, "secret_arn": { Type: schema.TypeString, Optional: true, @@ -85,6 +105,10 @@ func resourceStatementCreate(d *schema.ResourceData, meta interface{}) error { request.StatementName = aws.String(v.(string)) } + if v, ok := d.GetOk("parameters"); ok && len(v.([]interface{})) > 0 { + request.Parameters = expandParameters(v.([]interface{})) + } + output, err := conn.ExecuteStatement(request) if err != nil || output.Id == nil { return fmt.Errorf("Error Executing Redshift Data Statement %s: %s", d.Get("cluster_identifier").(string), err) @@ -120,5 +144,88 @@ func resourceStatementRead(d *schema.ResourceData, meta interface{}) error { d.Set("db_user", d.Get("db_user").(string)) d.Set("sql", sub.QueryString) + if err := d.Set("parameters", flattenParameters(sub.QueryParameters)); err != nil { + return fmt.Errorf("error setting parameters: %w", err) + } + return nil } + +func expandParameter(tfMap map[string]interface{}) *redshiftdataapiservice.SqlParameter { + if tfMap == nil { + return nil + } + + apiObject := &redshiftdataapiservice.SqlParameter{} + + if v, ok := tfMap["name"].(string); ok { + apiObject.Name = aws.String(v) + } + + if v, ok := tfMap["value"].(string); ok { + apiObject.Value = aws.String(v) + } + + return apiObject +} + +func expandParameters(tfList []interface{}) []*redshiftdataapiservice.SqlParameter { + if len(tfList) == 0 { + return nil + } + + var apiObjects []*redshiftdataapiservice.SqlParameter + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]interface{}) + + if !ok { + continue + } + + apiObject := expandParameter(tfMap) + + if apiObject == nil { + continue + } + + apiObjects = append(apiObjects, apiObject) + } + + return apiObjects +} + +func flattenParameter(apiObject *redshiftdataapiservice.SqlParameter) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.Name; v != nil { + tfMap["name"] = aws.StringValue(v) + } + + if v := apiObject.Value; v != nil { + tfMap["value"] = aws.StringValue(v) + } + return tfMap +} + +func flattenParameters(apiObjects []*redshiftdataapiservice.SqlParameter) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + tfList = append(tfList, flattenParameter(apiObject)) + } + + return tfList +} diff --git a/internal/service/redshiftdata/statement_test.go b/internal/service/redshiftdata/statement_test.go index b49307115cb..63cc67ec2f9 100644 --- a/internal/service/redshiftdata/statement_test.go +++ b/internal/service/redshiftdata/statement_test.go @@ -30,6 +30,7 @@ func TestAccRedshiftDataStatement_basic(t *testing.T) { testAccCheckStatementExists(resourceName, &v), resource.TestCheckResourceAttrPair(resourceName, "cluster_identifier", "aws_redshift_cluster.test", "cluster_identifier"), resource.TestCheckResourceAttr(resourceName, "sql", "CREATE GROUP group_name;"), + resource.TestCheckResourceAttr(resourceName, "parameters.#", "0"), ), }, { diff --git a/website/docs/r/redshiftdata_statement.html.markdown b/website/docs/r/redshiftdata_statement.html.markdown new file mode 100644 index 00000000000..f6abd3fc262 --- /dev/null +++ b/website/docs/r/redshiftdata_statement.html.markdown @@ -0,0 +1,48 @@ +--- +subcategory: "Redshift Data" +layout: "aws" +page_title: "AWS: aws_redshiftdata_.subnet_group" +description: |- + Provides a Redshift Data Statement execution resource. +--- + +# Resource: aws_redshiftdata_.subnet_group + +Executes a Redshift Data Statement. + +## Example Usage + +```terraform +resource "aws_redshiftdata_statement" "example" { + cluster_identifier = aws_redshift_cluster.example.cluster_identifier + database = aws_redshift_cluster.example.database_name + db_user = aws_redshift_cluster.example.master_username + sql = "CREATE GROUP group_name;" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cluster_identifier` - (Required) The cluster identifier. +* `database` - (Required) The name of the database. +* `db_user` - (Optional) The database user name. +* `secret_arn` - (Optional) The name or ARN of the secret that enables access to the database. +* `sql` - (Required) The SQL statement text to run. +* `statement_name` - (Optional) The name of the SQL statement. You can name the SQL statement when you create it to identify the query. +* `with_event` - (Optional) A value that indicates whether to send an event to the Amazon EventBridge event bus after the SQL statement runs. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The Redshift Data Statement ID. + +## Import + +Redshift Data Statements can be imported using the `id`, e.g., + +``` +$ terraform import aws_redshiftdata_statement.example example +``` From 858d7ffad86a8434a1db55548b432b79520b5ed9 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Mon, 30 May 2022 13:09:10 +0300 Subject: [PATCH 4/8] changelog --- .changelog/25104.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/25104.txt diff --git a/.changelog/25104.txt b/.changelog/25104.txt new file mode 100644 index 00000000000..73ff040fb97 --- /dev/null +++ b/.changelog/25104.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_redshiftdata_statement +``` \ No newline at end of file From f667a18b792fac5df60313d6f52fc1f36f4e870d Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Mon, 30 May 2022 13:37:55 +0300 Subject: [PATCH 5/8] docs --- website/docs/r/redshiftdata_statement.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/redshiftdata_statement.html.markdown b/website/docs/r/redshiftdata_statement.html.markdown index f6abd3fc262..b56fc7ffe9c 100644 --- a/website/docs/r/redshiftdata_statement.html.markdown +++ b/website/docs/r/redshiftdata_statement.html.markdown @@ -6,7 +6,7 @@ description: |- Provides a Redshift Data Statement execution resource. --- -# Resource: aws_redshiftdata_.subnet_group +# Resource: aws_redshiftdata_statement Executes a Redshift Data Statement. From d2554e438d254203e217bdad0524ec39f2ed5433 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Mon, 30 May 2022 14:51:00 +0300 Subject: [PATCH 6/8] docs --- internal/service/redshiftdata/statement_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/redshiftdata/statement_test.go b/internal/service/redshiftdata/statement_test.go index 63cc67ec2f9..1c5b2b9c9e6 100644 --- a/internal/service/redshiftdata/statement_test.go +++ b/internal/service/redshiftdata/statement_test.go @@ -25,7 +25,7 @@ func TestAccRedshiftDataStatement_basic(t *testing.T) { CheckDestroy: nil, Steps: []resource.TestStep{ { - Config: testAccStatement_basic(rName), + Config: testAccStatementConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckStatementExists(resourceName, &v), resource.TestCheckResourceAttrPair(resourceName, "cluster_identifier", "aws_redshift_cluster.test", "cluster_identifier"), @@ -68,7 +68,7 @@ func testAccCheckStatementExists(n string, v *redshiftdataapiservice.DescribeSta } } -func testAccStatement_basic(rName string) string { +func testAccStatementConfigBasic(rName string) string { return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptInExclude("usw2-az2"), fmt.Sprintf(` resource "aws_redshift_cluster" "test" { cluster_identifier = %[1]q From 07dcf48f2e470b99a6d54b0fb8efc8c213a60665 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 1 Jun 2022 11:45:30 -0400 Subject: [PATCH 7/8] Cosmetics. --- internal/service/redshiftdata/find.go | 2 +- internal/service/redshiftdata/statement.go | 40 +++++++++++-------- .../service/redshiftdata/statement_test.go | 6 +-- internal/service/redshiftdata/status.go | 2 +- internal/service/redshiftdata/wait.go | 4 +- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/internal/service/redshiftdata/find.go b/internal/service/redshiftdata/find.go index d07b61f5eaf..859d114a952 100644 --- a/internal/service/redshiftdata/find.go +++ b/internal/service/redshiftdata/find.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func FindStatementById(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) (*redshiftdataapiservice.DescribeStatementOutput, error) { +func FindStatementByID(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) (*redshiftdataapiservice.DescribeStatementOutput, error) { input := &redshiftdataapiservice.DescribeStatementInput{ Id: aws.String(id), } diff --git a/internal/service/redshiftdata/statement.go b/internal/service/redshiftdata/statement.go index cb55021642e..4f93959571c 100644 --- a/internal/service/redshiftdata/statement.go +++ b/internal/service/redshiftdata/statement.go @@ -3,6 +3,7 @@ package redshiftdata import ( "fmt" "log" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/redshiftdataapiservice" @@ -22,6 +23,10 @@ func ResourceStatement() *schema.Resource { State: schema.ImportStatePassthrough, }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + }, + Schema: map[string]*schema.Schema{ "cluster_identifier": { Type: schema.TypeString, @@ -86,38 +91,39 @@ func ResourceStatement() *schema.Resource { func resourceStatementCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).RedshiftDataConn - request := &redshiftdataapiservice.ExecuteStatementInput{ + input := &redshiftdataapiservice.ExecuteStatementInput{ ClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)), Database: aws.String(d.Get("database").(string)), Sql: aws.String(d.Get("sql").(string)), WithEvent: aws.Bool(d.Get("with_event").(bool)), } - if v, ok := d.GetOk("secret_arn"); ok { - request.SecretArn = aws.String(v.(string)) + if v, ok := d.GetOk("db_user"); ok { + input.DbUser = aws.String(v.(string)) } - if v, ok := d.GetOk("db_user"); ok { - request.DbUser = aws.String(v.(string)) + if v, ok := d.GetOk("parameters"); ok && len(v.([]interface{})) > 0 { + input.Parameters = expandParameters(v.([]interface{})) } - if v, ok := d.GetOk("statement_name"); ok { - request.StatementName = aws.String(v.(string)) + if v, ok := d.GetOk("secret_arn"); ok { + input.SecretArn = aws.String(v.(string)) } - if v, ok := d.GetOk("parameters"); ok && len(v.([]interface{})) > 0 { - request.Parameters = expandParameters(v.([]interface{})) + if v, ok := d.GetOk("statement_name"); ok { + input.StatementName = aws.String(v.(string)) } - output, err := conn.ExecuteStatement(request) - if err != nil || output.Id == nil { - return fmt.Errorf("Error Executing Redshift Data Statement %s: %s", d.Get("cluster_identifier").(string), err) + output, err := conn.ExecuteStatement(input) + + if err != nil { + return fmt.Errorf("executing Redshift Data Statement: %w", err) } d.SetId(aws.StringValue(output.Id)) - if _, err := waitStatementFinished(conn, d.Id()); err != nil { - return fmt.Errorf("error waiting for Redshift Data Statement (%s) to be finished: %w", d.Id(), err) + if _, err := waitStatementFinished(conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + return fmt.Errorf("waiting for Redshift Data Statement (%s) to finish: %w", d.Id(), err) } return resourceStatementRead(d, meta) @@ -126,7 +132,7 @@ func resourceStatementCreate(d *schema.ResourceData, meta interface{}) error { func resourceStatementRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).RedshiftDataConn - sub, err := FindStatementById(conn, d.Id()) + sub, err := FindStatementByID(conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Redshift Data Statement (%s) not found, removing from state", d.Id()) @@ -135,7 +141,7 @@ func resourceStatementRead(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error reading Redshift Data Statement %s: %w", d.Id(), err) + return fmt.Errorf("reading Redshift Data Statement (%s): %w", d.Id(), err) } d.Set("cluster_identifier", sub.ClusterIdentifier) @@ -145,7 +151,7 @@ func resourceStatementRead(d *schema.ResourceData, meta interface{}) error { d.Set("sql", sub.QueryString) if err := d.Set("parameters", flattenParameters(sub.QueryParameters)); err != nil { - return fmt.Errorf("error setting parameters: %w", err) + return fmt.Errorf("setting parameters: %w", err) } return nil diff --git a/internal/service/redshiftdata/statement_test.go b/internal/service/redshiftdata/statement_test.go index 1c5b2b9c9e6..0339ffdb4fb 100644 --- a/internal/service/redshiftdata/statement_test.go +++ b/internal/service/redshiftdata/statement_test.go @@ -51,18 +51,18 @@ func testAccCheckStatementExists(n string, v *redshiftdataapiservice.DescribeSta } if rs.Primary.ID == "" { - return fmt.Errorf("No Redshift Data Statement is set") + return fmt.Errorf("No Redshift Data Statement ID is set") } conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftDataConn - out, err := tfredshiftdata.FindStatementById(conn, rs.Primary.ID) + output, err := tfredshiftdata.FindStatementByID(conn, rs.Primary.ID) if err != nil { return err } - *v = *out + *v = *output return nil } diff --git a/internal/service/redshiftdata/status.go b/internal/service/redshiftdata/status.go index 852b8dc5b47..ae19f4f650b 100644 --- a/internal/service/redshiftdata/status.go +++ b/internal/service/redshiftdata/status.go @@ -9,7 +9,7 @@ import ( func statusStatement(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - output, err := FindStatementById(conn, id) + output, err := FindStatementByID(conn, id) if tfresource.NotFound(err) { return nil, "", nil diff --git a/internal/service/redshiftdata/wait.go b/internal/service/redshiftdata/wait.go index 686ca7491ff..8136b6e09d4 100644 --- a/internal/service/redshiftdata/wait.go +++ b/internal/service/redshiftdata/wait.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func waitStatementFinished(conn *redshiftdataapiservice.RedshiftDataAPIService, id string) (*redshiftdataapiservice.DescribeStatementOutput, error) { //nolint:unparam +func waitStatementFinished(conn *redshiftdataapiservice.RedshiftDataAPIService, id string, timeout time.Duration) (*redshiftdataapiservice.DescribeStatementOutput, error) { //nolint:unparam stateConf := &resource.StateChangeConf{ Pending: []string{ redshiftdataapiservice.StatusStringPicked, @@ -19,7 +19,7 @@ func waitStatementFinished(conn *redshiftdataapiservice.RedshiftDataAPIService, }, Target: []string{redshiftdataapiservice.StatusStringFinished}, Refresh: statusStatement(conn, id), - Timeout: 10 * time.Minute, + Timeout: timeout, MinTimeout: 10 * time.Second, Delay: 30 * time.Second, } From 88e16431ec0013368273593eace4d95b4d535659 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 1 Jun 2022 11:47:03 -0400 Subject: [PATCH 8/8] Fix golangci-lint error: 'directive '//nolint:unparam' is unused for linter "unparam" (nolintlint)'. --- internal/service/redshiftdata/wait.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/redshiftdata/wait.go b/internal/service/redshiftdata/wait.go index 8136b6e09d4..03f15d2df96 100644 --- a/internal/service/redshiftdata/wait.go +++ b/internal/service/redshiftdata/wait.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func waitStatementFinished(conn *redshiftdataapiservice.RedshiftDataAPIService, id string, timeout time.Duration) (*redshiftdataapiservice.DescribeStatementOutput, error) { //nolint:unparam +func waitStatementFinished(conn *redshiftdataapiservice.RedshiftDataAPIService, id string, timeout time.Duration) (*redshiftdataapiservice.DescribeStatementOutput, error) { stateConf := &resource.StateChangeConf{ Pending: []string{ redshiftdataapiservice.StatusStringPicked,