Skip to content

Commit

Permalink
provider/aws: allow empty value for autoscaling schedule parameters
Browse files Browse the repository at this point in the history
Specifically, this allows you to create a schedule which only changes
some of the group parameters without changing others, by setting the
parameters you wish to remain empty to -1.  This means you can adjust
min or max size without affecting the desired capacity, for example.

The ad hoc support for -1 isn't as nice as having real support for
leaving values out (see hashicorp#5694) but it solves a real use case.

Fixes hashicorp#5681.
  • Loading branch information
glasser committed Nov 7, 2016
1 parent 474bb24 commit 84e89b5
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 9 deletions.
41 changes: 35 additions & 6 deletions builtin/providers/aws/resource_aws_autoscaling_schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,24 @@ func resourceAwsAutoscalingScheduleCreate(d *schema.ResourceData, meta interface
params.Recurrence = aws.String(attr.(string))
}

params.MinSize = aws.Int64(int64(d.Get("min_size").(int)))
params.MaxSize = aws.Int64(int64(d.Get("max_size").(int)))
params.DesiredCapacity = aws.Int64(int64(d.Get("desired_capacity").(int)))
// Scheduled actions don't need to set all three size parameters. For example,
// you may want to change the min or max without also forcing an immediate
// resize by changing a desired_capacity that may have changed due to other
// autoscaling rules. Since Terraform doesn't have a great pattern for
// differentiating between 0 and unset fields, we accept "-1" to mean "don't
// include this parameter in the action".
minSize := int64(d.Get("min_size").(int))
maxSize := int64(d.Get("max_size").(int))
desiredCapacity := int64(d.Get("desired_capacity").(int))
if minSize != -1 {
params.MinSize = aws.Int64(minSize)
}
if maxSize != -1 {
params.MaxSize = aws.Int64(maxSize)
}
if desiredCapacity != -1 {
params.DesiredCapacity = aws.Int64(desiredCapacity)
}

log.Printf("[INFO] Creating Autoscaling Scheduled Action: %s", d.Get("scheduled_action_name").(string))
_, err := autoscalingconn.PutScheduledUpdateGroupAction(params)
Expand All @@ -120,9 +135,23 @@ func resourceAwsAutoscalingScheduleRead(d *schema.ResourceData, meta interface{}

d.Set("autoscaling_group_name", sa.AutoScalingGroupName)
d.Set("arn", sa.ScheduledActionARN)
d.Set("desired_capacity", sa.DesiredCapacity)
d.Set("min_size", sa.MinSize)
d.Set("max_size", sa.MaxSize)

if sa.MinSize == nil {
d.Set("min_size", -1)
} else {
d.Set("min_size", sa.MinSize)
}
if sa.MaxSize == nil {
d.Set("max_size", -1)
} else {
d.Set("max_size", sa.MaxSize)
}
if sa.DesiredCapacity == nil {
d.Set("desired_capacity", -1)
} else {
d.Set("desired_capacity", sa.DesiredCapacity)
}

d.Set("recurrence", sa.Recurrence)

if sa.StartTime != nil {
Expand Down
67 changes: 67 additions & 0 deletions builtin/providers/aws/resource_aws_autoscaling_schedule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,26 @@ func TestAccAWSAutoscalingSchedule_zeroValues(t *testing.T) {
})
}

func TestAccAWSAutoscalingSchedule_negativeOne(t *testing.T) {
var schedule autoscaling.ScheduledUpdateGroupAction

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSAutoscalingScheduleConfig_negativeOne,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalingScheduleExists("aws_autoscaling_schedule.foobar", &schedule),
testAccCheckScalingScheduleHasNoDesiredCapacity(&schedule),
resource.TestCheckResourceAttr("aws_autoscaling_schedule.foobar", "desired_capacity", "-1"),
),
},
},
})
}

func testAccCheckScalingScheduleExists(n string, policy *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand All @@ -86,6 +106,7 @@ func testAccCheckScalingScheduleExists(n string, policy *autoscaling.ScheduledUp
if len(resp.ScheduledUpdateGroupActions) == 0 {
return fmt.Errorf("Scaling Schedule not found")
}
*policy = *resp.ScheduledUpdateGroupActions[0]

return nil
}
Expand Down Expand Up @@ -118,6 +139,17 @@ func testAccCheckAWSAutoscalingScheduleDestroy(s *terraform.State) error {
return nil
}

func testAccCheckScalingScheduleHasNoDesiredCapacity(
schedule *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
return func(s *terraform.State) error {
if schedule.DesiredCapacity == nil {
return nil
}
return fmt.Errorf("Expected not to set desired capacity, got %v",
aws.Int64Value(schedule.DesiredCapacity))
}
}

var testAccAWSAutoscalingScheduleConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
name = "terraform-test-foobar5"
Expand Down Expand Up @@ -221,3 +253,38 @@ resource "aws_autoscaling_schedule" "foobar" {
autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`)

var testAccAWSAutoscalingScheduleConfig_negativeOne = fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
name = "terraform-test-foobar5"
image_id = "ami-21f78e11"
instance_type = "t1.micro"
}
resource "aws_autoscaling_group" "foobar" {
availability_zones = ["us-west-2a"]
name = "terraform-test-foobar5"
max_size = 1
min_size = 1
health_check_grace_period = 300
health_check_type = "ELB"
force_delete = true
termination_policies = ["OldestInstance"]
launch_configuration = "${aws_launch_configuration.foobar.name}"
tag {
key = "Foo"
value = "foo-bar"
propagate_at_launch = true
}
}
resource "aws_autoscaling_schedule" "foobar" {
scheduled_action_name = "foobar"
max_size = 3
min_size = 1
desired_capacity = -1
start_time = "2018-01-16T07:00:00Z"
end_time = "2018-01-16T13:00:00Z"
autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`)
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ The following arguments are supported:
If you try to schedule your action in the past, Auto Scaling returns an error message.
* `recurrence` - (Optional) The time when recurring future actions will start. Start time is specified by the user following the Unix cron syntax format.
* `min_size` - (Optional) The minimum size for the Auto Scaling group. Default
0.
0. Set to -1 if you don't want to change the minimum size at the scheduled time.
* `max_size` - (Optional) The maximum size for the Auto Scaling group. Default
0.
* `desired_capacity` - (Optional) The number of EC2 instances that should be running in the group. Default 0.
0. Set to -1 if you don't want to change the maximum size at the scheduled time.
* `desired_capacity` - (Optional) The number of EC2 instances that should be running in the group. Default 0. Set to -1 if you don't want to change the desired capacity at the scheduled time.

~> **NOTE:** When `start_time` and `end_time` are specified with `recurrence` , they form the boundaries of when the recurring action will start and stop.

Expand Down

0 comments on commit 84e89b5

Please sign in to comment.