Add AWS::AutoScaling::ScheduledAction action cloudformation support (#5289)

This commit is contained in:
Sahil Shah 2022-07-26 04:07:22 +05:30 committed by GitHub
parent 7658051594
commit 40eefb92d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 143 additions and 8 deletions

View File

@ -280,6 +280,67 @@ class FakeLaunchConfiguration(CloudFormationModel):
return block_device_map return block_device_map
class FakeScheduledAction(CloudFormationModel):
def __init__(
self,
name,
desired_capacity,
max_size,
min_size,
scheduled_action_name=None,
start_time=None,
end_time=None,
recurrence=None,
):
self.name = name
self.desired_capacity = desired_capacity
self.max_size = max_size
self.min_size = min_size
self.start_time = start_time
self.end_time = end_time
self.recurrence = recurrence
self.scheduled_action_name = scheduled_action_name
@staticmethod
def cloudformation_name_type():
return "ScheduledActionName"
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-as-scheduledaction.html
return "AWS::AutoScaling::ScheduledAction"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name, **kwargs
):
properties = cloudformation_json["Properties"]
backend = autoscaling_backends[region_name]
scheduled_action_name = (
kwargs["LogicalId"]
if kwargs.get("LogicalId")
else "ScheduledScalingAction-{random.randint(0,100)}"
)
scheduled_action = backend.put_scheduled_update_group_action(
name=properties.get("AutoScalingGroupName"),
desired_capacity=properties.get("DesiredCapacity"),
max_size=properties.get("MaxSize"),
min_size=properties.get("MinSize"),
scheduled_action_name=scheduled_action_name,
start_time=properties.get("StartTime"),
end_time=properties.get("EndTime"),
recurrence=properties.get("Recurrence"),
)
return scheduled_action
class FakeAutoScalingGroup(CloudFormationModel): class FakeAutoScalingGroup(CloudFormationModel):
def __init__( def __init__(
self, self,
@ -676,6 +737,7 @@ class AutoScalingBackend(BaseBackend):
super().__init__(region_name, account_id) super().__init__(region_name, account_id)
self.autoscaling_groups = OrderedDict() self.autoscaling_groups = OrderedDict()
self.launch_configurations = OrderedDict() self.launch_configurations = OrderedDict()
self.scheduled_actions = OrderedDict()
self.policies = {} self.policies = {}
self.lifecycle_hooks = {} self.lifecycle_hooks = {}
self.ec2_backend = ec2_backends[region_name] self.ec2_backend = ec2_backends[region_name]
@ -760,6 +822,39 @@ class AutoScalingBackend(BaseBackend):
def delete_launch_configuration(self, launch_configuration_name): def delete_launch_configuration(self, launch_configuration_name):
self.launch_configurations.pop(launch_configuration_name, None) self.launch_configurations.pop(launch_configuration_name, None)
def make_int(self, value):
return int(value) if value is not None else value
def put_scheduled_update_group_action(
self,
name,
desired_capacity,
max_size,
min_size,
scheduled_action_name=None,
start_time=None,
end_time=None,
recurrence=None,
):
# TODO: Add validations for parameters
max_size = self.make_int(max_size)
min_size = self.make_int(min_size)
desired_capacity = self.make_int(desired_capacity)
scheduled_action = FakeScheduledAction(
name=name,
desired_capacity=desired_capacity,
max_size=max_size,
min_size=min_size,
scheduled_action_name=scheduled_action_name,
start_time=start_time,
end_time=end_time,
recurrence=recurrence,
)
self.scheduled_actions[scheduled_action_name] = scheduled_action
return scheduled_action
def create_auto_scaling_group( def create_auto_scaling_group(
self, self,
name, name,
@ -781,17 +876,14 @@ class AutoScalingBackend(BaseBackend):
new_instances_protected_from_scale_in=False, new_instances_protected_from_scale_in=False,
instance_id=None, instance_id=None,
): ):
def make_int(value): max_size = self.make_int(max_size)
return int(value) if value is not None else value min_size = self.make_int(min_size)
desired_capacity = self.make_int(desired_capacity)
max_size = make_int(max_size) default_cooldown = self.make_int(default_cooldown)
min_size = make_int(min_size)
desired_capacity = make_int(desired_capacity)
default_cooldown = make_int(default_cooldown)
if health_check_period is None: if health_check_period is None:
health_check_period = 300 health_check_period = 300
else: else:
health_check_period = make_int(health_check_period) health_check_period = self.make_int(health_check_period)
# TODO: Add MixedInstancesPolicy once implemented. # TODO: Add MixedInstancesPolicy once implemented.
# Verify only a single launch config-like parameter is provided. # Verify only a single launch config-like parameter is provided.

View File

@ -102,6 +102,20 @@ class AutoScalingResponse(BaseResponse):
template = self.response_template(CREATE_AUTOSCALING_GROUP_TEMPLATE) template = self.response_template(CREATE_AUTOSCALING_GROUP_TEMPLATE)
return template.render() return template.render()
def put_scheduled_update_group_action(self):
self.autoscaling_backend.put_scheduled_update_group_action(
name=self._get_param("AutoScalingGroupName"),
desired_capacity=self._get_int_param("DesiredCapacity"),
max_size=self._get_int_param("MaxSize"),
min_size=self._get_int_param("MinSize"),
scheduled_action_name=None,
start_time=self._get_param("StartTime"),
end_time=self._get_param("EndTime"),
recurrence=self._get_param("Recurrence"),
)
template = self.response_template(PUT_SCHEDULED_UPDATE_GROUP_ACTION_TEMPLATE)
return template.render()
@amz_crc32 @amz_crc32
@amzn_request_id @amzn_request_id
def attach_instances(self): def attach_instances(self):
@ -580,6 +594,12 @@ CREATE_AUTOSCALING_GROUP_TEMPLATE = """<CreateAutoScalingGroupResponse xmlns="ht
</ResponseMetadata> </ResponseMetadata>
</CreateAutoScalingGroupResponse>""" </CreateAutoScalingGroupResponse>"""
PUT_SCHEDULED_UPDATE_GROUP_ACTION_TEMPLATE = """<PutScheduledUpdateGroupActionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId></RequestId>
</ResponseMetadata>
</PutScheduledUpdateGroupActionResponse>"""
ATTACH_LOAD_BALANCER_TARGET_GROUPS_TEMPLATE = """<AttachLoadBalancerTargetGroupsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/"> ATTACH_LOAD_BALANCER_TARGET_GROUPS_TEMPLATE = """<AttachLoadBalancerTargetGroupsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<AttachLoadBalancerTargetGroupsResult> <AttachLoadBalancerTargetGroupsResult>
</AttachLoadBalancerTargetGroupsResult> </AttachLoadBalancerTargetGroupsResult>

View File

@ -75,6 +75,17 @@ def test_create_autoscaling_group_within_elb():
), ),
) )
as_client.put_scheduled_update_group_action(
AutoScalingGroupName="tester_group",
ScheduledActionName="my-scheduled-action",
StartTime="2022-07-01T00:00:00Z",
EndTime="2022-09-01T00:00:00Z",
Recurrence="* * * * *",
MinSize=10,
MaxSize=12,
DesiredCapacity=9,
)
group = as_client.describe_auto_scaling_groups()["AutoScalingGroups"][0] group = as_client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
group["AutoScalingGroupName"].should.equal("tester_group") group["AutoScalingGroupName"].should.equal("tester_group")
set(group["AvailabilityZones"]).should.equal(set(["us-east-1a", "us-east-1b"])) set(group["AvailabilityZones"]).should.equal(set(["us-east-1a", "us-east-1b"]))

View File

@ -1435,6 +1435,18 @@ def test_autoscaling_propagate_tags():
"InstanceType": "t2.medium", "InstanceType": "t2.medium",
}, },
}, },
"ScheduledAction": {
"Type": "AWS::AutoScaling::ScheduledAction",
"Properties": {
"AutoScalingGroupName": "test-scaling-group",
"DesiredCapacity": 10,
"EndTime": "2022-08-01T00:00:00Z",
"MaxSize": 15,
"MinSize": 5,
"Recurrence": "* * * * *",
"StartTime": "2022-07-01T00:00:00Z",
},
},
}, },
} }
boto3.client("cloudformation", "us-east-1").create_stack( boto3.client("cloudformation", "us-east-1").create_stack(