From 6329f5456cb0d7f5b51aa940d6587655193d3aaf Mon Sep 17 00:00:00 2001 From: Jungseok Lee Date: Mon, 19 Dec 2022 04:43:38 +0000 Subject: [PATCH 01/13] r/aws_autoscaling_policy: Support metric math for target tracking policy This patch supports metric math for EC2 Auto Scaling target tracking policy, which was released on Dec 8, 2022. --- .changelog/28560.txt | 3 + internal/service/autoscaling/policy.go | 277 +++++++++++++++--- internal/service/autoscaling/policy_test.go | 86 ++++++ .../docs/r/autoscaling_policy.html.markdown | 104 ++++++- 4 files changed, 422 insertions(+), 48 deletions(-) create mode 100644 .changelog/28560.txt diff --git a/.changelog/28560.txt b/.changelog/28560.txt new file mode 100644 index 00000000000..b73508b6cd2 --- /dev/null +++ b/.changelog/28560.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_autoscaling_policy: Support metric math for target tracking +``` diff --git a/internal/service/autoscaling/policy.go b/internal/service/autoscaling/policy.go index 23ee71de0b4..0b05a2dd17e 100644 --- a/internal/service/autoscaling/policy.go +++ b/internal/service/autoscaling/policy.go @@ -259,9 +259,90 @@ func ResourcePolicy() *schema.Resource { ConflictsWith: []string{"target_tracking_configuration.0.predefined_metric_specification"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "metrics": { + Type: schema.TypeSet, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metric_dimension", "target_tracking_configuration.0.customized_metric_specification.0.metric_name", "target_tracking_configuration.0.customized_metric_specification.0.namespace", "target_tracking_configuration.0.customized_metric_specification.0.statistic", "target_tracking_configuration.0.customized_metric_specification.0.unit"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "expression": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 2047), + }, + "id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + "label": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 2047), + }, + "metric_stat": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimensions": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Required: true, + }, + "namespace": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "stat": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 100), + }, + "unit": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "return_data": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + }, + }, + }, "metric_dimension": { - Type: schema.TypeList, - Optional: true, + Type: schema.TypeList, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -276,20 +357,24 @@ func ResourcePolicy() *schema.Resource { }, }, "metric_name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "namespace": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "statistic": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "unit": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, }, }, @@ -709,32 +794,89 @@ func expandTargetTrackingConfiguration(configs []interface{}) *autoscaling.Targe } if v, ok := config["customized_metric_specification"]; ok && len(v.([]interface{})) > 0 { spec := v.([]interface{})[0].(map[string]interface{}) - customSpec := &autoscaling.CustomizedMetricSpecification{ - Namespace: aws.String(spec["namespace"].(string)), - MetricName: aws.String(spec["metric_name"].(string)), - Statistic: aws.String(spec["statistic"].(string)), - } - if val, ok := spec["unit"]; ok && len(val.(string)) > 0 { - customSpec.Unit = aws.String(val.(string)) - } - if val, ok := spec["metric_dimension"]; ok { - dims := val.([]interface{}) - metDimList := make([]*autoscaling.MetricDimension, len(dims)) - for i := range metDimList { - dim := dims[i].(map[string]interface{}) - md := &autoscaling.MetricDimension{ - Name: aws.String(dim["name"].(string)), - Value: aws.String(dim["value"].(string)), + customSpec := &autoscaling.CustomizedMetricSpecification{} + if val, ok := spec["metrics"].(*schema.Set); ok && val.Len() > 0 { + customSpec.Metrics = expandTargetTrackingMetricDataQueries(val.List()) + } else { + customSpec.Namespace = aws.String(spec["namespace"].(string)) + customSpec.MetricName = aws.String(spec["metric_name"].(string)) + customSpec.Statistic = aws.String(spec["statistic"].(string)) + if val, ok := spec["unit"]; ok && len(val.(string)) > 0 { + customSpec.Unit = aws.String(val.(string)) + } + if val, ok := spec["metric_dimension"]; ok { + dims := val.([]interface{}) + metDimList := make([]*autoscaling.MetricDimension, len(dims)) + for i := range metDimList { + dim := dims[i].(map[string]interface{}) + md := &autoscaling.MetricDimension{ + Name: aws.String(dim["name"].(string)), + Value: aws.String(dim["value"].(string)), + } + metDimList[i] = md } - metDimList[i] = md + customSpec.Dimensions = metDimList } - customSpec.Dimensions = metDimList } result.CustomizedMetricSpecification = customSpec } return result } +func expandTargetTrackingMetricDataQueries(metricDataQuerySlices []interface{}) []*autoscaling.TargetTrackingMetricDataQuery { + if metricDataQuerySlices == nil || len(metricDataQuerySlices) < 1 { + return nil + } + metricDataQueries := make([]*autoscaling.TargetTrackingMetricDataQuery, len(metricDataQuerySlices)) + + for i := range metricDataQueries { + metricDataQueryFlat := metricDataQuerySlices[i].(map[string]interface{}) + metricDataQuery := &autoscaling.TargetTrackingMetricDataQuery{ + Id: aws.String(metricDataQueryFlat["id"].(string)), + } + if val, ok := metricDataQueryFlat["metric_stat"]; ok && len(val.([]interface{})) > 0 { + metricStatSpec := val.([]interface{})[0].(map[string]interface{}) + metricSpec := metricStatSpec["metric"].([]interface{})[0].(map[string]interface{}) + metric := &autoscaling.Metric{ + MetricName: aws.String(metricSpec["metric_name"].(string)), + Namespace: aws.String(metricSpec["namespace"].(string)), + } + if v, ok := metricSpec["dimensions"]; ok { + dims := v.(*schema.Set).List() + dimList := make([]*autoscaling.MetricDimension, len(dims)) + for i := range dimList { + dim := dims[i].(map[string]interface{}) + md := &autoscaling.MetricDimension{ + Name: aws.String(dim["name"].(string)), + Value: aws.String(dim["value"].(string)), + } + dimList[i] = md + } + metric.Dimensions = dimList + } + metricStat := &autoscaling.TargetTrackingMetricStat{ + Metric: metric, + Stat: aws.String(metricStatSpec["stat"].(string)), + } + if v, ok := metricStatSpec["unit"]; ok && len(v.(string)) > 0 { + metricStat.Unit = aws.String(v.(string)) + } + metricDataQuery.MetricStat = metricStat + } + if val, ok := metricDataQueryFlat["expression"]; ok && val.(string) != "" { + metricDataQuery.Expression = aws.String(val.(string)) + } + if val, ok := metricDataQueryFlat["label"]; ok && val.(string) != "" { + metricDataQuery.Label = aws.String(val.(string)) + } + if val, ok := metricDataQueryFlat["return_data"]; ok { + metricDataQuery.ReturnData = aws.Bool(val.(bool)) + } + metricDataQueries[i] = metricDataQuery + } + return metricDataQueries +} + func expandPredictiveScalingConfig(predictiveScalingConfigSlice []interface{}) *autoscaling.PredictiveScalingConfiguration { if predictiveScalingConfigSlice == nil || len(predictiveScalingConfigSlice) < 1 { return nil @@ -912,28 +1054,77 @@ func flattenTargetTrackingConfiguration(config *autoscaling.TargetTrackingConfig } if config.CustomizedMetricSpecification != nil { spec := map[string]interface{}{} - spec["metric_name"] = aws.StringValue(config.CustomizedMetricSpecification.MetricName) - spec["namespace"] = aws.StringValue(config.CustomizedMetricSpecification.Namespace) - spec["statistic"] = aws.StringValue(config.CustomizedMetricSpecification.Statistic) - if config.CustomizedMetricSpecification.Unit != nil { - spec["unit"] = aws.StringValue(config.CustomizedMetricSpecification.Unit) - } - if config.CustomizedMetricSpecification.Dimensions != nil { - dimSpec := make([]interface{}, len(config.CustomizedMetricSpecification.Dimensions)) - for i := range dimSpec { - dim := map[string]interface{}{} - rawDim := config.CustomizedMetricSpecification.Dimensions[i] - dim["name"] = aws.StringValue(rawDim.Name) - dim["value"] = aws.StringValue(rawDim.Value) - dimSpec[i] = dim + if config.CustomizedMetricSpecification.Metrics != nil { + spec["metrics"] = flattenTargetTrackingMetricDataQueries(config.CustomizedMetricSpecification.Metrics) + } else { + spec["metric_name"] = aws.StringValue(config.CustomizedMetricSpecification.MetricName) + spec["namespace"] = aws.StringValue(config.CustomizedMetricSpecification.Namespace) + spec["statistic"] = aws.StringValue(config.CustomizedMetricSpecification.Statistic) + if config.CustomizedMetricSpecification.Unit != nil { + spec["unit"] = aws.StringValue(config.CustomizedMetricSpecification.Unit) + } + if config.CustomizedMetricSpecification.Dimensions != nil { + dimSpec := make([]interface{}, len(config.CustomizedMetricSpecification.Dimensions)) + for i := range dimSpec { + dim := map[string]interface{}{} + rawDim := config.CustomizedMetricSpecification.Dimensions[i] + dim["name"] = aws.StringValue(rawDim.Name) + dim["value"] = aws.StringValue(rawDim.Value) + dimSpec[i] = dim + } + spec["metric_dimension"] = dimSpec } - spec["metric_dimension"] = dimSpec } result["customized_metric_specification"] = []map[string]interface{}{spec} } return []interface{}{result} } +func flattenTargetTrackingMetricDataQueries(metricDataQueries []*autoscaling.TargetTrackingMetricDataQuery) []interface{} { + metricDataQueriesSpec := make([]interface{}, len(metricDataQueries)) + for i := range metricDataQueriesSpec { + metricDataQuery := map[string]interface{}{} + rawMetricDataQuery := metricDataQueries[i] + metricDataQuery["id"] = aws.StringValue(rawMetricDataQuery.Id) + if rawMetricDataQuery.Expression != nil { + metricDataQuery["expression"] = aws.StringValue(rawMetricDataQuery.Expression) + } + if rawMetricDataQuery.Label != nil { + metricDataQuery["label"] = aws.StringValue(rawMetricDataQuery.Label) + } + if rawMetricDataQuery.MetricStat != nil { + metricStatSpec := map[string]interface{}{} + rawMetricStat := rawMetricDataQuery.MetricStat + rawMetric := rawMetricStat.Metric + metricSpec := map[string]interface{}{} + if rawMetric.Dimensions != nil { + dimSpec := make([]interface{}, len(rawMetric.Dimensions)) + for i := range dimSpec { + dim := map[string]interface{}{} + rawDim := rawMetric.Dimensions[i] + dim["name"] = aws.StringValue(rawDim.Name) + dim["value"] = aws.StringValue(rawDim.Value) + dimSpec[i] = dim + } + metricSpec["dimensions"] = dimSpec + } + metricSpec["metric_name"] = aws.StringValue(rawMetric.MetricName) + metricSpec["namespace"] = aws.StringValue(rawMetric.Namespace) + metricStatSpec["metric"] = []map[string]interface{}{metricSpec} + metricStatSpec["stat"] = aws.StringValue(rawMetricStat.Stat) + if rawMetricStat.Unit != nil { + metricStatSpec["unit"] = aws.StringValue(rawMetricStat.Unit) + } + metricDataQuery["metric_stat"] = []map[string]interface{}{metricStatSpec} + } + if rawMetricDataQuery.ReturnData != nil { + metricDataQuery["return_data"] = aws.BoolValue(rawMetricDataQuery.ReturnData) + } + metricDataQueriesSpec[i] = metricDataQuery + } + return metricDataQueriesSpec +} + func flattenPredictiveScalingConfig(predictiveScalingConfig *autoscaling.PredictiveScalingConfiguration) []map[string]interface{} { predictiveScalingConfigFlat := map[string]interface{}{} if predictiveScalingConfig == nil { diff --git a/internal/service/autoscaling/policy_test.go b/internal/service/autoscaling/policy_test.go index 4b61bbffcdf..c1647612947 100644 --- a/internal/service/autoscaling/policy_test.go +++ b/internal/service/autoscaling/policy_test.go @@ -391,6 +391,33 @@ func TestAccAutoScalingPolicy_TargetTrack_custom(t *testing.T) { }) } +func TestAccAutoScalingPolicy_TargetTrack_metricMath(t *testing.T) { + var v autoscaling.ScalingPolicy + resourceName := "aws_autoscaling_policy.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, autoscaling.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccPolicyConfig_targetTrackingMetricMath(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckScalingPolicyExists(resourceName, &v), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccPolicyImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAutoScalingPolicy_zeroValue(t *testing.T) { var v1, v2 autoscaling.ScalingPolicy rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -798,6 +825,65 @@ resource "aws_autoscaling_policy" "test" { `, rName)) } +func testAccPolicyConfig_targetTrackingMetricMath(rName string) string { + return acctest.ConfigCompose(testAccPolicyConfigBase(rName), fmt.Sprintf(` +resource "aws_autoscaling_policy" "test" { + name = "%[1]s-tracking" + policy_type = "TargetTrackingScaling" + autoscaling_group_name = aws_autoscaling_group.test.name + + target_tracking_configuration { + customized_metric_specification { + metrics { + id = "m1" + expression = "TIME_SERIES(20)" + return_data = false + } + metrics { + id = "m2" + metric_stat { + metric { + namespace = "foo" + metric_name = "bar" + } + unit = "Percent" + stat = "Sum" + } + return_data = false + } + metrics { + id = "m3" + metric_stat { + metric { + namespace = "foo" + metric_name = "bar" + dimensions { + name = "x" + value = "y" + } + dimensions { + name = "y" + value = "x" + } + } + unit = "Percent" + stat = "Sum" + } + return_data = false + } + metrics { + id = "e1" + expression = "m1 + m2 + m3" + return_data = true + } + } + + target_value = 12.3 + } +} +`, rName)) +} + func testAccPolicyConfig_zeroValue(rName string) string { return acctest.ConfigCompose(testAccPolicyConfigBase(rName), fmt.Sprintf(` resource "aws_autoscaling_policy" "test_simple" { diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index cd094f371d9..3c2cc0c9649 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -41,6 +41,59 @@ resource "aws_autoscaling_group" "bar" { } ``` +### Create target tarcking scaling policy using metric math + +```terraform +resource "aws_autoscaling_policy" "example" { + autoscaling_group_name = "my-test-asg" + name = "foo" + policy_type = "TargetTrackingScaling" + target_tracking_configuration { + target_value = 100 + customized_metric_specification { + metrics { + label = "Get the queue size (the number of messages waiting to be processed)" + id = "m1" + metric_stat { + metric { + namespace = "AWS/SQS" + metric_name = "ApproximateNumberOfMessagesVisible" + dimensions { + name = "QueueName" + value = "my-queue" + } + } + stat = "Sum" + } + return_data = false + } + metrics { + label = "Get the group size (the number of InService instances)" + id = "m2" + metric_stat { + metric { + namespace = "AWS/AutoScaling" + metric_name = "GroupInServiceInstances" + dimensions { + name = "AutoScalingGroupName" + value = "my-asg" + } + } + stat = "Average" + } + return_data = false + } + metrics { + label = "Calculate the backlog per instance" + id = "e1" + expression = "m1 / m2" + return_data = true + } + } + } +} +``` + ### Create predictive scaling policy using customized metrics ```terraform @@ -224,10 +277,11 @@ The following arguments are supported: The following arguments are supported: * `metric_dimension` - (Optional) Dimensions of the metric. -* `metric_name` - (Required) Name of the metric. -* `namespace` - (Required) Namespace of the metric. -* `statistic` - (Required) Statistic of the metric. +* `metric_name` - (Optional) Name of the metric. +* `namespace` - (Optional) Namespace of the metric. +* `statistic` - (Optional) Statistic of the metric. * `unit` - (Optional) Unit of the metric. +* `metrics` - (Optional) Metrics to include, as a metric data query. #### metric_dimension @@ -236,6 +290,39 @@ The following arguments are supported: * `name` - (Required) Name of the dimension. * `value` - (Required) Value of the dimension. +#### metrics + +The following arguments are supported: + +* `expression` - (Optional) Math expression used on the returned metric. You must specify either `expression` or `metric_stat`, but not both. +* `id` - (Required) Short name for the metric used in target tracking scaling policy. +* `label` - (Optional) Human-readable label for this metric or expression. +* `metric_stat` - (Optional) Structure that defines CloudWatch metric to be used in target tracking scaling policy. You must specify either `expression` or `metric_stat`, but not both. +* `return_data` - (Optional) Boolean that indicates whether to return the timestamps and raw data values of this metric, the default is true + +##### metric_stat + +The following arguments are supported: + +* `metric` - (Required) Structure that defines the CloudWatch metric to return, including the metric name, namespace, and dimensions. +* `stat` - (Required) Statistic of the metrics to return. +* `unit` - (Optional) Unit of the metrics to return. + +##### metric + +The following arguments are supported: + +* `dimensions` - (Optional) Dimensions of the metric. +* `metric_name` - (Required) Name of the metric. +* `namespace` - (Required) Namespace of the metric. + +###### dimensions + +The following arguments are supported: + +* `name` - (Required) Name of the dimension. +* `value` - (Required) Value of the dimension. + ### predictive_scaling_configuration The following arguments are supported: @@ -279,30 +366,35 @@ The following arguments are supported: * `resource_label` - (Required) Label that uniquely identifies a specific Application Load Balancer target group from which to determine the request count served by your Auto Scaling group. ##### customized_scaling_metric_specification + The following arguments are supported: * `metric_data_queries` - (Required) List of up to 10 structures that defines custom scaling metric in predictive scaling policy ##### customized_load_metric_specification + The following arguments are supported: * `metric_data_queries` - (Required) List of up to 10 structures that defines custom load metric in predictive scaling policy ##### customized_capacity_metric_specification + The following arguments are supported: * `metric_data_queries` - (Required) List of up to 10 structures that defines custom capacity metric in predictive scaling policy ##### metric_data_queries + The following arguments are supported: * `expression` - (Optional) Math expression used on the returned metric. You must specify either `expression` or `metric_stat`, but not both. * `id` - (Required) Short name for the metric used in predictive scaling policy. -* `metric_stat` - (Optional) Structure that defines CloudWatch metric to be used in predictive scaling policy. You must specify either `expression` or `metric_stat`, but not both. * `label` - (Optional) Human-readable label for this metric or expression. -* `return_data` - (Optional) Boolean that indicates whether to return the timestamps and raw data values of this metric, the default it true +* `metric_stat` - (Optional) Structure that defines CloudWatch metric to be used in predictive scaling policy. You must specify either `expression` or `metric_stat`, but not both. +* `return_data` - (Optional) Boolean that indicates whether to return the timestamps and raw data values of this metric, the default is true ##### metric_stat + The following arguments are supported: * `metric` - (Required) Structure that defines the CloudWatch metric to return, including the metric name, namespace, and dimensions. @@ -310,6 +402,7 @@ The following arguments are supported: * `unit` - (Optional) Unit of the metrics to return. ##### metric + The following arguments are supported: * `dimensions` - (Optional) Dimensions of the metric. @@ -317,6 +410,7 @@ The following arguments are supported: * `namespace` - (Required) Namespace of the metric. ##### dimensions + The following arguments are supported: * `name` - (Required) Name of the dimension. From 803458152241579d97c242ed11696fdfe469fb35 Mon Sep 17 00:00:00 2001 From: Mehmet Gungoren Date: Sat, 28 Jan 2023 04:25:19 +0300 Subject: [PATCH 02/13] implement metrics of target tracking policy customizes metric specification Signed-off-by: Mehmet Gungoren --- internal/service/autoscaling/policy.go | 195 +++++++++++++++--- internal/service/autoscaling/policy_test.go | 104 ++++++++++ .../docs/r/autoscaling_policy.html.markdown | 56 +++++ 3 files changed, 328 insertions(+), 27 deletions(-) diff --git a/internal/service/autoscaling/policy.go b/internal/service/autoscaling/policy.go index ff4ad34b30c..27578addad4 100644 --- a/internal/service/autoscaling/policy.go +++ b/internal/service/autoscaling/policy.go @@ -262,6 +262,19 @@ func ResourcePolicy() *schema.Resource { ConflictsWith: []string{"target_tracking_configuration.0.predefined_metric_specification"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "metrics": func() *schema.Schema { + schema := customizedMetricDataQuerySchema() + schema.ConflictsWith = []string{ + "target_tracking_configuration.0.customized_metric_specification.0.metric_dimension", + "target_tracking_configuration.0.customized_metric_specification.0.metric_name", + "target_tracking_configuration.0.customized_metric_specification.0.namespace", + "target_tracking_configuration.0.customized_metric_specification.0.statistic", + "target_tracking_configuration.0.customized_metric_specification.0.unit", + } + schema.Required = false + schema.Optional = true + return schema + }(), "metric_dimension": { Type: schema.TypeList, Optional: true, @@ -279,16 +292,19 @@ func ResourcePolicy() *schema.Resource { }, }, "metric_name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "namespace": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "statistic": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "unit": { Type: schema.TypeString, @@ -714,10 +730,16 @@ func expandTargetTrackingConfiguration(configs []interface{}) *autoscaling.Targe } if v, ok := config["customized_metric_specification"]; ok && len(v.([]interface{})) > 0 { spec := v.([]interface{})[0].(map[string]interface{}) - customSpec := &autoscaling.CustomizedMetricSpecification{ - Namespace: aws.String(spec["namespace"].(string)), - MetricName: aws.String(spec["metric_name"].(string)), - Statistic: aws.String(spec["statistic"].(string)), + customSpec := &autoscaling.CustomizedMetricSpecification{} + + if val, ok := spec["namespace"]; ok && len(val.(string)) > 0 { + customSpec.Namespace = aws.String(val.(string)) + } + if val, ok := spec["metric_name"]; ok && len(val.(string)) > 0 { + customSpec.MetricName = aws.String(val.(string)) + } + if val, ok := spec["statistic"]; ok && len(val.(string)) > 0 { + customSpec.Statistic = aws.String(val.(string)) } if val, ok := spec["unit"]; ok && len(val.(string)) > 0 { customSpec.Unit = aws.String(val.(string)) @@ -735,11 +757,72 @@ func expandTargetTrackingConfiguration(configs []interface{}) *autoscaling.Targe } customSpec.Dimensions = metDimList } + if val, ok := spec["metrics"]; ok { + customSpec.Metrics = expandTargetTrackingMetricDataQuery(val.([]interface{})) + } result.CustomizedMetricSpecification = customSpec } return result } +func expandTargetTrackingMetricDataQuery(metrics []interface{}) []*autoscaling.TargetTrackingMetricDataQuery { + metDataQueryList := make([]*autoscaling.TargetTrackingMetricDataQuery, len(metrics)) + for i := range metDataQueryList { + metric := metrics[i].(map[string]interface{}) + md := &autoscaling.TargetTrackingMetricDataQuery{ + Id: aws.String(metric["id"].(string)), + ReturnData: aws.Bool(metric["return_data"].(bool)), + } + if val, ok := metric["expression"]; ok && len(val.(string)) > 0 { + md.Expression = aws.String(val.(string)) + } + if val, ok := metric["label"]; ok && len(val.(string)) > 0 { + md.Label = aws.String(val.(string)) + } + if val, ok := metric["metric_stat"]; ok { + md.MetricStat = expandTargetTrackingMetricStat(val.([]interface{})) + } + metDataQueryList[i] = md + } + return metDataQueryList +} + +func expandTargetTrackingMetricStat(stats []interface{}) *autoscaling.TargetTrackingMetricStat { + if len(stats) < 1 { + return nil + } + + stat := stats[0].(map[string]interface{}) + + metricSpec := stat["metric"].([]interface{})[0].(map[string]interface{}) + metric := &autoscaling.Metric{ + MetricName: aws.String(metricSpec["metric_name"].(string)), + Namespace: aws.String(metricSpec["namespace"].(string)), + } + if v, ok := metricSpec["dimensions"]; ok { + dims := v.(*schema.Set).List() + dimList := make([]*autoscaling.MetricDimension, len(dims)) + for i := range dimList { + dim := dims[i].(map[string]interface{}) + md := &autoscaling.MetricDimension{ + Name: aws.String(dim["name"].(string)), + Value: aws.String(dim["value"].(string)), + } + dimList[i] = md + } + metric.Dimensions = dimList + } + + metricStat := &autoscaling.TargetTrackingMetricStat{ + Metric: metric, + Stat: aws.String(stat["stat"].(string)), + } + if val, ok := stat["unit"]; ok && len(val.(string)) > 0 { + metricStat.Unit = aws.String(val.(string)) + } + return metricStat +} + func expandPredictiveScalingConfig(predictiveScalingConfigSlice []interface{}) *autoscaling.PredictiveScalingConfiguration { if predictiveScalingConfigSlice == nil || len(predictiveScalingConfigSlice) < 1 { return nil @@ -916,27 +999,85 @@ func flattenTargetTrackingConfiguration(config *autoscaling.TargetTrackingConfig result["predefined_metric_specification"] = []map[string]interface{}{spec} } if config.CustomizedMetricSpecification != nil { - spec := map[string]interface{}{} - spec["metric_name"] = aws.StringValue(config.CustomizedMetricSpecification.MetricName) - spec["namespace"] = aws.StringValue(config.CustomizedMetricSpecification.Namespace) - spec["statistic"] = aws.StringValue(config.CustomizedMetricSpecification.Statistic) - if config.CustomizedMetricSpecification.Unit != nil { - spec["unit"] = aws.StringValue(config.CustomizedMetricSpecification.Unit) + result["customized_metric_specification"] = flattenCustomizedMetricSpecification(config.CustomizedMetricSpecification) + } + return []interface{}{result} +} + +func flattenCustomizedMetricSpecification(customizedMetricSpecification *autoscaling.CustomizedMetricSpecification) []map[string]interface{} { + customizedMetricSpecificationFlat := map[string]interface{}{} + + if customizedMetricSpecification.MetricName != nil { + customizedMetricSpecificationFlat["metric_name"] = aws.StringValue(customizedMetricSpecification.MetricName) + } + if customizedMetricSpecification.Namespace != nil { + customizedMetricSpecificationFlat["namespace"] = aws.StringValue(customizedMetricSpecification.Namespace) + } + if customizedMetricSpecification.Statistic != nil { + customizedMetricSpecificationFlat["statistic"] = aws.StringValue(customizedMetricSpecification.Statistic) + } + if customizedMetricSpecification.Unit != nil { + customizedMetricSpecificationFlat["unit"] = aws.StringValue(customizedMetricSpecification.Unit) + } + if customizedMetricSpecification.Dimensions != nil { + dimSpec := make([]interface{}, len(customizedMetricSpecification.Dimensions)) + for i := range dimSpec { + dim := map[string]interface{}{} + rawDim := customizedMetricSpecification.Dimensions[i] + dim["name"] = aws.StringValue(rawDim.Name) + dim["value"] = aws.StringValue(rawDim.Value) + dimSpec[i] = dim } - if config.CustomizedMetricSpecification.Dimensions != nil { - dimSpec := make([]interface{}, len(config.CustomizedMetricSpecification.Dimensions)) - for i := range dimSpec { - dim := map[string]interface{}{} - rawDim := config.CustomizedMetricSpecification.Dimensions[i] - dim["name"] = aws.StringValue(rawDim.Name) - dim["value"] = aws.StringValue(rawDim.Value) - dimSpec[i] = dim + customizedMetricSpecificationFlat["metric_dimension"] = dimSpec + } + customizedMetricSpecificationFlat["metrics"] = flattenTargetTrackingMetricDataQueries(customizedMetricSpecification.Metrics) + + return []map[string]interface{}{customizedMetricSpecificationFlat} +} + +func flattenTargetTrackingMetricDataQueries(metricDataQueries []*autoscaling.TargetTrackingMetricDataQuery) []interface{} { + metricDataQueriesSpec := make([]interface{}, len(metricDataQueries)) + for i := range metricDataQueriesSpec { + metricDataQuery := map[string]interface{}{} + rawMetricDataQuery := metricDataQueries[i] + metricDataQuery["id"] = aws.StringValue(rawMetricDataQuery.Id) + if rawMetricDataQuery.Expression != nil { + metricDataQuery["expression"] = aws.StringValue(rawMetricDataQuery.Expression) + } + if rawMetricDataQuery.Label != nil { + metricDataQuery["label"] = aws.StringValue(rawMetricDataQuery.Label) + } + if rawMetricDataQuery.MetricStat != nil { + metricStatSpec := map[string]interface{}{} + rawMetricStat := rawMetricDataQuery.MetricStat + rawMetric := rawMetricStat.Metric + metricSpec := map[string]interface{}{} + if rawMetric.Dimensions != nil { + dimSpec := make([]interface{}, len(rawMetric.Dimensions)) + for i := range dimSpec { + dim := map[string]interface{}{} + rawDim := rawMetric.Dimensions[i] + dim["name"] = aws.StringValue(rawDim.Name) + dim["value"] = aws.StringValue(rawDim.Value) + dimSpec[i] = dim + } + metricSpec["dimensions"] = dimSpec } - spec["metric_dimension"] = dimSpec + metricSpec["metric_name"] = aws.StringValue(rawMetric.MetricName) + metricSpec["namespace"] = aws.StringValue(rawMetric.Namespace) + metricStatSpec["metric"] = []map[string]interface{}{metricSpec} + metricStatSpec["stat"] = aws.StringValue(rawMetricStat.Stat) + if rawMetricStat.Unit != nil { + metricStatSpec["unit"] = aws.StringValue(rawMetricStat.Unit) + } + metricDataQuery["metric_stat"] = []map[string]interface{}{metricStatSpec} + } + if rawMetricDataQuery.ReturnData != nil { + metricDataQuery["return_data"] = aws.BoolValue(rawMetricDataQuery.ReturnData) } - result["customized_metric_specification"] = []map[string]interface{}{spec} + metricDataQueriesSpec[i] = metricDataQuery } - return []interface{}{result} + return metricDataQueriesSpec } func flattenPredictiveScalingConfig(predictiveScalingConfig *autoscaling.PredictiveScalingConfiguration) []map[string]interface{} { diff --git a/internal/service/autoscaling/policy_test.go b/internal/service/autoscaling/policy_test.go index 063c77df587..e484b295e49 100644 --- a/internal/service/autoscaling/policy_test.go +++ b/internal/service/autoscaling/policy_test.go @@ -401,6 +401,53 @@ func TestAccAutoScalingPolicy_TargetTrack_custom(t *testing.T) { }) } +func TestAccAutoScalingPolicy_TargetTrack_advance(t *testing.T) { + ctx := acctest.Context(t) + var v autoscaling.ScalingPolicy + resourceName := "aws_autoscaling_policy.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, autoscaling.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyConfig_targetTrackingAdvance(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckScalingPolicyExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.id", "e1"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.expression", "m1 / m2"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.label", "e1 label"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.return_data", "true"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.id", "m1"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.metric.0.dimensions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.metric.0.metric_name", "metric_name_foo"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.metric.0.namespace", "namespace_foo"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.stat", "Sum"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.label", "m1 metric stat"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.return_data", "false"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.id", "m2"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.metric.0.dimensions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.metric.0.metric_name", "metric_name_bar"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.metric.0.namespace", "namespace_bar"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.stat", "Average"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.label", "m2 metric stat"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.return_data", "false"), + resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.target_value", "10"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccPolicyImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAutoScalingPolicy_zeroValue(t *testing.T) { ctx := acctest.Context(t) var v1, v2 autoscaling.ScalingPolicy @@ -811,6 +858,63 @@ resource "aws_autoscaling_policy" "test" { `, rName)) } +func testAccPolicyConfig_targetTrackingAdvance(rName string) string { + return acctest.ConfigCompose(testAccPolicyConfigBase(rName), fmt.Sprintf(` +resource "aws_autoscaling_policy" "test" { + name = "%[1]s-tracking" + policy_type = "TargetTrackingScaling" + autoscaling_group_name = aws_autoscaling_group.test.name + + target_tracking_configuration { + customized_metric_specification { + metrics { + id = "e1" + expression = "m1 / m2" + label = "e1 label" + return_data = true + } + + metrics { + id = "m1" + metric_stat { + metric { + namespace = "namespace_foo" + metric_name = "metric_name_foo" + dimensions { + name = "foo" + value = "bar" + } + } + stat = "Sum" + } + label = "m1 metric stat" + return_data = false + } + + metrics { + id = "m2" + metric_stat { + metric { + namespace = "namespace_bar" + metric_name = "metric_name_bar" + dimensions { + name = "foo" + value = "bar" + } + } + stat = "Average" + } + label = "m2 metric stat" + return_data = false + } + } + + target_value = 10 + } +} +`, rName)) +} + func testAccPolicyConfig_zeroValue(rName string) string { return acctest.ConfigCompose(testAccPolicyConfigBase(rName), fmt.Sprintf(` resource "aws_autoscaling_policy" "test_simple" { diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index aa29813d1fd..5f3b2da895c 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -119,6 +119,62 @@ resource "aws_autoscaling_policy" "example" { } ``` +### Create target tracking policy using customized metrics + +```terraform +resource "aws_autoscaling_policy" "example" { + autoscaling_group_name = "my-test-asg" + name = "foo" + policy_type = "PredictiveScaling" + target_tracking_configuration { + customized_metric_specification { + metrics { + id = "e1" + expression = "m1 / m2" + label = "Calculate the backlog per instance" + return_data = true + } + + metrics { + id = "m1" + metric_stat { + metric { + namespace = "AWS/SQS" + metric_name = "ApproximateNumberOfMessagesVisible" + dimensions { + name = "QueueName" + value = "my-queue" + } + } + stat = "Sum" + } + label = "Get the queue size (the number of messages waiting to be processed)" + return_data = false + } + + metrics { + id = "m2" + metric_stat { + metric { + namespace = "AWS/AutoScaling" + metric_name = "GroupInServiceInstances" + dimensions { + name = "AutoScalingGroupName" + value = "my-asg" + } + } + stat = "Average" + } + label = "Get the group size (the number of InService instances)" + return_data = false + } + } + + target_value = 10 + } +} +``` + ## Argument Reference * `name` - (Required) Name of the policy. From 06a5b57ba538b3998506fa9a7258160c7e052bf7 Mon Sep 17 00:00:00 2001 From: Mehmet Gungoren Date: Sat, 28 Jan 2023 04:34:22 +0300 Subject: [PATCH 03/13] linting Signed-off-by: Mehmet Gungoren --- internal/service/autoscaling/policy_test.go | 10 +++++----- website/docs/r/autoscaling_policy.html.markdown | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/service/autoscaling/policy_test.go b/internal/service/autoscaling/policy_test.go index e484b295e49..d771906ed13 100644 --- a/internal/service/autoscaling/policy_test.go +++ b/internal/service/autoscaling/policy_test.go @@ -868,9 +868,9 @@ resource "aws_autoscaling_policy" "test" { target_tracking_configuration { customized_metric_specification { metrics { - id = "e1" - expression = "m1 / m2" - label = "e1 label" + id = "e1" + expression = "m1 / m2" + label = "e1 label" return_data = true } @@ -887,7 +887,7 @@ resource "aws_autoscaling_policy" "test" { } stat = "Sum" } - label = "m1 metric stat" + label = "m1 metric stat" return_data = false } @@ -904,7 +904,7 @@ resource "aws_autoscaling_policy" "test" { } stat = "Average" } - label = "m2 metric stat" + label = "m2 metric stat" return_data = false } } diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index 5f3b2da895c..18425237e71 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -129,9 +129,9 @@ resource "aws_autoscaling_policy" "example" { target_tracking_configuration { customized_metric_specification { metrics { - id = "e1" - expression = "m1 / m2" - label = "Calculate the backlog per instance" + id = "e1" + expression = "m1 / m2" + label = "Calculate the backlog per instance" return_data = true } @@ -148,7 +148,7 @@ resource "aws_autoscaling_policy" "example" { } stat = "Sum" } - label = "Get the queue size (the number of messages waiting to be processed)" + label = "Get the queue size (the number of messages waiting to be processed)" return_data = false } @@ -165,7 +165,7 @@ resource "aws_autoscaling_policy" "example" { } stat = "Average" } - label = "Get the group size (the number of InService instances)" + label = "Get the group size (the number of InService instances)" return_data = false } } From 8417369d1d0c5d3120cf333bd9217d74db0665fb Mon Sep 17 00:00:00 2001 From: Mehmet Gungoren Date: Sat, 28 Jan 2023 12:52:04 +0300 Subject: [PATCH 04/13] re-run pipelines Signed-off-by: Mehmet Gungoren From f16ebde8b5afddc0cf3d58fad3c9d8f4046f420e Mon Sep 17 00:00:00 2001 From: Mehmet Gungoren Date: Sat, 28 Jan 2023 14:03:19 +0300 Subject: [PATCH 05/13] update autoscaling policy target tracking policy custom metric specification's metrics Signed-off-by: Mehmet Gungoren --- internal/service/autoscaling/policy.go | 22 ++++-------- .../docs/r/autoscaling_policy.html.markdown | 35 +++++++++++++++++-- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/internal/service/autoscaling/policy.go b/internal/service/autoscaling/policy.go index 27578addad4..4ed43f62e67 100644 --- a/internal/service/autoscaling/policy.go +++ b/internal/service/autoscaling/policy.go @@ -264,13 +264,6 @@ func ResourcePolicy() *schema.Resource { Schema: map[string]*schema.Schema{ "metrics": func() *schema.Schema { schema := customizedMetricDataQuerySchema() - schema.ConflictsWith = []string{ - "target_tracking_configuration.0.customized_metric_specification.0.metric_dimension", - "target_tracking_configuration.0.customized_metric_specification.0.metric_name", - "target_tracking_configuration.0.customized_metric_specification.0.namespace", - "target_tracking_configuration.0.customized_metric_specification.0.statistic", - "target_tracking_configuration.0.customized_metric_specification.0.unit", - } schema.Required = false schema.Optional = true return schema @@ -292,19 +285,16 @@ func ResourcePolicy() *schema.Resource { }, }, "metric_name": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Type: schema.TypeString, + Optional: true, }, "namespace": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Type: schema.TypeString, + Optional: true, }, "statistic": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Type: schema.TypeString, + Optional: true, }, "unit": { Type: schema.TypeString, diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index 18425237e71..fa2fba57fdb 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -269,11 +269,42 @@ The following arguments are supported: The following arguments are supported: +* `metrics` - (Optional) The metrics to include in the target tracking scaling policy, as a metric data query. This can include both raw metric and metric math expressions. * `metric_dimension` - (Optional) Dimensions of the metric. +* `metric_name` - (Optional) Name of the metric. +* `namespace` - (Optional) Namespace of the metric. +* `statistic` - (Optional) Statistic of the metric. +* `unit` - (Optional) Unit of the metric. + +#### metrics + +The following arguments are supported: + +* `expression` - (Optional) Math expression used on the returned metric. You must specify either `expression` or `metric_stat`, but not both. +* `id` - (Required) Short name for the metric used in target tracking scaling policy. +* `label` - (Optional) Human-readable label for this metric or expression. +* `metric_stat` - (Optional) Structure that defines CloudWatch metric to be used in target tracking scaling policy. You must specify either `expression` or `metric_stat`, but not both. +* `return_data` - (Optional) Boolean that indicates whether to return the timestamps and raw data values of this metric, the default it true + +##### metric_stat +The following arguments are supported: + +* `metric` - (Required) Structure that defines the CloudWatch metric to return, including the metric name, namespace, and dimensions. +* `stat` - (Required) Statistic of the metrics to return. +* `unit` - (Optional) Unit of the metrics to return. + +##### metric +The following arguments are supported: + +* `dimensions` - (Optional) Dimensions of the metric. * `metric_name` - (Required) Name of the metric. * `namespace` - (Required) Namespace of the metric. -* `statistic` - (Required) Statistic of the metric. -* `unit` - (Optional) Unit of the metric. + +##### dimensions +The following arguments are supported: + +* `name` - (Required) Name of the dimension. +* `value` - (Required) Value of the dimension. #### metric_dimension From d16dbddb9be1ce689c8079b4cec945d79c7c1955 Mon Sep 17 00:00:00 2001 From: Mehmet Gungoren Date: Sat, 28 Jan 2023 14:06:10 +0300 Subject: [PATCH 06/13] add 29148.txt changelog Signed-off-by: Mehmet Gungoren --- .changelog/29148.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/29148.txt diff --git a/.changelog/29148.txt b/.changelog/29148.txt new file mode 100644 index 00000000000..72f961861f1 --- /dev/null +++ b/.changelog/29148.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_autoscaling_policy: Add `metrics` argument to `target_tracking_configuration.customized_metric_specification` +``` \ No newline at end of file From 345204eb6807411a4ee4f94fb31d308158ae9740 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 13:54:49 -0500 Subject: [PATCH 07/13] Revert "add 29148.txt changelog" This reverts commit d16dbddb9be1ce689c8079b4cec945d79c7c1955. --- .changelog/29148.txt | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .changelog/29148.txt diff --git a/.changelog/29148.txt b/.changelog/29148.txt deleted file mode 100644 index 72f961861f1..00000000000 --- a/.changelog/29148.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:enhancement -resource/aws_autoscaling_policy: Add `metrics` argument to `target_tracking_configuration.customized_metric_specification` -``` \ No newline at end of file From 5063ddd6e79d52374f6cd491517d200b97f0a29c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 13:55:03 -0500 Subject: [PATCH 08/13] Revert "update autoscaling policy target tracking policy custom metric specification's metrics" This reverts commit f16ebde8b5afddc0cf3d58fad3c9d8f4046f420e. --- internal/service/autoscaling/policy.go | 22 ++++++++---- .../docs/r/autoscaling_policy.html.markdown | 35 ++----------------- 2 files changed, 18 insertions(+), 39 deletions(-) diff --git a/internal/service/autoscaling/policy.go b/internal/service/autoscaling/policy.go index 4ed43f62e67..27578addad4 100644 --- a/internal/service/autoscaling/policy.go +++ b/internal/service/autoscaling/policy.go @@ -264,6 +264,13 @@ func ResourcePolicy() *schema.Resource { Schema: map[string]*schema.Schema{ "metrics": func() *schema.Schema { schema := customizedMetricDataQuerySchema() + schema.ConflictsWith = []string{ + "target_tracking_configuration.0.customized_metric_specification.0.metric_dimension", + "target_tracking_configuration.0.customized_metric_specification.0.metric_name", + "target_tracking_configuration.0.customized_metric_specification.0.namespace", + "target_tracking_configuration.0.customized_metric_specification.0.statistic", + "target_tracking_configuration.0.customized_metric_specification.0.unit", + } schema.Required = false schema.Optional = true return schema @@ -285,16 +292,19 @@ func ResourcePolicy() *schema.Resource { }, }, "metric_name": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "namespace": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "statistic": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, }, "unit": { Type: schema.TypeString, diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index fa2fba57fdb..18425237e71 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -269,42 +269,11 @@ The following arguments are supported: The following arguments are supported: -* `metrics` - (Optional) The metrics to include in the target tracking scaling policy, as a metric data query. This can include both raw metric and metric math expressions. * `metric_dimension` - (Optional) Dimensions of the metric. -* `metric_name` - (Optional) Name of the metric. -* `namespace` - (Optional) Namespace of the metric. -* `statistic` - (Optional) Statistic of the metric. -* `unit` - (Optional) Unit of the metric. - -#### metrics - -The following arguments are supported: - -* `expression` - (Optional) Math expression used on the returned metric. You must specify either `expression` or `metric_stat`, but not both. -* `id` - (Required) Short name for the metric used in target tracking scaling policy. -* `label` - (Optional) Human-readable label for this metric or expression. -* `metric_stat` - (Optional) Structure that defines CloudWatch metric to be used in target tracking scaling policy. You must specify either `expression` or `metric_stat`, but not both. -* `return_data` - (Optional) Boolean that indicates whether to return the timestamps and raw data values of this metric, the default it true - -##### metric_stat -The following arguments are supported: - -* `metric` - (Required) Structure that defines the CloudWatch metric to return, including the metric name, namespace, and dimensions. -* `stat` - (Required) Statistic of the metrics to return. -* `unit` - (Optional) Unit of the metrics to return. - -##### metric -The following arguments are supported: - -* `dimensions` - (Optional) Dimensions of the metric. * `metric_name` - (Required) Name of the metric. * `namespace` - (Required) Namespace of the metric. - -##### dimensions -The following arguments are supported: - -* `name` - (Required) Name of the dimension. -* `value` - (Required) Value of the dimension. +* `statistic` - (Required) Statistic of the metric. +* `unit` - (Optional) Unit of the metric. #### metric_dimension From 4973d518e651fa092dd6e726568186029f640eae Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 13:55:17 -0500 Subject: [PATCH 09/13] Revert "linting" This reverts commit 06a5b57ba538b3998506fa9a7258160c7e052bf7. --- internal/service/autoscaling/policy_test.go | 10 +++++----- website/docs/r/autoscaling_policy.html.markdown | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/service/autoscaling/policy_test.go b/internal/service/autoscaling/policy_test.go index d771906ed13..e484b295e49 100644 --- a/internal/service/autoscaling/policy_test.go +++ b/internal/service/autoscaling/policy_test.go @@ -868,9 +868,9 @@ resource "aws_autoscaling_policy" "test" { target_tracking_configuration { customized_metric_specification { metrics { - id = "e1" - expression = "m1 / m2" - label = "e1 label" + id = "e1" + expression = "m1 / m2" + label = "e1 label" return_data = true } @@ -887,7 +887,7 @@ resource "aws_autoscaling_policy" "test" { } stat = "Sum" } - label = "m1 metric stat" + label = "m1 metric stat" return_data = false } @@ -904,7 +904,7 @@ resource "aws_autoscaling_policy" "test" { } stat = "Average" } - label = "m2 metric stat" + label = "m2 metric stat" return_data = false } } diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index 18425237e71..5f3b2da895c 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -129,9 +129,9 @@ resource "aws_autoscaling_policy" "example" { target_tracking_configuration { customized_metric_specification { metrics { - id = "e1" - expression = "m1 / m2" - label = "Calculate the backlog per instance" + id = "e1" + expression = "m1 / m2" + label = "Calculate the backlog per instance" return_data = true } @@ -148,7 +148,7 @@ resource "aws_autoscaling_policy" "example" { } stat = "Sum" } - label = "Get the queue size (the number of messages waiting to be processed)" + label = "Get the queue size (the number of messages waiting to be processed)" return_data = false } @@ -165,7 +165,7 @@ resource "aws_autoscaling_policy" "example" { } stat = "Average" } - label = "Get the group size (the number of InService instances)" + label = "Get the group size (the number of InService instances)" return_data = false } } From 41ee4508a74bf628dd60cb3acb409d4d0e698f7d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 13:55:27 -0500 Subject: [PATCH 10/13] Revert "implement metrics of target tracking policy customizes metric specification" This reverts commit 803458152241579d97c242ed11696fdfe469fb35. --- internal/service/autoscaling/policy.go | 195 +++--------------- internal/service/autoscaling/policy_test.go | 104 ---------- .../docs/r/autoscaling_policy.html.markdown | 56 ----- 3 files changed, 27 insertions(+), 328 deletions(-) diff --git a/internal/service/autoscaling/policy.go b/internal/service/autoscaling/policy.go index 27578addad4..ff4ad34b30c 100644 --- a/internal/service/autoscaling/policy.go +++ b/internal/service/autoscaling/policy.go @@ -262,19 +262,6 @@ func ResourcePolicy() *schema.Resource { ConflictsWith: []string{"target_tracking_configuration.0.predefined_metric_specification"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "metrics": func() *schema.Schema { - schema := customizedMetricDataQuerySchema() - schema.ConflictsWith = []string{ - "target_tracking_configuration.0.customized_metric_specification.0.metric_dimension", - "target_tracking_configuration.0.customized_metric_specification.0.metric_name", - "target_tracking_configuration.0.customized_metric_specification.0.namespace", - "target_tracking_configuration.0.customized_metric_specification.0.statistic", - "target_tracking_configuration.0.customized_metric_specification.0.unit", - } - schema.Required = false - schema.Optional = true - return schema - }(), "metric_dimension": { Type: schema.TypeList, Optional: true, @@ -292,19 +279,16 @@ func ResourcePolicy() *schema.Resource { }, }, "metric_name": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Type: schema.TypeString, + Required: true, }, "namespace": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Type: schema.TypeString, + Required: true, }, "statistic": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Type: schema.TypeString, + Required: true, }, "unit": { Type: schema.TypeString, @@ -730,16 +714,10 @@ func expandTargetTrackingConfiguration(configs []interface{}) *autoscaling.Targe } if v, ok := config["customized_metric_specification"]; ok && len(v.([]interface{})) > 0 { spec := v.([]interface{})[0].(map[string]interface{}) - customSpec := &autoscaling.CustomizedMetricSpecification{} - - if val, ok := spec["namespace"]; ok && len(val.(string)) > 0 { - customSpec.Namespace = aws.String(val.(string)) - } - if val, ok := spec["metric_name"]; ok && len(val.(string)) > 0 { - customSpec.MetricName = aws.String(val.(string)) - } - if val, ok := spec["statistic"]; ok && len(val.(string)) > 0 { - customSpec.Statistic = aws.String(val.(string)) + customSpec := &autoscaling.CustomizedMetricSpecification{ + Namespace: aws.String(spec["namespace"].(string)), + MetricName: aws.String(spec["metric_name"].(string)), + Statistic: aws.String(spec["statistic"].(string)), } if val, ok := spec["unit"]; ok && len(val.(string)) > 0 { customSpec.Unit = aws.String(val.(string)) @@ -757,72 +735,11 @@ func expandTargetTrackingConfiguration(configs []interface{}) *autoscaling.Targe } customSpec.Dimensions = metDimList } - if val, ok := spec["metrics"]; ok { - customSpec.Metrics = expandTargetTrackingMetricDataQuery(val.([]interface{})) - } result.CustomizedMetricSpecification = customSpec } return result } -func expandTargetTrackingMetricDataQuery(metrics []interface{}) []*autoscaling.TargetTrackingMetricDataQuery { - metDataQueryList := make([]*autoscaling.TargetTrackingMetricDataQuery, len(metrics)) - for i := range metDataQueryList { - metric := metrics[i].(map[string]interface{}) - md := &autoscaling.TargetTrackingMetricDataQuery{ - Id: aws.String(metric["id"].(string)), - ReturnData: aws.Bool(metric["return_data"].(bool)), - } - if val, ok := metric["expression"]; ok && len(val.(string)) > 0 { - md.Expression = aws.String(val.(string)) - } - if val, ok := metric["label"]; ok && len(val.(string)) > 0 { - md.Label = aws.String(val.(string)) - } - if val, ok := metric["metric_stat"]; ok { - md.MetricStat = expandTargetTrackingMetricStat(val.([]interface{})) - } - metDataQueryList[i] = md - } - return metDataQueryList -} - -func expandTargetTrackingMetricStat(stats []interface{}) *autoscaling.TargetTrackingMetricStat { - if len(stats) < 1 { - return nil - } - - stat := stats[0].(map[string]interface{}) - - metricSpec := stat["metric"].([]interface{})[0].(map[string]interface{}) - metric := &autoscaling.Metric{ - MetricName: aws.String(metricSpec["metric_name"].(string)), - Namespace: aws.String(metricSpec["namespace"].(string)), - } - if v, ok := metricSpec["dimensions"]; ok { - dims := v.(*schema.Set).List() - dimList := make([]*autoscaling.MetricDimension, len(dims)) - for i := range dimList { - dim := dims[i].(map[string]interface{}) - md := &autoscaling.MetricDimension{ - Name: aws.String(dim["name"].(string)), - Value: aws.String(dim["value"].(string)), - } - dimList[i] = md - } - metric.Dimensions = dimList - } - - metricStat := &autoscaling.TargetTrackingMetricStat{ - Metric: metric, - Stat: aws.String(stat["stat"].(string)), - } - if val, ok := stat["unit"]; ok && len(val.(string)) > 0 { - metricStat.Unit = aws.String(val.(string)) - } - return metricStat -} - func expandPredictiveScalingConfig(predictiveScalingConfigSlice []interface{}) *autoscaling.PredictiveScalingConfiguration { if predictiveScalingConfigSlice == nil || len(predictiveScalingConfigSlice) < 1 { return nil @@ -999,85 +916,27 @@ func flattenTargetTrackingConfiguration(config *autoscaling.TargetTrackingConfig result["predefined_metric_specification"] = []map[string]interface{}{spec} } if config.CustomizedMetricSpecification != nil { - result["customized_metric_specification"] = flattenCustomizedMetricSpecification(config.CustomizedMetricSpecification) - } - return []interface{}{result} -} - -func flattenCustomizedMetricSpecification(customizedMetricSpecification *autoscaling.CustomizedMetricSpecification) []map[string]interface{} { - customizedMetricSpecificationFlat := map[string]interface{}{} - - if customizedMetricSpecification.MetricName != nil { - customizedMetricSpecificationFlat["metric_name"] = aws.StringValue(customizedMetricSpecification.MetricName) - } - if customizedMetricSpecification.Namespace != nil { - customizedMetricSpecificationFlat["namespace"] = aws.StringValue(customizedMetricSpecification.Namespace) - } - if customizedMetricSpecification.Statistic != nil { - customizedMetricSpecificationFlat["statistic"] = aws.StringValue(customizedMetricSpecification.Statistic) - } - if customizedMetricSpecification.Unit != nil { - customizedMetricSpecificationFlat["unit"] = aws.StringValue(customizedMetricSpecification.Unit) - } - if customizedMetricSpecification.Dimensions != nil { - dimSpec := make([]interface{}, len(customizedMetricSpecification.Dimensions)) - for i := range dimSpec { - dim := map[string]interface{}{} - rawDim := customizedMetricSpecification.Dimensions[i] - dim["name"] = aws.StringValue(rawDim.Name) - dim["value"] = aws.StringValue(rawDim.Value) - dimSpec[i] = dim - } - customizedMetricSpecificationFlat["metric_dimension"] = dimSpec - } - customizedMetricSpecificationFlat["metrics"] = flattenTargetTrackingMetricDataQueries(customizedMetricSpecification.Metrics) - - return []map[string]interface{}{customizedMetricSpecificationFlat} -} - -func flattenTargetTrackingMetricDataQueries(metricDataQueries []*autoscaling.TargetTrackingMetricDataQuery) []interface{} { - metricDataQueriesSpec := make([]interface{}, len(metricDataQueries)) - for i := range metricDataQueriesSpec { - metricDataQuery := map[string]interface{}{} - rawMetricDataQuery := metricDataQueries[i] - metricDataQuery["id"] = aws.StringValue(rawMetricDataQuery.Id) - if rawMetricDataQuery.Expression != nil { - metricDataQuery["expression"] = aws.StringValue(rawMetricDataQuery.Expression) - } - if rawMetricDataQuery.Label != nil { - metricDataQuery["label"] = aws.StringValue(rawMetricDataQuery.Label) + spec := map[string]interface{}{} + spec["metric_name"] = aws.StringValue(config.CustomizedMetricSpecification.MetricName) + spec["namespace"] = aws.StringValue(config.CustomizedMetricSpecification.Namespace) + spec["statistic"] = aws.StringValue(config.CustomizedMetricSpecification.Statistic) + if config.CustomizedMetricSpecification.Unit != nil { + spec["unit"] = aws.StringValue(config.CustomizedMetricSpecification.Unit) } - if rawMetricDataQuery.MetricStat != nil { - metricStatSpec := map[string]interface{}{} - rawMetricStat := rawMetricDataQuery.MetricStat - rawMetric := rawMetricStat.Metric - metricSpec := map[string]interface{}{} - if rawMetric.Dimensions != nil { - dimSpec := make([]interface{}, len(rawMetric.Dimensions)) - for i := range dimSpec { - dim := map[string]interface{}{} - rawDim := rawMetric.Dimensions[i] - dim["name"] = aws.StringValue(rawDim.Name) - dim["value"] = aws.StringValue(rawDim.Value) - dimSpec[i] = dim - } - metricSpec["dimensions"] = dimSpec + if config.CustomizedMetricSpecification.Dimensions != nil { + dimSpec := make([]interface{}, len(config.CustomizedMetricSpecification.Dimensions)) + for i := range dimSpec { + dim := map[string]interface{}{} + rawDim := config.CustomizedMetricSpecification.Dimensions[i] + dim["name"] = aws.StringValue(rawDim.Name) + dim["value"] = aws.StringValue(rawDim.Value) + dimSpec[i] = dim } - metricSpec["metric_name"] = aws.StringValue(rawMetric.MetricName) - metricSpec["namespace"] = aws.StringValue(rawMetric.Namespace) - metricStatSpec["metric"] = []map[string]interface{}{metricSpec} - metricStatSpec["stat"] = aws.StringValue(rawMetricStat.Stat) - if rawMetricStat.Unit != nil { - metricStatSpec["unit"] = aws.StringValue(rawMetricStat.Unit) - } - metricDataQuery["metric_stat"] = []map[string]interface{}{metricStatSpec} - } - if rawMetricDataQuery.ReturnData != nil { - metricDataQuery["return_data"] = aws.BoolValue(rawMetricDataQuery.ReturnData) + spec["metric_dimension"] = dimSpec } - metricDataQueriesSpec[i] = metricDataQuery + result["customized_metric_specification"] = []map[string]interface{}{spec} } - return metricDataQueriesSpec + return []interface{}{result} } func flattenPredictiveScalingConfig(predictiveScalingConfig *autoscaling.PredictiveScalingConfiguration) []map[string]interface{} { diff --git a/internal/service/autoscaling/policy_test.go b/internal/service/autoscaling/policy_test.go index e484b295e49..063c77df587 100644 --- a/internal/service/autoscaling/policy_test.go +++ b/internal/service/autoscaling/policy_test.go @@ -401,53 +401,6 @@ func TestAccAutoScalingPolicy_TargetTrack_custom(t *testing.T) { }) } -func TestAccAutoScalingPolicy_TargetTrack_advance(t *testing.T) { - ctx := acctest.Context(t) - var v autoscaling.ScalingPolicy - resourceName := "aws_autoscaling_policy.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, autoscaling.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckPolicyDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccPolicyConfig_targetTrackingAdvance(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckScalingPolicyExists(ctx, resourceName, &v), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.id", "e1"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.expression", "m1 / m2"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.label", "e1 label"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.0.return_data", "true"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.id", "m1"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.metric.0.dimensions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.metric.0.metric_name", "metric_name_foo"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.metric.0.namespace", "namespace_foo"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.metric_stat.0.stat", "Sum"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.label", "m1 metric stat"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.1.return_data", "false"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.id", "m2"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.metric.0.dimensions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.metric.0.metric_name", "metric_name_bar"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.metric.0.namespace", "namespace_bar"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.metric_stat.0.stat", "Average"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.label", "m2 metric stat"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.customized_metric_specification.0.metrics.2.return_data", "false"), - resource.TestCheckResourceAttr(resourceName, "target_tracking_configuration.0.target_value", "10"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateIdFunc: testAccPolicyImportStateIdFunc(resourceName), - ImportStateVerify: true, - }, - }, - }) -} - func TestAccAutoScalingPolicy_zeroValue(t *testing.T) { ctx := acctest.Context(t) var v1, v2 autoscaling.ScalingPolicy @@ -858,63 +811,6 @@ resource "aws_autoscaling_policy" "test" { `, rName)) } -func testAccPolicyConfig_targetTrackingAdvance(rName string) string { - return acctest.ConfigCompose(testAccPolicyConfigBase(rName), fmt.Sprintf(` -resource "aws_autoscaling_policy" "test" { - name = "%[1]s-tracking" - policy_type = "TargetTrackingScaling" - autoscaling_group_name = aws_autoscaling_group.test.name - - target_tracking_configuration { - customized_metric_specification { - metrics { - id = "e1" - expression = "m1 / m2" - label = "e1 label" - return_data = true - } - - metrics { - id = "m1" - metric_stat { - metric { - namespace = "namespace_foo" - metric_name = "metric_name_foo" - dimensions { - name = "foo" - value = "bar" - } - } - stat = "Sum" - } - label = "m1 metric stat" - return_data = false - } - - metrics { - id = "m2" - metric_stat { - metric { - namespace = "namespace_bar" - metric_name = "metric_name_bar" - dimensions { - name = "foo" - value = "bar" - } - } - stat = "Average" - } - label = "m2 metric stat" - return_data = false - } - } - - target_value = 10 - } -} -`, rName)) -} - func testAccPolicyConfig_zeroValue(rName string) string { return acctest.ConfigCompose(testAccPolicyConfigBase(rName), fmt.Sprintf(` resource "aws_autoscaling_policy" "test_simple" { diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index 5f3b2da895c..aa29813d1fd 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -119,62 +119,6 @@ resource "aws_autoscaling_policy" "example" { } ``` -### Create target tracking policy using customized metrics - -```terraform -resource "aws_autoscaling_policy" "example" { - autoscaling_group_name = "my-test-asg" - name = "foo" - policy_type = "PredictiveScaling" - target_tracking_configuration { - customized_metric_specification { - metrics { - id = "e1" - expression = "m1 / m2" - label = "Calculate the backlog per instance" - return_data = true - } - - metrics { - id = "m1" - metric_stat { - metric { - namespace = "AWS/SQS" - metric_name = "ApproximateNumberOfMessagesVisible" - dimensions { - name = "QueueName" - value = "my-queue" - } - } - stat = "Sum" - } - label = "Get the queue size (the number of messages waiting to be processed)" - return_data = false - } - - metrics { - id = "m2" - metric_stat { - metric { - namespace = "AWS/AutoScaling" - metric_name = "GroupInServiceInstances" - dimensions { - name = "AutoScalingGroupName" - value = "my-asg" - } - } - stat = "Average" - } - label = "Get the group size (the number of InService instances)" - return_data = false - } - } - - target_value = 10 - } -} -``` - ## Argument Reference * `name` - (Required) Name of the policy. From 102f94f7d88d284972e132f55160cad9576d74b0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 14:04:05 -0500 Subject: [PATCH 11/13] Tweak CHANGELOG entry. --- .changelog/28560.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/28560.txt b/.changelog/28560.txt index b73508b6cd2..e982bd00133 100644 --- a/.changelog/28560.txt +++ b/.changelog/28560.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -resource/aws_autoscaling_policy: Support metric math for target tracking +resource/aws_autoscaling_policy: Add `metrics` to the `target_tracking_configuration.customized_metric_specification` configuration block in support of [metric math](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-target-tracking-metric-math.html) ``` From c858a91065fa65a487546b62b7a4e4552c82c2df Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 14:07:07 -0500 Subject: [PATCH 12/13] Fix compilation errors. --- internal/service/autoscaling/policy.go | 44 ++++++++++----------- internal/service/autoscaling/policy_test.go | 5 ++- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/internal/service/autoscaling/policy.go b/internal/service/autoscaling/policy.go index 74828c65b51..75ba6786191 100644 --- a/internal/service/autoscaling/policy.go +++ b/internal/service/autoscaling/policy.go @@ -262,6 +262,28 @@ func ResourcePolicy() *schema.Resource { ConflictsWith: []string{"target_tracking_configuration.0.predefined_metric_specification"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "metric_dimension": { + Type: schema.TypeList, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, + }, "metrics": { Type: schema.TypeSet, Optional: true, @@ -342,28 +364,6 @@ func ResourcePolicy() *schema.Resource { }, }, }, - "metric_dimension": { - Type: schema.TypeList, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "value": { - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, - "metric_name": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification.0.metrics"}, - }, "namespace": { Type: schema.TypeString, Optional: true, diff --git a/internal/service/autoscaling/policy_test.go b/internal/service/autoscaling/policy_test.go index 8b564284c28..7ce005ea3c1 100644 --- a/internal/service/autoscaling/policy_test.go +++ b/internal/service/autoscaling/policy_test.go @@ -470,6 +470,7 @@ func TestAccAutoScalingPolicy_TargetTrack_custom(t *testing.T) { } func TestAccAutoScalingPolicy_TargetTrack_metricMath(t *testing.T) { + ctx := acctest.Context(t) var v autoscaling.ScalingPolicy resourceName := "aws_autoscaling_policy.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -478,12 +479,12 @@ func TestAccAutoScalingPolicy_TargetTrack_metricMath(t *testing.T) { PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, autoscaling.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckPolicyDestroy, + CheckDestroy: testAccCheckPolicyDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccPolicyConfig_targetTrackingMetricMath(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckScalingPolicyExists(resourceName, &v), + testAccCheckScalingPolicyExists(ctx, resourceName, &v), ), }, { From 0197a29179a7bc915e0d231348394e8d1650c0f0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 25 Feb 2023 14:15:34 -0500 Subject: [PATCH 13/13] Fix terrafmt error. --- website/docs/r/autoscaling_policy.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/autoscaling_policy.html.markdown b/website/docs/r/autoscaling_policy.html.markdown index 5a96f6aabad..1e4445f7278 100644 --- a/website/docs/r/autoscaling_policy.html.markdown +++ b/website/docs/r/autoscaling_policy.html.markdown @@ -84,8 +84,8 @@ resource "aws_autoscaling_policy" "example" { return_data = false } metrics { - label = "Calculate the backlog per instance" - id = "e1" + label = "Calculate the backlog per instance" + id = "e1" expression = "m1 / m2" return_data = true }