Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add price_performance_target param onto aws provider #40946

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/40915.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_redshiftserverless_workgroup: Add price_performance_target argument
```
27 changes: 27 additions & 0 deletions internal/service/redshiftserverless/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package redshiftserverless

const (
performanceTargetLevelLowCostValue = 1
performanceTargetLevelEconomicalValue = 25
performanceTargetLevelBalancedValue = 50
performanceTargetLevelResourcefulValue = 75
performanceTargetLevelHighPerformanceValue = 100
)

const (
performanceTargetLevelLowCost = "LOW_COST"
performanceTargetLevelEconomical = "ECONOMICAL"
performanceTargetLevelBalanced = "BALANCED"
performanceTargetLevelResourceful = "RESOURCEFUL"
performanceTargetLevelHighPerformance = "HIGH_PERFORMANCE"
)

func performanceTargetLevel_Values() []string {
return []string{
performanceTargetLevelLowCost,
performanceTargetLevelEconomical,
performanceTargetLevelBalanced,
performanceTargetLevelResourceful,
performanceTargetLevelHighPerformance,
}
}
103 changes: 103 additions & 0 deletions internal/service/redshiftserverless/workgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ func resourceWorkgroup() *schema.Resource {
Optional: true,
Computed: true,
},
"price_performance_target": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
names.AttrEnabled: {
Type: schema.TypeBool,
Required: true,
},
"level": {
Type: schema.TypeString,
Default: performanceTargetLevelBalanced,
Optional: true,
ValidateFunc: validation.StringInSlice(performanceTargetLevel_Values(), false),
},
},
},
},
"config_parameter": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -222,6 +242,14 @@ func resourceWorkgroupCreate(ctx context.Context, d *schema.ResourceData, meta i
input.BaseCapacity = aws.Int32(int32(v.(int)))
}

if v, ok := d.GetOk("price_performance_target"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.PricePerformanceTarget = expandPricePerformanceTarget(v.([]interface{}))
}

if input.BaseCapacity != nil && input.PricePerformanceTarget != nil && input.PricePerformanceTarget.Status == awstypes.PerformanceTargetStatusEnabled {
return sdkdiag.AppendErrorf(diags, "base_capacity cannot be set when price_performance_target.enabled is true")
}

if v, ok := d.GetOk("config_parameter"); ok && v.(*schema.Set).Len() > 0 {
input.ConfigParameters = expandConfigParameters(v.(*schema.Set).List())
}
Expand Down Expand Up @@ -283,6 +311,9 @@ func resourceWorkgroupRead(ctx context.Context, d *schema.ResourceData, meta int

d.Set(names.AttrARN, out.WorkgroupArn)
d.Set("base_capacity", out.BaseCapacity)
if err := d.Set("price_performance_target", flattenPricePerformanceTarget(out.PricePerformanceTarget)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting price_performance_target: %s", err)
}
if err := d.Set("config_parameter", flattenConfigParameters(out.ConfigParameters)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting config_parameter: %s", err)
}
Expand Down Expand Up @@ -376,6 +407,17 @@ func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta i
}
}

if d.HasChange("price_performance_target") {
input := &redshiftserverless.UpdateWorkgroupInput{
PricePerformanceTarget: expandPricePerformanceTarget(d.Get("price_performance_target").([]interface{})),
WorkgroupName: aws.String(d.Id()),
}

if err := updateWorkgroup(ctx, conn, input, d.Timeout(schema.TimeoutUpdate)); err != nil {
return sdkdiag.AppendFromErr(diags, err)
}
}

if d.HasChange("config_parameter") {
input := &redshiftserverless.UpdateWorkgroupInput{
ConfigParameters: expandConfigParameters(d.Get("config_parameter").(*schema.Set).List()),
Expand Down Expand Up @@ -582,6 +624,67 @@ func waitWorkgroupDeleted(ctx context.Context, conn *redshiftserverless.Client,
return nil, err
}

func expandPricePerformanceTarget(list []interface{}) *awstypes.PerformanceTarget {
if len(list) == 0 {
return nil
}

tfMap := list[0].(map[string]interface{})
apiObject := &awstypes.PerformanceTarget{}
// bool is a nicer way to represent the enabled/disabled state but the API expects
// a string enumeration
if enabled, ok := tfMap[names.AttrEnabled].(bool); ok {
if enabled {
apiObject.Status = awstypes.PerformanceTargetStatusEnabled
} else {
apiObject.Status = awstypes.PerformanceTargetStatusDisabled
}
}
// The target price performance level for the workgroup. Valid values include 1,
// 25, 50, 75, and 100. These correspond to the price performance levels LOW_COST,
// ECONOMICAL, BALANCED, RESOURCEFUL, and HIGH_PERFORMANCE.
if level, ok := tfMap["level"].(string); ok {
switch level {
case performanceTargetLevelLowCost:
apiObject.Level = aws.Int32(int32(performanceTargetLevelLowCostValue))
case performanceTargetLevelEconomical:
apiObject.Level = aws.Int32(int32(performanceTargetLevelEconomicalValue))
case performanceTargetLevelBalanced:
apiObject.Level = aws.Int32(int32(performanceTargetLevelBalancedValue))
case performanceTargetLevelResourceful:
apiObject.Level = aws.Int32(int32(performanceTargetLevelResourcefulValue))
case performanceTargetLevelHighPerformance:
apiObject.Level = aws.Int32(int32(performanceTargetLevelHighPerformanceValue))
}
}

return apiObject
}

func flattenPricePerformanceTarget(apiObject *awstypes.PerformanceTarget) []interface{} {
if apiObject == nil {
return []interface{}{}
}

tfMap := map[string]interface{}{}

tfMap[names.AttrEnabled] = apiObject.Status == awstypes.PerformanceTargetStatusEnabled
switch aws.ToInt32(apiObject.Level) {
case performanceTargetLevelLowCostValue:
tfMap["level"] = performanceTargetLevelLowCost
case performanceTargetLevelEconomicalValue:
tfMap["level"] = performanceTargetLevelEconomical
case performanceTargetLevelBalancedValue:
tfMap["level"] = performanceTargetLevelBalanced
case performanceTargetLevelResourcefulValue:
tfMap["level"] = performanceTargetLevelResourceful
case performanceTargetLevelHighPerformanceValue:
tfMap["level"] = performanceTargetLevelHighPerformance
}

return []interface{}{tfMap}
}

func expandConfigParameter(tfMap map[string]interface{}) awstypes.ConfigParameter {
apiObject := awstypes.ConfigParameter{}

Expand Down
68 changes: 68 additions & 0 deletions internal/service/redshiftserverless/workgroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,39 @@ func TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible(
})
}

// Tests the logic involved in validating/updating 'base_capacity' and 'price_performance_target'.
func TestAccRedshiftServerlessWorkgroup_pricePerformanceTarget(t *testing.T) {
ctx := acctest.Context(t)
resourceName := "aws_redshiftserverless_workgroup.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.RedshiftServerlessServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckWorkgroupDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccWorkgroupConfig_pricePerformanceTargetAndBaseCapacity(rName, true),
ExpectError: regexache.MustCompile("base_capacity cannot be set when price_performance_target.enabled is true"),
},
{
Config: testAccWorkgroupConfig_pricePerformanceTargetAndBaseCapacity(rName, false),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "base_capacity", "128"),
resource.TestCheckResourceAttr(resourceName, names.AttrMaxCapacity, "0"),
),
},
{
Config: testAccWorkgroupConfig_pricePerformanceTarget(rName, "LOW_COST"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "price_performance_target.0.enabled", acctest.CtTrue),
resource.TestCheckResourceAttr(resourceName, "price_performance_target.0.level", "LOW_COST"),
),
},
},
})
}

func TestAccRedshiftServerlessWorkgroup_configParameters(t *testing.T) {
ctx := acctest.Context(t)
resourceName := "aws_redshiftserverless_workgroup.test"
Expand Down Expand Up @@ -407,6 +440,41 @@ resource "aws_redshiftserverless_workgroup" "test" {
`, rName, baseCapacity)
}

func testAccWorkgroupConfig_pricePerformanceTarget(rName string, targetLevel string) string {
return fmt.Sprintf(`
resource "aws_redshiftserverless_namespace" "test" {
namespace_name = %[1]q
}

resource "aws_redshiftserverless_workgroup" "test" {
namespace_name = aws_redshiftserverless_namespace.test.namespace_name
workgroup_name = %[1]q
price_performance_target {
enabled = true
level = %[2]q
}
}

`, rName, targetLevel)
}

func testAccWorkgroupConfig_pricePerformanceTargetAndBaseCapacity(rName string, pricePerformanceEnabled bool) string {
return fmt.Sprintf(`
resource "aws_redshiftserverless_namespace" "test" {
namespace_name = %[1]q
}

resource "aws_redshiftserverless_workgroup" "test" {
namespace_name = aws_redshiftserverless_namespace.test.namespace_name
workgroup_name = %[1]q
base_capacity = 128
price_performance_target {
enabled = %[2]t
}
}
`, rName, pricePerformanceEnabled)
}

func testAccWorkgroupConfig_configParameters(rName, maxQueryExecutionTime string) string {
return fmt.Sprintf(`
resource "aws_redshiftserverless_namespace" "test" {
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/redshiftserverless_workgroup.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ The following arguments are required:
The following arguments are optional:

* `base_capacity` - (Optional) The base data warehouse capacity of the workgroup in Redshift Processing Units (RPUs).
* `price_performance_target` - (Optional) Price-performance scaling for the workgroup. See `Price Performance Target` below.
* `config_parameter` - (Optional) An array of parameters to set for more control over a serverless database. See `Config Parameter` below.
* `enhanced_vpc_routing` - (Optional) The value that specifies whether to turn on enhanced virtual private cloud (VPC) routing, which forces Amazon Redshift Serverless to route traffic through your VPC instead of over the internet.
* `max_capacity` - (Optional) The maximum data-warehouse capacity Amazon Redshift Serverless uses to serve queries, specified in Redshift Processing Units (RPUs).
Expand All @@ -38,6 +39,11 @@ The following arguments are optional:
* `subnet_ids` - (Optional) An array of VPC subnet IDs to associate with the workgroup. When set, must contain at least three subnets spanning three Availability Zones. A minimum number of IP addresses is required and scales with the Base Capacity. For more information, see the following [AWS document](https://docs.aws.amazon.com/redshift/latest/mgmt/serverless-known-issues.html).
* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

### Price Performance Target

* `enabled` - (Required) Whether to enable price-performance scaling.
* `level` - (Required) The price-performance scaling level. Valid values are `LOW_COST`, `ECONOMICAL`, `BALANCED`, `RESOURCEFUL`, and `HIGH_PERFORMANCE`.

### Config Parameter

* `parameter_key` - (Required) The key of the parameter. The options are `auto_mv`, `datestyle`, `enable_case_sensitive_identifier`, `enable_user_activity_logging`, `query_group`, `search_path`, `require_ssl`, `use_fips_ssl`, and [query monitoring metrics](https://docs.aws.amazon.com/redshift/latest/dg/cm-c-wlm-query-monitoring-rules.html#cm-c-wlm-query-monitoring-metrics-serverless) that let you define performance boundaries: `max_query_cpu_time`, `max_query_blocks_read`, `max_scan_row_count`, `max_query_execution_time`, `max_query_queue_time`, `max_query_cpu_usage_percent`, `max_query_temp_blocks_to_disk`, `max_join_row_count` and `max_nested_loop_join_row_count`.
Expand Down
Loading