Merge branch 'andskli-appautoscaling'
This commit is contained in:
commit
28e073ec41
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/apigateway"
|
"github.com/aws/aws-sdk-go/service/apigateway"
|
||||||
|
"github.com/aws/aws-sdk-go/service/applicationautoscaling"
|
||||||
"github.com/aws/aws-sdk-go/service/autoscaling"
|
"github.com/aws/aws-sdk-go/service/autoscaling"
|
||||||
"github.com/aws/aws-sdk-go/service/cloudformation"
|
"github.com/aws/aws-sdk-go/service/cloudformation"
|
||||||
"github.com/aws/aws-sdk-go/service/cloudfront"
|
"github.com/aws/aws-sdk-go/service/cloudfront"
|
||||||
|
@ -94,6 +95,7 @@ type AWSClient struct {
|
||||||
emrconn *emr.EMR
|
emrconn *emr.EMR
|
||||||
esconn *elasticsearch.ElasticsearchService
|
esconn *elasticsearch.ElasticsearchService
|
||||||
apigateway *apigateway.APIGateway
|
apigateway *apigateway.APIGateway
|
||||||
|
appautoscalingconn *applicationautoscaling.ApplicationAutoScaling
|
||||||
autoscalingconn *autoscaling.AutoScaling
|
autoscalingconn *autoscaling.AutoScaling
|
||||||
s3conn *s3.S3
|
s3conn *s3.S3
|
||||||
sesConn *ses.SES
|
sesConn *ses.SES
|
||||||
|
@ -213,6 +215,7 @@ func (c *Config) Client() (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
client.apigateway = apigateway.New(sess)
|
client.apigateway = apigateway.New(sess)
|
||||||
|
client.appautoscalingconn = applicationautoscaling.New(sess)
|
||||||
client.autoscalingconn = autoscaling.New(sess)
|
client.autoscalingconn = autoscaling.New(sess)
|
||||||
client.cfconn = cloudformation.New(sess)
|
client.cfconn = cloudformation.New(sess)
|
||||||
client.cloudfrontconn = cloudfront.New(sess)
|
client.cloudfrontconn = cloudfront.New(sess)
|
||||||
|
|
|
@ -135,6 +135,8 @@ func Provider() terraform.ResourceProvider {
|
||||||
"aws_api_gateway_resource": resourceAwsApiGatewayResource(),
|
"aws_api_gateway_resource": resourceAwsApiGatewayResource(),
|
||||||
"aws_api_gateway_rest_api": resourceAwsApiGatewayRestApi(),
|
"aws_api_gateway_rest_api": resourceAwsApiGatewayRestApi(),
|
||||||
"aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(),
|
"aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(),
|
||||||
|
"aws_appautoscaling_target": resourceAwsAppautoscalingTarget(),
|
||||||
|
"aws_appautoscaling_policy": resourceAwsAppautoscalingPolicy(),
|
||||||
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
|
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
|
||||||
"aws_autoscaling_notification": resourceAwsAutoscalingNotification(),
|
"aws_autoscaling_notification": resourceAwsAutoscalingNotification(),
|
||||||
"aws_autoscaling_policy": resourceAwsAutoscalingPolicy(),
|
"aws_autoscaling_policy": resourceAwsAutoscalingPolicy(),
|
||||||
|
|
|
@ -0,0 +1,331 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"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/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingPolicy() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAwsAppautoscalingPolicyCreate,
|
||||||
|
Read: resourceAwsAppautoscalingPolicyRead,
|
||||||
|
Update: resourceAwsAppautoscalingPolicyUpdate,
|
||||||
|
Delete: resourceAwsAppautoscalingPolicyDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||||
|
// https://github.com/boto/botocore/blob/9f322b1/botocore/data/autoscaling/2011-01-01/service-2.json#L1862-L1873
|
||||||
|
value := v.(string)
|
||||||
|
if len(value) > 255 {
|
||||||
|
errors = append(errors, fmt.Errorf("q cannot be longer than 255 characters", k))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"arn": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"policy_type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "StepScaling",
|
||||||
|
},
|
||||||
|
"resource_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"scalable_dimension": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "ecs:service:DesiredCount",
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"service_namespace": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "ecs",
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"adjustment_type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"cooldown": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"metric_aggregation_type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"min_adjustment_magnitude": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"alarms": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"step_adjustment": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"metric_interval_lower_bound": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"metric_interval_upper_bound": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"scaling_adjustment": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Set: resourceAwsAppautoscalingAdjustmentHash,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingPolicyCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
params, err := getAwsAppautoscalingPutScalingPolicyInput(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] ApplicationAutoScaling PutScalingPolicy: %#v", params)
|
||||||
|
resp, err := conn.PutScalingPolicy(¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error putting scaling policy: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("arn", resp.PolicyARN)
|
||||||
|
d.SetId(d.Get("name").(string))
|
||||||
|
log.Printf("[INFO] ApplicationAutoScaling scaling PolicyARN: %s", d.Get("arn").(string))
|
||||||
|
|
||||||
|
return resourceAwsAppautoscalingPolicyRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingPolicyRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
p, err := getAwsAppautoscalingPolicy(d, meta)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p == nil {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Read ApplicationAutoScaling policy: %s, SP: %s, Obj: %s", d.Get("name"), d.Get("name"), p)
|
||||||
|
|
||||||
|
d.Set("arn", p.PolicyARN)
|
||||||
|
d.Set("name", p.PolicyName)
|
||||||
|
d.Set("policy_type", p.PolicyType)
|
||||||
|
d.Set("resource_id", p.ResourceId)
|
||||||
|
d.Set("scalable_dimension", p.ScalableDimension)
|
||||||
|
d.Set("service_namespace", p.ServiceNamespace)
|
||||||
|
d.Set("alarms", p.Alarms)
|
||||||
|
d.Set("step_scaling_policy_configuration", p.StepScalingPolicyConfiguration)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
params, inputErr := getAwsAppautoscalingPutScalingPolicyInput(d)
|
||||||
|
if inputErr != nil {
|
||||||
|
return inputErr
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Application Autoscaling Update Scaling Policy: %#v", params)
|
||||||
|
_, err := conn.PutScalingPolicy(¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceAwsAppautoscalingPolicyRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingPolicyDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
p, err := getAwsAppautoscalingPolicy(d, meta)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error getting policy: %s", err)
|
||||||
|
}
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
params := applicationautoscaling.DeleteScalingPolicyInput{
|
||||||
|
PolicyName: aws.String(d.Get("name").(string)),
|
||||||
|
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||||
|
ScalableDimension: aws.String(d.Get("scalable_dimension").(string)),
|
||||||
|
ServiceNamespace: aws.String(d.Get("service_namespace").(string)),
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] Deleting Application AutoScaling Policy opts: %#v", params)
|
||||||
|
if _, err := conn.DeleteScalingPolicy(¶ms); err != nil {
|
||||||
|
return fmt.Errorf("Application AutoScaling Policy: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes the result of flatmap.Expand for an array of step adjustments and
|
||||||
|
// returns a []*applicationautoscaling.StepAdjustment.
|
||||||
|
func expandAppautoscalingStepAdjustments(configured []interface{}) ([]*applicationautoscaling.StepAdjustment, error) {
|
||||||
|
var adjustments []*applicationautoscaling.StepAdjustment
|
||||||
|
|
||||||
|
// Loop over our configured step adjustments and create an array
|
||||||
|
// of aws-sdk-go compatible objects. We're forced to convert strings
|
||||||
|
// to floats here because there's no way to detect whether or not
|
||||||
|
// an uninitialized, optional schema element is "0.0" deliberately.
|
||||||
|
// With strings, we can test for "", which is definitely an empty
|
||||||
|
// struct value.
|
||||||
|
for _, raw := range configured {
|
||||||
|
data := raw.(map[string]interface{})
|
||||||
|
a := &applicationautoscaling.StepAdjustment{
|
||||||
|
ScalingAdjustment: aws.Int64(int64(data["scaling_adjustment"].(int))),
|
||||||
|
}
|
||||||
|
if data["metric_interval_lower_bound"] != "" {
|
||||||
|
bound := data["metric_interval_lower_bound"]
|
||||||
|
switch bound := bound.(type) {
|
||||||
|
case string:
|
||||||
|
f, err := strconv.ParseFloat(bound, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"metric_interval_lower_bound must be a float value represented as a string")
|
||||||
|
}
|
||||||
|
a.MetricIntervalLowerBound = aws.Float64(f)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"metric_interval_lower_bound isn't a string. This is a bug. Please file an issue.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if data["metric_interval_upper_bound"] != "" {
|
||||||
|
bound := data["metric_interval_upper_bound"]
|
||||||
|
switch bound := bound.(type) {
|
||||||
|
case string:
|
||||||
|
f, err := strconv.ParseFloat(bound, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"metric_interval_upper_bound must be a float value represented as a string")
|
||||||
|
}
|
||||||
|
a.MetricIntervalUpperBound = aws.Float64(f)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"metric_interval_upper_bound isn't a string. This is a bug. Please file an issue.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adjustments = append(adjustments, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return adjustments, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAwsAppautoscalingPutScalingPolicyInput(d *schema.ResourceData) (applicationautoscaling.PutScalingPolicyInput, error) {
|
||||||
|
var params = applicationautoscaling.PutScalingPolicyInput{
|
||||||
|
PolicyName: aws.String(d.Get("name").(string)),
|
||||||
|
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("policy_type"); ok {
|
||||||
|
params.PolicyType = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("service_namespace"); ok {
|
||||||
|
params.ServiceNamespace = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("policy_type"); ok {
|
||||||
|
params.PolicyType = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("scalable_dimension"); ok {
|
||||||
|
params.ScalableDimension = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
var adjustmentSteps []*applicationautoscaling.StepAdjustment
|
||||||
|
if v, ok := d.GetOk("step_adjustment"); ok {
|
||||||
|
steps, err := expandAppautoscalingStepAdjustments(v.(*schema.Set).List())
|
||||||
|
if err != nil {
|
||||||
|
return params, fmt.Errorf("metric_interval_lower_bound and metric_interval_upper_bound must be strings!")
|
||||||
|
}
|
||||||
|
adjustmentSteps = steps
|
||||||
|
}
|
||||||
|
|
||||||
|
// build StepScalingPolicyConfiguration
|
||||||
|
params.StepScalingPolicyConfiguration = &applicationautoscaling.StepScalingPolicyConfiguration{
|
||||||
|
AdjustmentType: aws.String(d.Get("adjustment_type").(string)),
|
||||||
|
Cooldown: aws.Int64(int64(d.Get("cooldown").(int))),
|
||||||
|
MetricAggregationType: aws.String(d.Get("metric_aggregation_type").(string)),
|
||||||
|
StepAdjustments: adjustmentSteps,
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("min_adjustment_magnitude"); ok {
|
||||||
|
params.StepScalingPolicyConfiguration.MinAdjustmentMagnitude = aws.Int64(int64(v.(int)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAwsAppautoscalingPolicy(d *schema.ResourceData, meta interface{}) (*applicationautoscaling.ScalingPolicy, error) {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
params := applicationautoscaling.DescribeScalingPoliciesInput{
|
||||||
|
PolicyNames: []*string{aws.String(d.Get("name").(string))},
|
||||||
|
ServiceNamespace: aws.String(d.Get("service_namespace").(string)),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Application AutoScaling Policy Describe Params: %#v", params)
|
||||||
|
resp, err := conn.DescribeScalingPolicies(¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error retrieving scaling policies: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// find scaling policy
|
||||||
|
name := d.Get("name")
|
||||||
|
for idx, sp := range resp.ScalingPolicies {
|
||||||
|
if *sp.PolicyName == name {
|
||||||
|
return resp.ScalingPolicies[idx], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// policy not found
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingAdjustmentHash(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
if v, ok := m["metric_interval_lower_bound"]; ok {
|
||||||
|
buf.WriteString(fmt.Sprintf("%f-", v))
|
||||||
|
}
|
||||||
|
if v, ok := m["metric_interval_upper_bound"]; ok {
|
||||||
|
buf.WriteString(fmt.Sprintf("%f-", v))
|
||||||
|
}
|
||||||
|
buf.WriteString(fmt.Sprintf("%d-", m["scaling_adjustment"].(int)))
|
||||||
|
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/applicationautoscaling"
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccAWSAppautoScalingPolicy_basic(t *testing.T) {
|
||||||
|
var policy applicationautoscaling.ScalingPolicy
|
||||||
|
|
||||||
|
randClusterName := fmt.Sprintf("cluster%s", acctest.RandString(10))
|
||||||
|
randPolicyName := fmt.Sprintf("terraform-test-foobar-%s", acctest.RandString(5))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckAWSAppautoscalingPolicyDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccAWSAppautoscalingPolicyConfig(randClusterName, randPolicyName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAWSAppautoscalingPolicyExists("aws_appautoscaling_policy.foobar_simple", &policy),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "adjustment_type", "ChangeInCapacity"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "policy_type", "StepScaling"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "cooldown", "60"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "name", randPolicyName),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "resource_id", fmt.Sprintf("service/%s/foobar", randClusterName)),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "service_namespace", "ecs"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_policy.foobar_simple", "scalable_dimension", "ecs:service:DesiredCount"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckAWSAppautoscalingPolicyExists(n string, policy *applicationautoscaling.ScalingPolicy) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).appautoscalingconn
|
||||||
|
params := &applicationautoscaling.DescribeScalingPoliciesInput{
|
||||||
|
ServiceNamespace: aws.String(rs.Primary.Attributes["service_namespace"]),
|
||||||
|
PolicyNames: []*string{aws.String(rs.Primary.ID)},
|
||||||
|
}
|
||||||
|
resp, err := conn.DescribeScalingPolicies(params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(resp.ScalingPolicies) == 0 {
|
||||||
|
return fmt.Errorf("ScalingPolicy %s not found", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckAWSAppautoscalingPolicyDestroy(s *terraform.State) error {
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
params := applicationautoscaling.DescribeScalingPoliciesInput{
|
||||||
|
ServiceNamespace: aws.String(rs.Primary.Attributes["service_namespace"]),
|
||||||
|
PolicyNames: []*string{aws.String(rs.Primary.ID)},
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.DescribeScalingPolicies(¶ms)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
if len(resp.ScalingPolicies) != 0 &&
|
||||||
|
*resp.ScalingPolicies[0].PolicyName == rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Application autoscaling policy still exists: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccAWSAppautoscalingPolicyConfig(
|
||||||
|
randClusterName string,
|
||||||
|
randPolicyName string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "aws_iam_role" "autoscale_role" {
|
||||||
|
name = "%s"
|
||||||
|
path = "/"
|
||||||
|
|
||||||
|
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"sts:AssumeRole\"]}]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "autoscale_role_policy" {
|
||||||
|
name = "%s"
|
||||||
|
role = "${aws_iam_role.autoscale_role.id}"
|
||||||
|
|
||||||
|
policy = <<EOF
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"ecs:DescribeServices",
|
||||||
|
"ecs:UpdateService",
|
||||||
|
"cloudwatch:DescribeAlarms"
|
||||||
|
],
|
||||||
|
"Resource": ["*"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_cluster" "foo" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_task_definition" "task" {
|
||||||
|
family = "foobar"
|
||||||
|
container_definitions = <<EOF
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "busybox",
|
||||||
|
"image": "busybox:latest",
|
||||||
|
"cpu": 10,
|
||||||
|
"memory": 128,
|
||||||
|
"essential": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_service" "service" {
|
||||||
|
name = "foobar"
|
||||||
|
cluster = "${aws_ecs_cluster.foo.id}"
|
||||||
|
task_definition = "${aws_ecs_task_definition.task.arn}"
|
||||||
|
desired_count = 1
|
||||||
|
deployment_maximum_percent = 200
|
||||||
|
deployment_minimum_healthy_percent = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_appautoscaling_target" "tgt" {
|
||||||
|
service_namespace = "ecs"
|
||||||
|
resource_id = "service/${aws_ecs_cluster.foo.name}/${aws_ecs_service.service.name}"
|
||||||
|
scalable_dimension = "ecs:service:DesiredCount"
|
||||||
|
role_arn = "${aws_iam_role.autoscale_role.arn}"
|
||||||
|
min_capacity = 1
|
||||||
|
max_capacity = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_appautoscaling_policy" "foobar_simple" {
|
||||||
|
name = "%s"
|
||||||
|
service_namespace = "ecs"
|
||||||
|
resource_id = "service/${aws_ecs_cluster.foo.name}/${aws_ecs_service.service.name}"
|
||||||
|
scalable_dimension = "ecs:service:DesiredCount"
|
||||||
|
adjustment_type = "ChangeInCapacity"
|
||||||
|
cooldown = 60
|
||||||
|
metric_aggregation_type = "Average"
|
||||||
|
step_adjustment {
|
||||||
|
metric_interval_lower_bound = 0
|
||||||
|
scaling_adjustment = 1
|
||||||
|
}
|
||||||
|
depends_on = ["aws_appautoscaling_target.tgt"]
|
||||||
|
}
|
||||||
|
`, randClusterName, randClusterName, randClusterName, randPolicyName)
|
||||||
|
}
|
|
@ -0,0 +1,216 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/service/applicationautoscaling"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingTarget() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAwsAppautoscalingTargetCreate,
|
||||||
|
Read: resourceAwsAppautoscalingTargetRead,
|
||||||
|
Delete: resourceAwsAppautoscalingTargetDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||||
|
// https://github.com/boto/botocore/blob/9f322b1/botocore/data/autoscaling/2011-01-01/service-2.json#L1862-L1873
|
||||||
|
value := v.(string)
|
||||||
|
if len(value) > 255 {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"%q cannot be longer than 255 characters", k))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"arn": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"max_capacity": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"min_capacity": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"resource_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"role_arn": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"scalable_dimension": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "ecs:service:DesiredCount",
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"service_namespace": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "ecs",
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingTargetCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
var targetOpts applicationautoscaling.RegisterScalableTargetInput
|
||||||
|
|
||||||
|
targetOpts.MaxCapacity = aws.Int64(int64(d.Get("max_capacity").(int)))
|
||||||
|
targetOpts.MinCapacity = aws.Int64(int64(d.Get("min_capacity").(int)))
|
||||||
|
targetOpts.ResourceId = aws.String(d.Get("resource_id").(string))
|
||||||
|
targetOpts.RoleARN = aws.String(d.Get("role_arn").(string))
|
||||||
|
targetOpts.ScalableDimension = aws.String(d.Get("scalable_dimension").(string))
|
||||||
|
targetOpts.ServiceNamespace = aws.String(d.Get("service_namespace").(string))
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Application autoscaling target create configuration %#v", targetOpts)
|
||||||
|
var out *applicationautoscaling.RegisterScalableTargetOutput
|
||||||
|
var err error
|
||||||
|
err = resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||||
|
out, err = conn.RegisterScalableTarget(&targetOpts)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ValidationException" {
|
||||||
|
log.Printf("[DEBUG] Retrying creation of Application Autoscaling Scalable Target due to possible issues with IAM: %s", awsErr)
|
||||||
|
return resource.RetryableError(err)
|
||||||
|
}
|
||||||
|
return resource.NonRetryableError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating application autoscaling target: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(d.Get("resource_id").(string))
|
||||||
|
log.Printf("[INFO] Application AutoScaling Target ID: %s", d.Id())
|
||||||
|
|
||||||
|
return resourceAwsAppautoscalingTargetRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingTargetRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
t, err := getAwsAppautoscalingTarget(d, conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if t == nil {
|
||||||
|
log.Printf("[INFO] Application AutoScaling Target %q not found", d.Id())
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("max_capacity", t.MaxCapacity)
|
||||||
|
d.Set("min_capacity", t.MinCapacity)
|
||||||
|
d.Set("resource_id", t.ResourceId)
|
||||||
|
d.Set("role_arn", t.RoleARN)
|
||||||
|
d.Set("scalable_dimension", t.ScalableDimension)
|
||||||
|
d.Set("service_namespace", t.ServiceNamespace)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updating Target is not supported
|
||||||
|
// func getAwsAppautoscalingTargetUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
// conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
func resourceAwsAppautoscalingTargetDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
t, err := getAwsAppautoscalingTarget(d, conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if t == nil {
|
||||||
|
log.Printf("[INFO] Application AutoScaling Target %q not found", d.Id())
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Application AutoScaling Target destroy: %#v", d.Id())
|
||||||
|
deleteOpts := applicationautoscaling.DeregisterScalableTargetInput{
|
||||||
|
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||||
|
ServiceNamespace: aws.String(d.Get("service_namespace").(string)),
|
||||||
|
ScalableDimension: aws.String(d.Get("scalable_dimension").(string)),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||||
|
if _, err := conn.DeregisterScalableTarget(&deleteOpts); err != nil {
|
||||||
|
if awserr, ok := err.(awserr.Error); ok {
|
||||||
|
// @TODO: We should do stuff here depending on the actual error returned
|
||||||
|
return resource.RetryableError(awserr)
|
||||||
|
}
|
||||||
|
// Non recognized error, no retry.
|
||||||
|
return resource.NonRetryableError(err)
|
||||||
|
}
|
||||||
|
// Successful delete
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||||
|
if t, _ = getAwsAppautoscalingTarget(d, conn); t != nil {
|
||||||
|
return resource.RetryableError(
|
||||||
|
fmt.Errorf("Application AutoScaling Target still exists"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAwsAppautoscalingTarget(
|
||||||
|
d *schema.ResourceData,
|
||||||
|
conn *applicationautoscaling.ApplicationAutoScaling) (*applicationautoscaling.ScalableTarget, error) {
|
||||||
|
|
||||||
|
tgtName := d.Id()
|
||||||
|
describeOpts := applicationautoscaling.DescribeScalableTargetsInput{
|
||||||
|
ResourceIds: []*string{aws.String(tgtName)},
|
||||||
|
ServiceNamespace: aws.String(d.Get("service_namespace").(string)),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Application AutoScaling Target describe configuration: %#v", describeOpts)
|
||||||
|
describeTargets, err := conn.DescribeScalableTargets(&describeOpts)
|
||||||
|
if err != nil {
|
||||||
|
// @TODO: We should probably send something else back if we're trying to access an unknown Resource ID
|
||||||
|
// targetserr, ok := err.(awserr.Error)
|
||||||
|
// if ok && targetserr.Code() == ""
|
||||||
|
return nil, fmt.Errorf("Error retrieving Application AutoScaling Target: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, tgt := range describeTargets.ScalableTargets {
|
||||||
|
if *tgt.ResourceId == tgtName {
|
||||||
|
return describeTargets.ScalableTargets[idx], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/service/applicationautoscaling"
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccAWSAppautoScalingTarget_basic(t *testing.T) {
|
||||||
|
var target applicationautoscaling.ScalableTarget
|
||||||
|
|
||||||
|
randClusterName := fmt.Sprintf("cluster-%s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
IDRefreshName: "aws_appautoscaling_target.bar",
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckAWSAppautoscalingTargetDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccAWSAppautoscalingTargetConfig(randClusterName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAWSAppautoscalingTargetExists("aws_appautoscaling_target.bar", &target),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_target.bar", "service_namespace", "ecs"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_target.bar", "scalable_dimension", "ecs:service:DesiredCount"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_target.bar", "min_capacity", "1"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_target.bar", "max_capacity", "3"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccAWSAppautoscalingTargetConfigUpdate(randClusterName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAWSAppautoscalingTargetExists("aws_appautoscaling_target.bar", &target),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_target.bar", "min_capacity", "2"),
|
||||||
|
resource.TestCheckResourceAttr("aws_appautoscaling_target.bar", "max_capacity", "8"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckAWSAppautoscalingTargetDestroy(s *terraform.State) error {
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "aws_appautoscaling_target" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find the target
|
||||||
|
describeTargets, err := conn.DescribeScalableTargets(
|
||||||
|
&applicationautoscaling.DescribeScalableTargetsInput{
|
||||||
|
ResourceIds: []*string{aws.String(rs.Primary.ID)},
|
||||||
|
ServiceNamespace: aws.String(rs.Primary.Attributes["service_namespace"]),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
if len(describeTargets.ScalableTargets) != 0 &&
|
||||||
|
*describeTargets.ScalableTargets[0].ResourceId == rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Application AutoScaling Target still exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify error
|
||||||
|
e, ok := err.(awserr.Error)
|
||||||
|
if !ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if e.Code() != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckAWSAppautoscalingTargetExists(n string, target *applicationautoscaling.ScalableTarget) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Application AutoScaling Target ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).appautoscalingconn
|
||||||
|
|
||||||
|
describeTargets, err := conn.DescribeScalableTargets(
|
||||||
|
&applicationautoscaling.DescribeScalableTargetsInput{
|
||||||
|
ResourceIds: []*string{aws.String(rs.Primary.ID)},
|
||||||
|
ServiceNamespace: aws.String(rs.Primary.Attributes["service_namespace"]),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(describeTargets.ScalableTargets) != 1 || *describeTargets.ScalableTargets[0].ResourceId != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Application AutoScaling ResourceId not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
target = describeTargets.ScalableTargets[0]
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccAWSAppautoscalingTargetConfig(
|
||||||
|
randClusterName string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "aws_iam_role" "autoscale_role" {
|
||||||
|
name = "autoscalerole%s"
|
||||||
|
path = "/"
|
||||||
|
|
||||||
|
assume_role_policy = <<EOF
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {
|
||||||
|
"Service": "application-autoscaling.amazonaws.com"
|
||||||
|
},
|
||||||
|
"Action": "sts:AssumeRole"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "autoscale_role_policy" {
|
||||||
|
name = "autoscalepolicy%s"
|
||||||
|
role = "${aws_iam_role.autoscale_role.id}"
|
||||||
|
|
||||||
|
policy = <<EOF
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"ecs:DescribeServices",
|
||||||
|
"ecs:UpdateService"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"cloudwatch:DescribeAlarms"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_cluster" "foo" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
resource "aws_ecs_task_definition" "task" {
|
||||||
|
family = "foobar"
|
||||||
|
container_definitions = <<EOF
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "busybox",
|
||||||
|
"image": "busybox:latest",
|
||||||
|
"cpu": 10,
|
||||||
|
"memory": 128,
|
||||||
|
"essential": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
resource "aws_ecs_service" "service" {
|
||||||
|
name = "foobar"
|
||||||
|
cluster = "${aws_ecs_cluster.foo.id}"
|
||||||
|
task_definition = "${aws_ecs_task_definition.task.arn}"
|
||||||
|
desired_count = 1
|
||||||
|
|
||||||
|
deployment_maximum_percent = 200
|
||||||
|
deployment_minimum_healthy_percent = 50
|
||||||
|
}
|
||||||
|
resource "aws_appautoscaling_target" "bar" {
|
||||||
|
service_namespace = "ecs"
|
||||||
|
resource_id = "service/${aws_ecs_cluster.foo.name}/${aws_ecs_service.service.name}"
|
||||||
|
scalable_dimension = "ecs:service:DesiredCount"
|
||||||
|
role_arn = "${aws_iam_role.autoscale_role.arn}"
|
||||||
|
min_capacity = 1
|
||||||
|
max_capacity = 3
|
||||||
|
}
|
||||||
|
`, randClusterName, randClusterName, randClusterName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccAWSAppautoscalingTargetConfigUpdate(
|
||||||
|
randClusterName string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "aws_iam_role" "autoscale_role" {
|
||||||
|
name = "autoscalerole%s"
|
||||||
|
path = "/"
|
||||||
|
|
||||||
|
assume_role_policy = <<EOF
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {
|
||||||
|
"Service": "application-autoscaling.amazonaws.com"
|
||||||
|
},
|
||||||
|
"Action": "sts:AssumeRole"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "autoscale_role_policy" {
|
||||||
|
name = "autoscalepolicy%s"
|
||||||
|
role = "${aws_iam_role.autoscale_role.id}"
|
||||||
|
|
||||||
|
policy = <<EOF
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"ecs:DescribeServices",
|
||||||
|
"ecs:UpdateService"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"cloudwatch:DescribeAlarms"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_cluster" "foo" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
resource "aws_ecs_task_definition" "task" {
|
||||||
|
family = "foobar"
|
||||||
|
container_definitions = <<EOF
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "busybox",
|
||||||
|
"image": "busybox:latest",
|
||||||
|
"cpu": 10,
|
||||||
|
"memory": 128,
|
||||||
|
"essential": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
resource "aws_ecs_service" "service" {
|
||||||
|
name = "foobar"
|
||||||
|
cluster = "${aws_ecs_cluster.foo.id}"
|
||||||
|
task_definition = "${aws_ecs_task_definition.task.arn}"
|
||||||
|
desired_count = 1
|
||||||
|
|
||||||
|
deployment_maximum_percent = 200
|
||||||
|
deployment_minimum_healthy_percent = 50
|
||||||
|
}
|
||||||
|
resource "aws_appautoscaling_target" "bar" {
|
||||||
|
service_namespace = "ecs"
|
||||||
|
resource_id = "service/${aws_ecs_cluster.foo.name}/${aws_ecs_service.service.name}"
|
||||||
|
scalable_dimension = "ecs:service:DesiredCount"
|
||||||
|
role_arn = "${aws_iam_role.autoscale_role.arn}"
|
||||||
|
min_capacity = 2
|
||||||
|
max_capacity = 8
|
||||||
|
}
|
||||||
|
`, randClusterName, randClusterName, randClusterName)
|
||||||
|
}
|
1450
vendor/github.com/aws/aws-sdk-go/service/applicationautoscaling/api.go
generated
vendored
Normal file
1450
vendor/github.com/aws/aws-sdk-go/service/applicationautoscaling/api.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
112
vendor/github.com/aws/aws-sdk-go/service/applicationautoscaling/service.go
generated
vendored
Normal file
112
vendor/github.com/aws/aws-sdk-go/service/applicationautoscaling/service.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package applicationautoscaling
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||||
|
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Application Auto Scaling is a general purpose Auto Scaling service for supported
|
||||||
|
// elastic AWS resources. With Application Auto Scaling, you can automatically
|
||||||
|
// scale your AWS resources, with an experience similar to that of Auto Scaling.
|
||||||
|
//
|
||||||
|
// At this time, Application Auto Scaling only supports scaling Amazon ECS
|
||||||
|
// services.
|
||||||
|
//
|
||||||
|
// For example, you can use Application Auto Scaling to accomplish the following
|
||||||
|
// tasks:
|
||||||
|
//
|
||||||
|
// Define scaling policies for automatically adjusting your application’s
|
||||||
|
// resources
|
||||||
|
//
|
||||||
|
// Scale your resources in response to CloudWatch alarms
|
||||||
|
//
|
||||||
|
// View history of your scaling events
|
||||||
|
//
|
||||||
|
// Application Auto Scaling is available in the following regions:
|
||||||
|
//
|
||||||
|
// us-east-1
|
||||||
|
//
|
||||||
|
// us-west-2
|
||||||
|
//
|
||||||
|
// eu-west-1
|
||||||
|
//The service client's operations are safe to be used concurrently.
|
||||||
|
// It is not safe to mutate any of the client's properties though.
|
||||||
|
type ApplicationAutoScaling struct {
|
||||||
|
*client.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for custom client initialization logic
|
||||||
|
var initClient func(*client.Client)
|
||||||
|
|
||||||
|
// Used for custom request initialization logic
|
||||||
|
var initRequest func(*request.Request)
|
||||||
|
|
||||||
|
// A ServiceName is the name of the service the client will make API calls to.
|
||||||
|
const ServiceName = "autoscaling"
|
||||||
|
|
||||||
|
// New creates a new instance of the ApplicationAutoScaling client with a session.
|
||||||
|
// If additional configuration is needed for the client instance use the optional
|
||||||
|
// aws.Config parameter to add your extra config.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// // Create a ApplicationAutoScaling client from just a session.
|
||||||
|
// svc := applicationautoscaling.New(mySession)
|
||||||
|
//
|
||||||
|
// // Create a ApplicationAutoScaling client with additional configuration
|
||||||
|
// svc := applicationautoscaling.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||||
|
func New(p client.ConfigProvider, cfgs ...*aws.Config) *ApplicationAutoScaling {
|
||||||
|
c := p.ClientConfig(ServiceName, cfgs...)
|
||||||
|
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newClient creates, initializes and returns a new service client instance.
|
||||||
|
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *ApplicationAutoScaling {
|
||||||
|
svc := &ApplicationAutoScaling{
|
||||||
|
Client: client.New(
|
||||||
|
cfg,
|
||||||
|
metadata.ClientInfo{
|
||||||
|
ServiceName: ServiceName,
|
||||||
|
SigningName: "application-autoscaling",
|
||||||
|
SigningRegion: signingRegion,
|
||||||
|
Endpoint: endpoint,
|
||||||
|
APIVersion: "2016-02-06",
|
||||||
|
JSONVersion: "1.1",
|
||||||
|
TargetPrefix: "AnyScaleFrontendService",
|
||||||
|
},
|
||||||
|
handlers,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
|
||||||
|
svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler)
|
||||||
|
svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler)
|
||||||
|
svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler)
|
||||||
|
svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler)
|
||||||
|
|
||||||
|
// Run custom client initialization if present
|
||||||
|
if initClient != nil {
|
||||||
|
initClient(svc.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRequest creates a new request for a ApplicationAutoScaling operation and runs any
|
||||||
|
// custom request initialization.
|
||||||
|
func (c *ApplicationAutoScaling) newRequest(op *request.Operation, params, data interface{}) *request.Request {
|
||||||
|
req := c.NewRequest(op, params, data)
|
||||||
|
|
||||||
|
// Run custom request initialization if present
|
||||||
|
if initRequest != nil {
|
||||||
|
initRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return req
|
||||||
|
}
|
|
@ -532,6 +532,12 @@
|
||||||
"version": "v1.2.7",
|
"version": "v1.2.7",
|
||||||
"versionExact": "v1.2.7"
|
"versionExact": "v1.2.7"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "Td30Frd+lrCLlkMAirUTbjBXq5Q=",
|
||||||
|
"path": "github.com/aws/aws-sdk-go/service/applicationautoscaling",
|
||||||
|
"revision": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6",
|
||||||
|
"revisionTime": "2016-07-08T00:08:20Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "AUA6op9dlm0X4vv1YPFnIFs6404=",
|
"checksumSHA1": "AUA6op9dlm0X4vv1YPFnIFs6404=",
|
||||||
"comment": "v1.1.23",
|
"comment": "v1.1.23",
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_appautoscaling_policy"
|
||||||
|
sidebar_current: "docs-aws-resource-appautoscaling-policy"
|
||||||
|
description: |-
|
||||||
|
Provides an Application AutoScaling Policy resource.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_appautoscaling\_policy
|
||||||
|
|
||||||
|
Provides an Application AutoScaling Policy resource.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
```
|
||||||
|
resource "aws_appautoscaling_policy" "down" {
|
||||||
|
name = "scale-down"
|
||||||
|
service_namespace = "ecs"
|
||||||
|
resource_id = "service/ecsclustername/servicename"
|
||||||
|
scalable_dimension = "ecs:service:DesiredCount"
|
||||||
|
|
||||||
|
adjustment_type = "ChangeInCapacity"
|
||||||
|
cooldown = 60
|
||||||
|
metric_aggregation_type = "Maximum"
|
||||||
|
|
||||||
|
step_adjustment {
|
||||||
|
metric_interval_lower_bound = 0
|
||||||
|
scaling_adjustment = -1
|
||||||
|
}
|
||||||
|
depends_on = ["aws_appautoscaling_target.target"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the policy.
|
||||||
|
* `policy_type` - (Optional) Defaults to "StepScaling" because it is the only option available.
|
||||||
|
* `resource_id` - (Required) The Resource ID on which you want the Application AutoScaling policy to apply to. For Amazon ECS services, this value is the resource type, followed by the cluster name and service name, such as `service/default/sample-webapp`.
|
||||||
|
* `scalable_dimension` - (Optional) The scalable dimension of the scalable target that this scaling policy applies to. The scalable dimension contains the service names- pace, resource type, and scaling property, such as `ecs:service:DesiredCount` for the desired task count of an Amazon ECS service. Defaults to `ecs:service:DesiredCount` since that is the only allowed value.
|
||||||
|
* `service_namespace` - (Optional) The AWS service namespace of the scalable target that this scaling policy applies to. Defaults to `ecs`, because that is currently the only supported option.
|
||||||
|
* `adjustment_type` - (Required) Specifies whether the adjustment is an absolute number or a percentage of the current capacity. Valid values are `ChangeInCapacity`, `ExactCapacity`, and `PercentChangeInCapacity`.
|
||||||
|
* `cooldown` - (Required) The amount of time, in seconds, after a scaling activity completes and before the next scaling activity can start.
|
||||||
|
* `metric_aggregation_type` - (Required) The aggregation type for the policy's metrics. Valid values are "Minimum", "Maximum", and "Average". Without a value, AWS will treat the aggregation type as "Average".
|
||||||
|
* `step_adjustments` - (Optional) A set of adjustments that manage scaling. These have the following structure:
|
||||||
|
```
|
||||||
|
step_adjustment {
|
||||||
|
scaling_adjustment = -1
|
||||||
|
metric_interval_lower_bound = 1.0
|
||||||
|
metric_interval_upper_bound = 2.0
|
||||||
|
}
|
||||||
|
step_adjustment {
|
||||||
|
scaling_adjustment = 1
|
||||||
|
metric_interval_lower_bound = 2.0
|
||||||
|
metric_interval_upper_bound = 3.0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* `scaling_adjustment` - (Required) The number of members by which to
|
||||||
|
scale, when the adjustment bounds are breached. A positive value scales
|
||||||
|
up. A negative value scales down.
|
||||||
|
* `metric_interval_lower_bound` - (Optional) The lower bound for the
|
||||||
|
difference between the alarm threshold and the CloudWatch metric.
|
||||||
|
Without a value, AWS will treat this bound as infinity.
|
||||||
|
* `metric_interval_upper_bound` - (Optional) The upper bound for the
|
||||||
|
difference between the alarm threshold and the CloudWatch metric.
|
||||||
|
Without a value, AWS will treat this bound as infinity. The upper bound
|
||||||
|
must be greater than the lower bound.
|
||||||
|
|
||||||
|
## Attribute Reference
|
||||||
|
* `arn` - The ARN assigned by AWS to the scaling policy.
|
||||||
|
* `name` - The scaling policy's name.
|
||||||
|
* `adjustment_type` - The scaling policy's adjustment type.
|
||||||
|
* `policy_type` - The scaling policy's type.
|
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_appautoscaling_target"
|
||||||
|
sidebar_current: "docs-aws-resource-appautoscaling-target"
|
||||||
|
description: |-
|
||||||
|
Provides an Application AutoScaling ScalableTarget resource.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_appautoscaling\_target
|
||||||
|
|
||||||
|
Provides an Application AutoScaling ScalableTarget resource.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
```
|
||||||
|
resource "aws_appautoscaling_target" "tgt" {
|
||||||
|
service_namespace = "ecs"
|
||||||
|
resource_id = "service/clusterName/serviceName"
|
||||||
|
scalable_dimension = "ecs:service:DesiredCount"
|
||||||
|
role_arn = "${var.ecs_iam_role}"
|
||||||
|
min_capacity = 1
|
||||||
|
max_capacity = 4
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the policy.
|
||||||
|
* `resource_id` - (Required) The Resource ID on which you want the Application AutoScaling policy to apply to. For Amazon ECS services, this value is the resource type, followed by the cluster name and service name, such as `service/default/sample-webapp`.
|
||||||
|
* `scalable_dimension` - (Optional) The scalable dimension of the scalable target. The scalable dimension contains the service namespace, resource type, and scaling property, such as `ecs:service:DesiredCount` for the desired task count of an Amazon ECS service. Defaults to `ecs:service:DesiredCount` since that is the only allowed value.
|
||||||
|
* `service_namespace` - (Optional) The AWS service namespace of the scalable target. Defaults to `ecs`, because that is currently the only supported option.
|
||||||
|
* `max_capacity` - (Required) The max capacity of the scalable target.
|
||||||
|
* `min_capacity` - (Required) The min capacity of the scalable target.
|
||||||
|
* `role_arn` - (Required) The ARN of the IAM role that allows Application AutoScaling to modify your scalable target on your behalf.
|
||||||
|
|
||||||
|
|
||||||
|
## Attribute Reference
|
||||||
|
* `arn` - The ARN assigned by AWS to the scaling policy.
|
||||||
|
* `name` - The scaling policy's name.
|
Loading…
Reference in New Issue