Skip to content

Commit

Permalink
Merge pull request #1650 from terraform-providers/f-dynamodb-autoscaling
Browse files Browse the repository at this point in the history
r/appautoscaling_policy: Add support for DynamoDB
  • Loading branch information
radeksimko authored Sep 26, 2017
2 parents b93878f + fca3eab commit 08d051c
Show file tree
Hide file tree
Showing 5 changed files with 452 additions and 3 deletions.
266 changes: 264 additions & 2 deletions aws/resource_aws_appautoscaling_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"fmt"
"log"
"strconv"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/applicationautoscaling"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

Expand Down Expand Up @@ -153,6 +155,95 @@ func resourceAwsAppautoscalingPolicy() *schema.Resource {
},
},
},
"target_tracking_scaling_policy_configuration": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"customized_metric_specification": &schema.Schema{
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
ConflictsWith: []string{"target_tracking_scaling_policy_configuration.0.predefined_metric_specification"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dimensions": &schema.Schema{
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": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"namespace": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"statistic": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validateAppautoscalingCustomizedMetricSpecificationStatistic,
},
"unit": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
},
},
"predefined_metric_specification": &schema.Schema{
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
ConflictsWith: []string{"target_tracking_scaling_policy_configuration.0.customized_metric_specification"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"predefined_metric_type": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validateAppautoscalingPredefinedMetricSpecification,
},
"resource_label": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateAppautoscalingPredefinedResourceLabel,
},
},
},
},
"disable_scale_in": &schema.Schema{
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"scale_in_cooldown": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"scale_out_cooldown": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"target_value": &schema.Schema{
Type: schema.TypeFloat,
Required: true,
},
},
},
},
},
}
}
Expand All @@ -166,9 +257,20 @@ func resourceAwsAppautoscalingPolicyCreate(d *schema.ResourceData, meta interfac
}

log.Printf("[DEBUG] ApplicationAutoScaling PutScalingPolicy: %#v", params)
resp, err := conn.PutScalingPolicy(&params)
var resp *applicationautoscaling.PutScalingPolicyOutput
err = resource.Retry(1*time.Minute, func() *resource.RetryError {
var err error
resp, err = conn.PutScalingPolicy(&params)
if err != nil {
if isAWSErr(err, "FailedResourceAccessException", "is not authorized to perform") {
return resource.RetryableError(err)
}
return resource.NonRetryableError(fmt.Errorf("Error putting scaling policy: %s", err))
}
return nil
})
if err != nil {
return fmt.Errorf("Error putting scaling policy: %s", err)
return err
}

d.Set("arn", resp.PolicyARN)
Expand Down Expand Up @@ -198,6 +300,8 @@ func resourceAwsAppautoscalingPolicyRead(d *schema.ResourceData, meta interface{
d.Set("service_namespace", p.ServiceNamespace)
d.Set("alarms", p.Alarms)
d.Set("step_scaling_policy_configuration", flattenStepScalingPolicyConfiguration(p.StepScalingPolicyConfiguration))
d.Set("target_tracking_scaling_policy_configuration",
flattenTargetTrackingScalingPolicyConfiguration(p.TargetTrackingScalingPolicyConfiguration))

return nil
}
Expand Down Expand Up @@ -304,6 +408,59 @@ func expandAppautoscalingStepAdjustments(configured []interface{}) ([]*applicati
return adjustments, nil
}

func expandAppautoscalingCustomizedMetricSpecification(configured []interface{}) *applicationautoscaling.CustomizedMetricSpecification {
spec := &applicationautoscaling.CustomizedMetricSpecification{}

for _, raw := range configured {
data := raw.(map[string]interface{})
if v, ok := data["metric_name"]; ok {
spec.MetricName = aws.String(v.(string))
}

if v, ok := data["namespace"]; ok {
spec.Namespace = aws.String(v.(string))
}

if v, ok := data["unit"].(string); ok && v != "" {
spec.Unit = aws.String(v)
}

if v, ok := data["statistic"]; ok {
spec.Statistic = aws.String(v.(string))
}

if s, ok := data["dimensions"].(*schema.Set); ok && s.Len() > 0 {
dimensions := make([]*applicationautoscaling.MetricDimension, s.Len(), s.Len())
for i, d := range s.List() {
dimension := d.(map[string]interface{})
dimensions[i] = &applicationautoscaling.MetricDimension{
Name: aws.String(dimension["name"].(string)),
Value: aws.String(dimension["value"].(string)),
}
}
spec.Dimensions = dimensions
}
}
return spec
}

func expandAppautoscalingPredefinedMetricSpecification(configured []interface{}) *applicationautoscaling.PredefinedMetricSpecification {
spec := &applicationautoscaling.PredefinedMetricSpecification{}

for _, raw := range configured {
data := raw.(map[string]interface{})

if v, ok := data["predefined_metric_type"]; ok {
spec.PredefinedMetricType = aws.String(v.(string))
}

if v, ok := data["resource_label"].(string); ok && v != "" {
spec.ResourceLabel = aws.String(v)
}
}
return spec
}

func getAwsAppautoscalingPutScalingPolicyInput(d *schema.ResourceData) (applicationautoscaling.PutScalingPolicyInput, error) {
var params = applicationautoscaling.PutScalingPolicyInput{
PolicyName: aws.String(d.Get("name").(string)),
Expand Down Expand Up @@ -363,6 +520,39 @@ func getAwsAppautoscalingPutScalingPolicyInput(d *schema.ResourceData) (applicat
params.StepScalingPolicyConfiguration = expandStepScalingPolicyConfiguration(v.([]interface{}))
}

if l, ok := d.GetOk("target_tracking_scaling_policy_configuration"); ok {
v := l.([]interface{})
if len(v) < 1 {
return params, fmt.Errorf("Empty target_tracking_scaling_policy_configuration block")
}
ttspCfg := v[0].(map[string]interface{})
cfg := &applicationautoscaling.TargetTrackingScalingPolicyConfiguration{
TargetValue: aws.Float64(ttspCfg["target_value"].(float64)),
}

if v, ok := ttspCfg["scale_in_cooldown"]; ok {
cfg.ScaleInCooldown = aws.Int64(int64(v.(int)))
}

if v, ok := ttspCfg["scale_out_cooldown"]; ok {
cfg.ScaleOutCooldown = aws.Int64(int64(v.(int)))
}

if v, ok := ttspCfg["disable_scale_in"]; ok {
cfg.DisableScaleIn = aws.Bool(v.(bool))
}

if v, ok := ttspCfg["customized_metric_specification"].([]interface{}); ok && len(v) > 0 {
cfg.CustomizedMetricSpecification = expandAppautoscalingCustomizedMetricSpecification(v)
}

if v, ok := ttspCfg["predefined_metric_specification"].([]interface{}); ok && len(v) > 0 {
cfg.PredefinedMetricSpecification = expandAppautoscalingPredefinedMetricSpecification(v)
}

params.TargetTrackingScalingPolicyConfiguration = cfg
}

return params, nil
}

Expand Down Expand Up @@ -466,6 +656,78 @@ func flattenAppautoscalingStepAdjustments(adjs []*applicationautoscaling.StepAdj
return out
}

func flattenTargetTrackingScalingPolicyConfiguration(cfg *applicationautoscaling.TargetTrackingScalingPolicyConfiguration) []interface{} {
if cfg == nil {
return []interface{}{}
}

m := make(map[string]interface{}, 0)
m["target_value"] = *cfg.TargetValue

if cfg.DisableScaleIn != nil {
m["disable_scale_in"] = *cfg.DisableScaleIn
}
if cfg.ScaleInCooldown != nil {
m["scale_in_cooldown"] = *cfg.ScaleInCooldown
}
if cfg.ScaleOutCooldown != nil {
m["scale_out_cooldown"] = *cfg.ScaleOutCooldown
}
if cfg.CustomizedMetricSpecification != nil {
m["customized_metric_specification"] = flattenCustomizedMetricSpecification(cfg.CustomizedMetricSpecification)
}
if cfg.PredefinedMetricSpecification != nil {
m["predefined_metric_specification"] = flattenPredefinedMetricSpecification(cfg.PredefinedMetricSpecification)
}

return []interface{}{m}
}

func flattenCustomizedMetricSpecification(cfg *applicationautoscaling.CustomizedMetricSpecification) []interface{} {
if cfg == nil {
return []interface{}{}
}

m := map[string]interface{}{
"metric_name": *cfg.MetricName,
"namespace": *cfg.Namespace,
"statistic": *cfg.Statistic,
}

if len(cfg.Dimensions) > 0 {
m["dimensions"] = flattenMetricDimensions(cfg.Dimensions)
}

if cfg.Unit != nil {
m["unit"] = *cfg.Unit
}
return []interface{}{m}
}

func flattenMetricDimensions(ds []*applicationautoscaling.MetricDimension) []interface{} {
l := make([]interface{}, len(ds), len(ds))
for i, d := range ds {
l[i] = map[string]interface{}{
"name": *d.Name,
"value": *d.Value,
}
}
return l
}

func flattenPredefinedMetricSpecification(cfg *applicationautoscaling.PredefinedMetricSpecification) []interface{} {
if cfg == nil {
return []interface{}{}
}
m := map[string]interface{}{
"predefined_metric_type": *cfg.PredefinedMetricType,
}
if cfg.ResourceLabel != nil {
m["resource_label"] = *cfg.ResourceLabel
}
return []interface{}{m}
}

func resourceAwsAppautoscalingAdjustmentHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
Expand Down
Loading

0 comments on commit 08d051c

Please sign in to comment.