Add support for Launch Templates in Auto Scaling Groups (#3236)
* Add support for Launch Templates in Auto Scaling Groups * Use named parameters, simplify parameter validation
This commit is contained in:
parent
2a27e457bf
commit
55b02c6ee9
@ -2639,7 +2639,7 @@
|
|||||||
- [X] create_internet_gateway
|
- [X] create_internet_gateway
|
||||||
- [X] create_key_pair
|
- [X] create_key_pair
|
||||||
- [X] create_launch_template
|
- [X] create_launch_template
|
||||||
- [ ] create_launch_template_version
|
- [x] create_launch_template_version
|
||||||
- [ ] create_local_gateway_route
|
- [ ] create_local_gateway_route
|
||||||
- [ ] create_local_gateway_route_table_vpc_association
|
- [ ] create_local_gateway_route_table_vpc_association
|
||||||
- [X] create_nat_gateway
|
- [X] create_nat_gateway
|
||||||
|
@ -21,3 +21,8 @@ class InvalidInstanceError(AutoscalingClientError):
|
|||||||
super(InvalidInstanceError, self).__init__(
|
super(InvalidInstanceError, self).__init__(
|
||||||
"ValidationError", "Instance [{0}] is invalid.".format(instance_id)
|
"ValidationError", "Instance [{0}] is invalid.".format(instance_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationError(AutoscalingClientError):
|
||||||
|
def __init__(self, message):
|
||||||
|
super(ValidationError, self).__init__("ValidationError", message)
|
||||||
|
@ -7,6 +7,7 @@ from moto.ec2.exceptions import InvalidInstanceIdError
|
|||||||
|
|
||||||
from moto.compat import OrderedDict
|
from moto.compat import OrderedDict
|
||||||
from moto.core import BaseBackend, BaseModel, CloudFormationModel
|
from moto.core import BaseBackend, BaseModel, CloudFormationModel
|
||||||
|
from moto.core.utils import camelcase_to_underscores
|
||||||
from moto.ec2 import ec2_backends
|
from moto.ec2 import ec2_backends
|
||||||
from moto.elb import elb_backends
|
from moto.elb import elb_backends
|
||||||
from moto.elbv2 import elbv2_backends
|
from moto.elbv2 import elbv2_backends
|
||||||
@ -15,6 +16,7 @@ from .exceptions import (
|
|||||||
AutoscalingClientError,
|
AutoscalingClientError,
|
||||||
ResourceContentionError,
|
ResourceContentionError,
|
||||||
InvalidInstanceError,
|
InvalidInstanceError,
|
||||||
|
ValidationError,
|
||||||
)
|
)
|
||||||
|
|
||||||
# http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/AS_Concepts.html#Cooldown
|
# http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/AS_Concepts.html#Cooldown
|
||||||
@ -233,6 +235,7 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
max_size,
|
max_size,
|
||||||
min_size,
|
min_size,
|
||||||
launch_config_name,
|
launch_config_name,
|
||||||
|
launch_template,
|
||||||
vpc_zone_identifier,
|
vpc_zone_identifier,
|
||||||
default_cooldown,
|
default_cooldown,
|
||||||
health_check_period,
|
health_check_period,
|
||||||
@ -242,10 +245,12 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
placement_group,
|
placement_group,
|
||||||
termination_policies,
|
termination_policies,
|
||||||
autoscaling_backend,
|
autoscaling_backend,
|
||||||
|
ec2_backend,
|
||||||
tags,
|
tags,
|
||||||
new_instances_protected_from_scale_in=False,
|
new_instances_protected_from_scale_in=False,
|
||||||
):
|
):
|
||||||
self.autoscaling_backend = autoscaling_backend
|
self.autoscaling_backend = autoscaling_backend
|
||||||
|
self.ec2_backend = ec2_backend
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
self._set_azs_and_vpcs(availability_zones, vpc_zone_identifier)
|
self._set_azs_and_vpcs(availability_zones, vpc_zone_identifier)
|
||||||
@ -253,10 +258,10 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
self.max_size = max_size
|
self.max_size = max_size
|
||||||
self.min_size = min_size
|
self.min_size = min_size
|
||||||
|
|
||||||
self.launch_config = self.autoscaling_backend.launch_configurations[
|
self.launch_template = None
|
||||||
launch_config_name
|
self.launch_config = None
|
||||||
]
|
|
||||||
self.launch_config_name = launch_config_name
|
self._set_launch_configuration(launch_config_name, launch_template)
|
||||||
|
|
||||||
self.default_cooldown = (
|
self.default_cooldown = (
|
||||||
default_cooldown if default_cooldown else DEFAULT_COOLDOWN
|
default_cooldown if default_cooldown else DEFAULT_COOLDOWN
|
||||||
@ -310,6 +315,34 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
self.availability_zones = availability_zones
|
self.availability_zones = availability_zones
|
||||||
self.vpc_zone_identifier = vpc_zone_identifier
|
self.vpc_zone_identifier = vpc_zone_identifier
|
||||||
|
|
||||||
|
def _set_launch_configuration(self, launch_config_name, launch_template):
|
||||||
|
if launch_config_name:
|
||||||
|
self.launch_config = self.autoscaling_backend.launch_configurations[
|
||||||
|
launch_config_name
|
||||||
|
]
|
||||||
|
self.launch_config_name = launch_config_name
|
||||||
|
|
||||||
|
if launch_template:
|
||||||
|
launch_template_id = launch_template.get("launch_template_id")
|
||||||
|
launch_template_name = launch_template.get("launch_template_name")
|
||||||
|
|
||||||
|
if not (launch_template_id or launch_template_name) or (
|
||||||
|
launch_template_id and launch_template_name
|
||||||
|
):
|
||||||
|
raise ValidationError(
|
||||||
|
"Valid requests must contain either launchTemplateId or LaunchTemplateName"
|
||||||
|
)
|
||||||
|
|
||||||
|
if launch_template_id:
|
||||||
|
self.launch_template = self.ec2_backend.get_launch_template(
|
||||||
|
launch_template_id
|
||||||
|
)
|
||||||
|
elif launch_template_name:
|
||||||
|
self.launch_template = self.ec2_backend.get_launch_template_by_name(
|
||||||
|
launch_template_name
|
||||||
|
)
|
||||||
|
self.launch_template_version = int(launch_template["version"])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __set_string_propagate_at_launch_booleans_on_tags(tags):
|
def __set_string_propagate_at_launch_booleans_on_tags(tags):
|
||||||
bool_to_string = {True: "true", False: "false"}
|
bool_to_string = {True: "true", False: "false"}
|
||||||
@ -334,6 +367,10 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
properties = cloudformation_json["Properties"]
|
properties = cloudformation_json["Properties"]
|
||||||
|
|
||||||
launch_config_name = properties.get("LaunchConfigurationName")
|
launch_config_name = properties.get("LaunchConfigurationName")
|
||||||
|
launch_template = {
|
||||||
|
camelcase_to_underscores(k): v
|
||||||
|
for k, v in properties.get("LaunchTemplate", {}).items()
|
||||||
|
}
|
||||||
load_balancer_names = properties.get("LoadBalancerNames", [])
|
load_balancer_names = properties.get("LoadBalancerNames", [])
|
||||||
target_group_arns = properties.get("TargetGroupARNs", [])
|
target_group_arns = properties.get("TargetGroupARNs", [])
|
||||||
|
|
||||||
@ -345,6 +382,7 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
max_size=properties.get("MaxSize"),
|
max_size=properties.get("MaxSize"),
|
||||||
min_size=properties.get("MinSize"),
|
min_size=properties.get("MinSize"),
|
||||||
launch_config_name=launch_config_name,
|
launch_config_name=launch_config_name,
|
||||||
|
launch_template=launch_template,
|
||||||
vpc_zone_identifier=(
|
vpc_zone_identifier=(
|
||||||
",".join(properties.get("VPCZoneIdentifier", [])) or None
|
",".join(properties.get("VPCZoneIdentifier", [])) or None
|
||||||
),
|
),
|
||||||
@ -393,6 +431,38 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
def physical_resource_id(self):
|
def physical_resource_id(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def image_id(self):
|
||||||
|
if self.launch_template:
|
||||||
|
version = self.launch_template.get_version(self.launch_template_version)
|
||||||
|
return version.image_id
|
||||||
|
|
||||||
|
return self.launch_config.image_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def instance_type(self):
|
||||||
|
if self.launch_template:
|
||||||
|
version = self.launch_template.get_version(self.launch_template_version)
|
||||||
|
return version.instance_type
|
||||||
|
|
||||||
|
return self.launch_config.instance_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data(self):
|
||||||
|
if self.launch_template:
|
||||||
|
version = self.launch_template.get_version(self.launch_template_version)
|
||||||
|
return version.user_data
|
||||||
|
|
||||||
|
return self.launch_config.user_data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def security_groups(self):
|
||||||
|
if self.launch_template:
|
||||||
|
version = self.launch_template.get_version(self.launch_template_version)
|
||||||
|
return version.security_groups
|
||||||
|
|
||||||
|
return self.launch_config.security_groups
|
||||||
|
|
||||||
def update(
|
def update(
|
||||||
self,
|
self,
|
||||||
availability_zones,
|
availability_zones,
|
||||||
@ -400,6 +470,7 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
max_size,
|
max_size,
|
||||||
min_size,
|
min_size,
|
||||||
launch_config_name,
|
launch_config_name,
|
||||||
|
launch_template,
|
||||||
vpc_zone_identifier,
|
vpc_zone_identifier,
|
||||||
default_cooldown,
|
default_cooldown,
|
||||||
health_check_period,
|
health_check_period,
|
||||||
@ -421,11 +492,8 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
if max_size is not None and max_size < len(self.instance_states):
|
if max_size is not None and max_size < len(self.instance_states):
|
||||||
desired_capacity = max_size
|
desired_capacity = max_size
|
||||||
|
|
||||||
if launch_config_name:
|
self._set_launch_configuration(launch_config_name, launch_template)
|
||||||
self.launch_config = self.autoscaling_backend.launch_configurations[
|
|
||||||
launch_config_name
|
|
||||||
]
|
|
||||||
self.launch_config_name = launch_config_name
|
|
||||||
if health_check_period is not None:
|
if health_check_period is not None:
|
||||||
self.health_check_period = health_check_period
|
self.health_check_period = health_check_period
|
||||||
if health_check_type is not None:
|
if health_check_type is not None:
|
||||||
@ -489,12 +557,13 @@ class FakeAutoScalingGroup(CloudFormationModel):
|
|||||||
|
|
||||||
def replace_autoscaling_group_instances(self, count_needed, propagated_tags):
|
def replace_autoscaling_group_instances(self, count_needed, propagated_tags):
|
||||||
propagated_tags[ASG_NAME_TAG] = self.name
|
propagated_tags[ASG_NAME_TAG] = self.name
|
||||||
|
|
||||||
reservation = self.autoscaling_backend.ec2_backend.add_instances(
|
reservation = self.autoscaling_backend.ec2_backend.add_instances(
|
||||||
self.launch_config.image_id,
|
self.image_id,
|
||||||
count_needed,
|
count_needed,
|
||||||
self.launch_config.user_data,
|
self.user_data,
|
||||||
self.launch_config.security_groups,
|
self.security_groups,
|
||||||
instance_type=self.launch_config.instance_type,
|
instance_type=self.instance_type,
|
||||||
tags={"instance": propagated_tags},
|
tags={"instance": propagated_tags},
|
||||||
placement=random.choice(self.availability_zones),
|
placement=random.choice(self.availability_zones),
|
||||||
)
|
)
|
||||||
@ -586,6 +655,7 @@ class AutoScalingBackend(BaseBackend):
|
|||||||
max_size,
|
max_size,
|
||||||
min_size,
|
min_size,
|
||||||
launch_config_name,
|
launch_config_name,
|
||||||
|
launch_template,
|
||||||
vpc_zone_identifier,
|
vpc_zone_identifier,
|
||||||
default_cooldown,
|
default_cooldown,
|
||||||
health_check_period,
|
health_check_period,
|
||||||
@ -609,7 +679,19 @@ class AutoScalingBackend(BaseBackend):
|
|||||||
health_check_period = 300
|
health_check_period = 300
|
||||||
else:
|
else:
|
||||||
health_check_period = make_int(health_check_period)
|
health_check_period = make_int(health_check_period)
|
||||||
if launch_config_name is None and instance_id is not None:
|
|
||||||
|
# TODO: Add MixedInstancesPolicy once implemented.
|
||||||
|
# Verify only a single launch config-like parameter is provided.
|
||||||
|
params = [launch_config_name, launch_template, instance_id]
|
||||||
|
num_params = sum([1 for param in params if param])
|
||||||
|
|
||||||
|
if num_params != 1:
|
||||||
|
raise ValidationError(
|
||||||
|
"Valid requests must contain either LaunchTemplate, LaunchConfigurationName, "
|
||||||
|
"InstanceId or MixedInstancesPolicy parameter."
|
||||||
|
)
|
||||||
|
|
||||||
|
if instance_id:
|
||||||
try:
|
try:
|
||||||
instance = self.ec2_backend.get_instance(instance_id)
|
instance = self.ec2_backend.get_instance(instance_id)
|
||||||
launch_config_name = name
|
launch_config_name = name
|
||||||
@ -626,6 +708,7 @@ class AutoScalingBackend(BaseBackend):
|
|||||||
max_size=max_size,
|
max_size=max_size,
|
||||||
min_size=min_size,
|
min_size=min_size,
|
||||||
launch_config_name=launch_config_name,
|
launch_config_name=launch_config_name,
|
||||||
|
launch_template=launch_template,
|
||||||
vpc_zone_identifier=vpc_zone_identifier,
|
vpc_zone_identifier=vpc_zone_identifier,
|
||||||
default_cooldown=default_cooldown,
|
default_cooldown=default_cooldown,
|
||||||
health_check_period=health_check_period,
|
health_check_period=health_check_period,
|
||||||
@ -635,6 +718,7 @@ class AutoScalingBackend(BaseBackend):
|
|||||||
placement_group=placement_group,
|
placement_group=placement_group,
|
||||||
termination_policies=termination_policies,
|
termination_policies=termination_policies,
|
||||||
autoscaling_backend=self,
|
autoscaling_backend=self,
|
||||||
|
ec2_backend=self.ec2_backend,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
new_instances_protected_from_scale_in=new_instances_protected_from_scale_in,
|
new_instances_protected_from_scale_in=new_instances_protected_from_scale_in,
|
||||||
)
|
)
|
||||||
@ -652,6 +736,7 @@ class AutoScalingBackend(BaseBackend):
|
|||||||
max_size,
|
max_size,
|
||||||
min_size,
|
min_size,
|
||||||
launch_config_name,
|
launch_config_name,
|
||||||
|
launch_template,
|
||||||
vpc_zone_identifier,
|
vpc_zone_identifier,
|
||||||
default_cooldown,
|
default_cooldown,
|
||||||
health_check_period,
|
health_check_period,
|
||||||
@ -660,19 +745,28 @@ class AutoScalingBackend(BaseBackend):
|
|||||||
termination_policies,
|
termination_policies,
|
||||||
new_instances_protected_from_scale_in=None,
|
new_instances_protected_from_scale_in=None,
|
||||||
):
|
):
|
||||||
|
# TODO: Add MixedInstancesPolicy once implemented.
|
||||||
|
# Verify only a single launch config-like parameter is provided.
|
||||||
|
if launch_config_name and launch_template:
|
||||||
|
raise ValidationError(
|
||||||
|
"Valid requests must contain either LaunchTemplate, LaunchConfigurationName "
|
||||||
|
"or MixedInstancesPolicy parameter."
|
||||||
|
)
|
||||||
|
|
||||||
group = self.autoscaling_groups[name]
|
group = self.autoscaling_groups[name]
|
||||||
group.update(
|
group.update(
|
||||||
availability_zones,
|
availability_zones=availability_zones,
|
||||||
desired_capacity,
|
desired_capacity=desired_capacity,
|
||||||
max_size,
|
max_size=max_size,
|
||||||
min_size,
|
min_size=min_size,
|
||||||
launch_config_name,
|
launch_config_name=launch_config_name,
|
||||||
vpc_zone_identifier,
|
launch_template=launch_template,
|
||||||
default_cooldown,
|
vpc_zone_identifier=vpc_zone_identifier,
|
||||||
health_check_period,
|
default_cooldown=default_cooldown,
|
||||||
health_check_type,
|
health_check_period=health_check_period,
|
||||||
placement_group,
|
health_check_type=health_check_type,
|
||||||
termination_policies,
|
placement_group=placement_group,
|
||||||
|
termination_policies=termination_policies,
|
||||||
new_instances_protected_from_scale_in=new_instances_protected_from_scale_in,
|
new_instances_protected_from_scale_in=new_instances_protected_from_scale_in,
|
||||||
)
|
)
|
||||||
return group
|
return group
|
||||||
|
@ -81,6 +81,7 @@ class AutoScalingResponse(BaseResponse):
|
|||||||
min_size=self._get_int_param("MinSize"),
|
min_size=self._get_int_param("MinSize"),
|
||||||
instance_id=self._get_param("InstanceId"),
|
instance_id=self._get_param("InstanceId"),
|
||||||
launch_config_name=self._get_param("LaunchConfigurationName"),
|
launch_config_name=self._get_param("LaunchConfigurationName"),
|
||||||
|
launch_template=self._get_dict_param("LaunchTemplate."),
|
||||||
vpc_zone_identifier=self._get_param("VPCZoneIdentifier"),
|
vpc_zone_identifier=self._get_param("VPCZoneIdentifier"),
|
||||||
default_cooldown=self._get_int_param("DefaultCooldown"),
|
default_cooldown=self._get_int_param("DefaultCooldown"),
|
||||||
health_check_period=self._get_int_param("HealthCheckGracePeriod"),
|
health_check_period=self._get_int_param("HealthCheckGracePeriod"),
|
||||||
@ -197,6 +198,7 @@ class AutoScalingResponse(BaseResponse):
|
|||||||
max_size=self._get_int_param("MaxSize"),
|
max_size=self._get_int_param("MaxSize"),
|
||||||
min_size=self._get_int_param("MinSize"),
|
min_size=self._get_int_param("MinSize"),
|
||||||
launch_config_name=self._get_param("LaunchConfigurationName"),
|
launch_config_name=self._get_param("LaunchConfigurationName"),
|
||||||
|
launch_template=self._get_dict_param("LaunchTemplate."),
|
||||||
vpc_zone_identifier=self._get_param("VPCZoneIdentifier"),
|
vpc_zone_identifier=self._get_param("VPCZoneIdentifier"),
|
||||||
default_cooldown=self._get_int_param("DefaultCooldown"),
|
default_cooldown=self._get_int_param("DefaultCooldown"),
|
||||||
health_check_period=self._get_int_param("HealthCheckGracePeriod"),
|
health_check_period=self._get_int_param("HealthCheckGracePeriod"),
|
||||||
@ -573,14 +575,31 @@ DESCRIBE_AUTOSCALING_GROUPS_TEMPLATE = """<DescribeAutoScalingGroupsResponse xml
|
|||||||
<HealthCheckType>{{ group.health_check_type }}</HealthCheckType>
|
<HealthCheckType>{{ group.health_check_type }}</HealthCheckType>
|
||||||
<CreatedTime>2013-05-06T17:47:15.107Z</CreatedTime>
|
<CreatedTime>2013-05-06T17:47:15.107Z</CreatedTime>
|
||||||
<EnabledMetrics/>
|
<EnabledMetrics/>
|
||||||
|
{% if group.launch_config_name %}
|
||||||
<LaunchConfigurationName>{{ group.launch_config_name }}</LaunchConfigurationName>
|
<LaunchConfigurationName>{{ group.launch_config_name }}</LaunchConfigurationName>
|
||||||
|
{% elif group.launch_template %}
|
||||||
|
<LaunchTemplate>
|
||||||
|
<LaunchTemplateId>{{ group.launch_template.id }}</LaunchTemplateId>
|
||||||
|
<Version>{{ group.launch_template_version }}</Version>
|
||||||
|
<LaunchTemplateName>{{ group.launch_template.name }}</LaunchTemplateName>
|
||||||
|
</LaunchTemplate>
|
||||||
|
{% endif %}
|
||||||
<Instances>
|
<Instances>
|
||||||
{% for instance_state in group.instance_states %}
|
{% for instance_state in group.instance_states %}
|
||||||
<member>
|
<member>
|
||||||
<HealthStatus>{{ instance_state.health_status }}</HealthStatus>
|
<HealthStatus>{{ instance_state.health_status }}</HealthStatus>
|
||||||
<AvailabilityZone>{{ instance_state.instance.placement }}</AvailabilityZone>
|
<AvailabilityZone>{{ instance_state.instance.placement }}</AvailabilityZone>
|
||||||
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
||||||
|
<InstanceType>{{ instance_state.instance.instance_type }}</InstanceType>
|
||||||
|
{% if group.launch_config_name %}
|
||||||
<LaunchConfigurationName>{{ group.launch_config_name }}</LaunchConfigurationName>
|
<LaunchConfigurationName>{{ group.launch_config_name }}</LaunchConfigurationName>
|
||||||
|
{% elif group.launch_template %}
|
||||||
|
<LaunchTemplate>
|
||||||
|
<LaunchTemplateId>{{ group.launch_template.id }}</LaunchTemplateId>
|
||||||
|
<Version>{{ group.launch_template_version }}</Version>
|
||||||
|
<LaunchTemplateName>{{ group.launch_template.name }}</LaunchTemplateName>
|
||||||
|
</LaunchTemplate>
|
||||||
|
{% endif %}
|
||||||
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
||||||
<ProtectedFromScaleIn>{{ instance_state.protected_from_scale_in|string|lower }}</ProtectedFromScaleIn>
|
<ProtectedFromScaleIn>{{ instance_state.protected_from_scale_in|string|lower }}</ProtectedFromScaleIn>
|
||||||
</member>
|
</member>
|
||||||
@ -666,7 +685,16 @@ DESCRIBE_AUTOSCALING_INSTANCES_TEMPLATE = """<DescribeAutoScalingInstancesRespon
|
|||||||
<AutoScalingGroupName>{{ instance_state.instance.autoscaling_group.name }}</AutoScalingGroupName>
|
<AutoScalingGroupName>{{ instance_state.instance.autoscaling_group.name }}</AutoScalingGroupName>
|
||||||
<AvailabilityZone>{{ instance_state.instance.placement }}</AvailabilityZone>
|
<AvailabilityZone>{{ instance_state.instance.placement }}</AvailabilityZone>
|
||||||
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
||||||
|
<InstanceType>{{ instance_state.instance.instance_type }}</InstanceType>
|
||||||
|
{% if instance_state.instance.autoscaling_group.launch_config_name %}
|
||||||
<LaunchConfigurationName>{{ instance_state.instance.autoscaling_group.launch_config_name }}</LaunchConfigurationName>
|
<LaunchConfigurationName>{{ instance_state.instance.autoscaling_group.launch_config_name }}</LaunchConfigurationName>
|
||||||
|
{% elif instance_state.instance.autoscaling_group.launch_template %}
|
||||||
|
<LaunchTemplate>
|
||||||
|
<LaunchTemplateId>{{ instance_state.instance.autoscaling_group.launch_template.id }}</LaunchTemplateId>
|
||||||
|
<Version>{{ instance_state.instance.autoscaling_group.launch_template_version }}</Version>
|
||||||
|
<LaunchTemplateName>{{ instance_state.instance.autoscaling_group.launch_template.name }}</LaunchTemplateName>
|
||||||
|
</LaunchTemplate>
|
||||||
|
{% endif %}
|
||||||
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
||||||
<ProtectedFromScaleIn>{{ instance_state.protected_from_scale_in|string|lower }}</ProtectedFromScaleIn>
|
<ProtectedFromScaleIn>{{ instance_state.protected_from_scale_in|string|lower }}</ProtectedFromScaleIn>
|
||||||
</member>
|
</member>
|
||||||
|
@ -538,8 +538,8 @@ class BaseResponse(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
|
|
||||||
returns
|
returns
|
||||||
{
|
{
|
||||||
"SlaveInstanceType": "m1.small",
|
"slave_instance_type": "m1.small",
|
||||||
"InstanceCount": "1",
|
"instance_count": "1",
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
params = {}
|
params = {}
|
||||||
|
@ -5386,6 +5386,22 @@ class LaunchTemplateVersion(object):
|
|||||||
self.description = description
|
self.description = description
|
||||||
self.create_time = utc_date_and_time()
|
self.create_time = utc_date_and_time()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def image_id(self):
|
||||||
|
return self.data.get("ImageId", "")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def instance_type(self):
|
||||||
|
return self.data.get("InstanceType", "")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def security_groups(self):
|
||||||
|
return self.data.get("SecurityGroups", [])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data(self):
|
||||||
|
return self.data.get("UserData", "")
|
||||||
|
|
||||||
|
|
||||||
class LaunchTemplate(TaggedEC2Resource):
|
class LaunchTemplate(TaggedEC2Resource):
|
||||||
def __init__(self, backend, name, template_data, version_description):
|
def __init__(self, backend, name, template_data, version_description):
|
||||||
|
@ -17,6 +17,7 @@ from moto import (
|
|||||||
mock_elb,
|
mock_elb,
|
||||||
mock_autoscaling_deprecated,
|
mock_autoscaling_deprecated,
|
||||||
mock_ec2,
|
mock_ec2,
|
||||||
|
mock_cloudformation,
|
||||||
)
|
)
|
||||||
from tests.helpers import requires_boto_gte
|
from tests.helpers import requires_boto_gte
|
||||||
|
|
||||||
@ -164,7 +165,7 @@ def test_list_many_autoscaling_groups():
|
|||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_list_many_autoscaling_groups():
|
def test_propogate_tags():
|
||||||
mocked_networking = setup_networking()
|
mocked_networking = setup_networking()
|
||||||
conn = boto3.client("autoscaling", region_name="us-east-1")
|
conn = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
conn.create_launch_configuration(LaunchConfigurationName="TestLC")
|
conn.create_launch_configuration(LaunchConfigurationName="TestLC")
|
||||||
@ -692,7 +693,7 @@ def test_detach_load_balancer():
|
|||||||
def test_create_autoscaling_group_boto3():
|
def test_create_autoscaling_group_boto3():
|
||||||
mocked_networking = setup_networking()
|
mocked_networking = setup_networking()
|
||||||
client = boto3.client("autoscaling", region_name="us-east-1")
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
_ = client.create_launch_configuration(
|
client.create_launch_configuration(
|
||||||
LaunchConfigurationName="test_launch_configuration"
|
LaunchConfigurationName="test_launch_configuration"
|
||||||
)
|
)
|
||||||
response = client.create_auto_scaling_group(
|
response = client.create_auto_scaling_group(
|
||||||
@ -798,13 +799,171 @@ def test_create_autoscaling_group_from_invalid_instance_id():
|
|||||||
|
|
||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
def test_describe_autoscaling_groups_boto3():
|
@mock_ec2
|
||||||
|
def test_create_autoscaling_group_from_template():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
response = client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={
|
||||||
|
"LaunchTemplateId": template["LaunchTemplateId"],
|
||||||
|
"Version": str(template["LatestVersionNumber"]),
|
||||||
|
},
|
||||||
|
MinSize=1,
|
||||||
|
MaxSize=3,
|
||||||
|
DesiredCapacity=2,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
|
)
|
||||||
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_autoscaling_group_no_template_ref():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={"Version": str(template["LatestVersionNumber"])},
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
|
)
|
||||||
|
ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("ValidationError")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Valid requests must contain either launchTemplateId or LaunchTemplateName"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_autoscaling_group_multiple_template_ref():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={
|
||||||
|
"LaunchTemplateId": template["LaunchTemplateId"],
|
||||||
|
"LaunchTemplateName": template["LaunchTemplateName"],
|
||||||
|
"Version": str(template["LatestVersionNumber"]),
|
||||||
|
},
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
|
)
|
||||||
|
ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("ValidationError")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Valid requests must contain either launchTemplateId or LaunchTemplateName"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
def test_create_autoscaling_group_boto3_no_launch_configuration():
|
||||||
mocked_networking = setup_networking()
|
mocked_networking = setup_networking()
|
||||||
client = boto3.client("autoscaling", region_name="us-east-1")
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
_ = client.create_launch_configuration(
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
|
)
|
||||||
|
ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("ValidationError")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Valid requests must contain either LaunchTemplate, LaunchConfigurationName, "
|
||||||
|
"InstanceId or MixedInstancesPolicy parameter."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_autoscaling_group_boto3_multiple_launch_configurations():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
client.create_launch_configuration(
|
||||||
LaunchConfigurationName="test_launch_configuration"
|
LaunchConfigurationName="test_launch_configuration"
|
||||||
)
|
)
|
||||||
_ = client.create_auto_scaling_group(
|
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchConfigurationName="test_launch_configuration",
|
||||||
|
LaunchTemplate={
|
||||||
|
"LaunchTemplateId": template["LaunchTemplateId"],
|
||||||
|
"Version": str(template["LatestVersionNumber"]),
|
||||||
|
},
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
|
)
|
||||||
|
ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("ValidationError")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Valid requests must contain either LaunchTemplate, LaunchConfigurationName, "
|
||||||
|
"InstanceId or MixedInstancesPolicy parameter."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
def test_describe_autoscaling_groups_boto3_launch_config():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName="test_launch_configuration", InstanceType="t2.micro",
|
||||||
|
)
|
||||||
|
client.create_auto_scaling_group(
|
||||||
AutoScalingGroupName="test_asg",
|
AutoScalingGroupName="test_asg",
|
||||||
LaunchConfigurationName="test_launch_configuration",
|
LaunchConfigurationName="test_launch_configuration",
|
||||||
MinSize=0,
|
MinSize=0,
|
||||||
@ -818,22 +977,72 @@ def test_describe_autoscaling_groups_boto3():
|
|||||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
group = response["AutoScalingGroups"][0]
|
group = response["AutoScalingGroups"][0]
|
||||||
group["AutoScalingGroupName"].should.equal("test_asg")
|
group["AutoScalingGroupName"].should.equal("test_asg")
|
||||||
|
group["LaunchConfigurationName"].should.equal("test_launch_configuration")
|
||||||
|
group.should_not.have.key("LaunchTemplate")
|
||||||
group["AvailabilityZones"].should.equal(["us-east-1a"])
|
group["AvailabilityZones"].should.equal(["us-east-1a"])
|
||||||
group["VPCZoneIdentifier"].should.equal(mocked_networking["subnet1"])
|
group["VPCZoneIdentifier"].should.equal(mocked_networking["subnet1"])
|
||||||
group["NewInstancesProtectedFromScaleIn"].should.equal(True)
|
group["NewInstancesProtectedFromScaleIn"].should.equal(True)
|
||||||
for instance in group["Instances"]:
|
for instance in group["Instances"]:
|
||||||
|
instance["LaunchConfigurationName"].should.equal("test_launch_configuration")
|
||||||
|
instance.should_not.have.key("LaunchTemplate")
|
||||||
instance["AvailabilityZone"].should.equal("us-east-1a")
|
instance["AvailabilityZone"].should.equal("us-east-1a")
|
||||||
instance["ProtectedFromScaleIn"].should.equal(True)
|
instance["ProtectedFromScaleIn"].should.equal(True)
|
||||||
|
instance["InstanceType"].should.equal("t2.micro")
|
||||||
|
|
||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
def test_describe_autoscaling_instances_boto3():
|
@mock_ec2
|
||||||
|
def test_describe_autoscaling_groups_boto3_launch_template():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={"LaunchTemplateName": "test_launch_template", "Version": "1"},
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=True,
|
||||||
|
)
|
||||||
|
expected_launch_template = {
|
||||||
|
"LaunchTemplateId": template["LaunchTemplateId"],
|
||||||
|
"LaunchTemplateName": "test_launch_template",
|
||||||
|
"Version": "1",
|
||||||
|
}
|
||||||
|
|
||||||
|
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||||
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
|
group = response["AutoScalingGroups"][0]
|
||||||
|
group["AutoScalingGroupName"].should.equal("test_asg")
|
||||||
|
group["LaunchTemplate"].should.equal(expected_launch_template)
|
||||||
|
group.should_not.have.key("LaunchConfigurationName")
|
||||||
|
group["AvailabilityZones"].should.equal(["us-east-1a"])
|
||||||
|
group["VPCZoneIdentifier"].should.equal(mocked_networking["subnet1"])
|
||||||
|
group["NewInstancesProtectedFromScaleIn"].should.equal(True)
|
||||||
|
for instance in group["Instances"]:
|
||||||
|
instance["LaunchTemplate"].should.equal(expected_launch_template)
|
||||||
|
instance.should_not.have.key("LaunchConfigurationName")
|
||||||
|
instance["AvailabilityZone"].should.equal("us-east-1a")
|
||||||
|
instance["ProtectedFromScaleIn"].should.equal(True)
|
||||||
|
instance["InstanceType"].should.equal("t2.micro")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
def test_describe_autoscaling_instances_boto3_launch_config():
|
||||||
mocked_networking = setup_networking()
|
mocked_networking = setup_networking()
|
||||||
client = boto3.client("autoscaling", region_name="us-east-1")
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
_ = client.create_launch_configuration(
|
client.create_launch_configuration(
|
||||||
LaunchConfigurationName="test_launch_configuration"
|
LaunchConfigurationName="test_launch_configuration", InstanceType="t2.micro",
|
||||||
)
|
)
|
||||||
_ = client.create_auto_scaling_group(
|
client.create_auto_scaling_group(
|
||||||
AutoScalingGroupName="test_asg",
|
AutoScalingGroupName="test_asg",
|
||||||
LaunchConfigurationName="test_launch_configuration",
|
LaunchConfigurationName="test_launch_configuration",
|
||||||
MinSize=0,
|
MinSize=0,
|
||||||
@ -846,9 +1055,51 @@ def test_describe_autoscaling_instances_boto3():
|
|||||||
response = client.describe_auto_scaling_instances()
|
response = client.describe_auto_scaling_instances()
|
||||||
len(response["AutoScalingInstances"]).should.equal(5)
|
len(response["AutoScalingInstances"]).should.equal(5)
|
||||||
for instance in response["AutoScalingInstances"]:
|
for instance in response["AutoScalingInstances"]:
|
||||||
|
instance["LaunchConfigurationName"].should.equal("test_launch_configuration")
|
||||||
|
instance.should_not.have.key("LaunchTemplate")
|
||||||
instance["AutoScalingGroupName"].should.equal("test_asg")
|
instance["AutoScalingGroupName"].should.equal("test_asg")
|
||||||
instance["AvailabilityZone"].should.equal("us-east-1a")
|
instance["AvailabilityZone"].should.equal("us-east-1a")
|
||||||
instance["ProtectedFromScaleIn"].should.equal(True)
|
instance["ProtectedFromScaleIn"].should.equal(True)
|
||||||
|
instance["InstanceType"].should.equal("t2.micro")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_ec2
|
||||||
|
def test_describe_autoscaling_instances_boto3_launch_template():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={"LaunchTemplateName": "test_launch_template", "Version": "1"},
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=True,
|
||||||
|
)
|
||||||
|
expected_launch_template = {
|
||||||
|
"LaunchTemplateId": template["LaunchTemplateId"],
|
||||||
|
"LaunchTemplateName": "test_launch_template",
|
||||||
|
"Version": "1",
|
||||||
|
}
|
||||||
|
|
||||||
|
response = client.describe_auto_scaling_instances()
|
||||||
|
len(response["AutoScalingInstances"]).should.equal(5)
|
||||||
|
for instance in response["AutoScalingInstances"]:
|
||||||
|
instance["LaunchTemplate"].should.equal(expected_launch_template)
|
||||||
|
instance.should_not.have.key("LaunchConfigurationName")
|
||||||
|
instance["AutoScalingGroupName"].should.equal("test_asg")
|
||||||
|
instance["AvailabilityZone"].should.equal("us-east-1a")
|
||||||
|
instance["ProtectedFromScaleIn"].should.equal(True)
|
||||||
|
instance["InstanceType"].should.equal("t2.micro")
|
||||||
|
|
||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
@ -885,13 +1136,16 @@ def test_describe_autoscaling_instances_instanceid_filter():
|
|||||||
|
|
||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
def test_update_autoscaling_group_boto3():
|
def test_update_autoscaling_group_boto3_launch_config():
|
||||||
mocked_networking = setup_networking()
|
mocked_networking = setup_networking()
|
||||||
client = boto3.client("autoscaling", region_name="us-east-1")
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
_ = client.create_launch_configuration(
|
client.create_launch_configuration(
|
||||||
LaunchConfigurationName="test_launch_configuration"
|
LaunchConfigurationName="test_launch_configuration"
|
||||||
)
|
)
|
||||||
_ = client.create_auto_scaling_group(
|
client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName="test_launch_configuration_new"
|
||||||
|
)
|
||||||
|
client.create_auto_scaling_group(
|
||||||
AutoScalingGroupName="test_asg",
|
AutoScalingGroupName="test_asg",
|
||||||
LaunchConfigurationName="test_launch_configuration",
|
LaunchConfigurationName="test_launch_configuration",
|
||||||
MinSize=0,
|
MinSize=0,
|
||||||
@ -901,8 +1155,9 @@ def test_update_autoscaling_group_boto3():
|
|||||||
NewInstancesProtectedFromScaleIn=True,
|
NewInstancesProtectedFromScaleIn=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
_ = client.update_auto_scaling_group(
|
client.update_auto_scaling_group(
|
||||||
AutoScalingGroupName="test_asg",
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchConfigurationName="test_launch_configuration_new",
|
||||||
MinSize=1,
|
MinSize=1,
|
||||||
VPCZoneIdentifier="{subnet1},{subnet2}".format(
|
VPCZoneIdentifier="{subnet1},{subnet2}".format(
|
||||||
subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
|
subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
|
||||||
@ -912,6 +1167,64 @@ def test_update_autoscaling_group_boto3():
|
|||||||
|
|
||||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||||
group = response["AutoScalingGroups"][0]
|
group = response["AutoScalingGroups"][0]
|
||||||
|
group["LaunchConfigurationName"].should.equal("test_launch_configuration_new")
|
||||||
|
group["MinSize"].should.equal(1)
|
||||||
|
set(group["AvailabilityZones"]).should.equal({"us-east-1a", "us-east-1b"})
|
||||||
|
group["NewInstancesProtectedFromScaleIn"].should.equal(False)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_ec2
|
||||||
|
def test_update_autoscaling_group_boto3_launch_template():
|
||||||
|
mocked_networking = setup_networking()
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
template = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template_new",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-1ea5b10a3d8867db4",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)["LaunchTemplate"]
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={"LaunchTemplateName": "test_launch_template", "Version": "1"},
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5,
|
||||||
|
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||||
|
NewInstancesProtectedFromScaleIn=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
client.update_auto_scaling_group(
|
||||||
|
AutoScalingGroupName="test_asg",
|
||||||
|
LaunchTemplate={
|
||||||
|
"LaunchTemplateName": "test_launch_template_new",
|
||||||
|
"Version": "1",
|
||||||
|
},
|
||||||
|
MinSize=1,
|
||||||
|
VPCZoneIdentifier="{subnet1},{subnet2}".format(
|
||||||
|
subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
|
||||||
|
),
|
||||||
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
expected_launch_template = {
|
||||||
|
"LaunchTemplateId": template["LaunchTemplateId"],
|
||||||
|
"LaunchTemplateName": "test_launch_template_new",
|
||||||
|
"Version": "1",
|
||||||
|
}
|
||||||
|
|
||||||
|
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||||
|
group = response["AutoScalingGroups"][0]
|
||||||
|
group["LaunchTemplate"].should.equal(expected_launch_template)
|
||||||
group["MinSize"].should.equal(1)
|
group["MinSize"].should.equal(1)
|
||||||
set(group["AvailabilityZones"]).should.equal({"us-east-1a", "us-east-1b"})
|
set(group["AvailabilityZones"]).should.equal({"us-east-1a", "us-east-1b"})
|
||||||
group["NewInstancesProtectedFromScaleIn"].should.equal(False)
|
group["NewInstancesProtectedFromScaleIn"].should.equal(False)
|
||||||
@ -966,7 +1279,7 @@ def test_update_autoscaling_group_max_size_desired_capacity_change():
|
|||||||
|
|
||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
def test_autoscaling_taqs_update_boto3():
|
def test_autoscaling_tags_update_boto3():
|
||||||
mocked_networking = setup_networking()
|
mocked_networking = setup_networking()
|
||||||
client = boto3.client("autoscaling", region_name="us-east-1")
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
_ = client.create_launch_configuration(
|
_ = client.create_launch_configuration(
|
||||||
|
276
tests/test_autoscaling/test_cloudformation.py
Normal file
276
tests/test_autoscaling/test_cloudformation.py
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
import boto3
|
||||||
|
import sure # noqa
|
||||||
|
|
||||||
|
from moto import (
|
||||||
|
mock_autoscaling,
|
||||||
|
mock_cloudformation,
|
||||||
|
mock_ec2,
|
||||||
|
)
|
||||||
|
|
||||||
|
from utils import setup_networking
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_cloudformation
|
||||||
|
def test_launch_configuration():
|
||||||
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
|
||||||
|
stack_name = "test-launch-configuration"
|
||||||
|
|
||||||
|
cf_template = """
|
||||||
|
Resources:
|
||||||
|
LaunchConfiguration:
|
||||||
|
Type: AWS::AutoScaling::LaunchConfiguration
|
||||||
|
Properties:
|
||||||
|
ImageId: ami-0cc293023f983ed53
|
||||||
|
InstanceType: t2.micro
|
||||||
|
LaunchConfigurationName: test_launch_configuration
|
||||||
|
Outputs:
|
||||||
|
LaunchConfigurationName:
|
||||||
|
Value: !Ref LaunchConfiguration
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
cf_client.create_stack(
|
||||||
|
StackName=stack_name, TemplateBody=cf_template,
|
||||||
|
)
|
||||||
|
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
||||||
|
stack["Outputs"][0]["OutputValue"].should.be.equal("test_launch_configuration")
|
||||||
|
|
||||||
|
lc = client.describe_launch_configurations()["LaunchConfigurations"][0]
|
||||||
|
lc["LaunchConfigurationName"].should.be.equal("test_launch_configuration")
|
||||||
|
lc["ImageId"].should.be.equal("ami-0cc293023f983ed53")
|
||||||
|
lc["InstanceType"].should.be.equal("t2.micro")
|
||||||
|
|
||||||
|
cf_template = """
|
||||||
|
Resources:
|
||||||
|
LaunchConfiguration:
|
||||||
|
Type: AWS::AutoScaling::LaunchConfiguration
|
||||||
|
Properties:
|
||||||
|
ImageId: ami-1ea5b10a3d8867db4
|
||||||
|
InstanceType: m5.large
|
||||||
|
LaunchConfigurationName: test_launch_configuration
|
||||||
|
Outputs:
|
||||||
|
LaunchConfigurationName:
|
||||||
|
Value: !Ref LaunchConfiguration
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
cf_client.update_stack(
|
||||||
|
StackName=stack_name, TemplateBody=cf_template,
|
||||||
|
)
|
||||||
|
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
||||||
|
stack["Outputs"][0]["OutputValue"].should.be.equal("test_launch_configuration")
|
||||||
|
|
||||||
|
lc = client.describe_launch_configurations()["LaunchConfigurations"][0]
|
||||||
|
lc["LaunchConfigurationName"].should.be.equal("test_launch_configuration")
|
||||||
|
lc["ImageId"].should.be.equal("ami-1ea5b10a3d8867db4")
|
||||||
|
lc["InstanceType"].should.be.equal("m5.large")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_cloudformation
|
||||||
|
def test_autoscaling_group_from_launch_config():
|
||||||
|
subnet_id = setup_networking()["subnet1"]
|
||||||
|
|
||||||
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
|
||||||
|
client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName="test_launch_configuration", InstanceType="t2.micro",
|
||||||
|
)
|
||||||
|
stack_name = "test-auto-scaling-group"
|
||||||
|
|
||||||
|
cf_template = """
|
||||||
|
Parameters:
|
||||||
|
SubnetId:
|
||||||
|
Type: AWS::EC2::Subnet::Id
|
||||||
|
Resources:
|
||||||
|
AutoScalingGroup:
|
||||||
|
Type: AWS::AutoScaling::AutoScalingGroup
|
||||||
|
Properties:
|
||||||
|
AutoScalingGroupName: test_auto_scaling_group
|
||||||
|
AvailabilityZones:
|
||||||
|
- us-east-1a
|
||||||
|
LaunchConfigurationName: test_launch_configuration
|
||||||
|
MaxSize: "5"
|
||||||
|
MinSize: "1"
|
||||||
|
VPCZoneIdentifier:
|
||||||
|
- !Ref SubnetId
|
||||||
|
Outputs:
|
||||||
|
AutoScalingGroupName:
|
||||||
|
Value: !Ref AutoScalingGroup
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
cf_client.create_stack(
|
||||||
|
StackName=stack_name,
|
||||||
|
TemplateBody=cf_template,
|
||||||
|
Parameters=[{"ParameterKey": "SubnetId", "ParameterValue": subnet_id}],
|
||||||
|
)
|
||||||
|
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
||||||
|
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
|
||||||
|
|
||||||
|
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
|
||||||
|
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
|
||||||
|
asg["MinSize"].should.be.equal(1)
|
||||||
|
asg["MaxSize"].should.be.equal(5)
|
||||||
|
asg["LaunchConfigurationName"].should.be.equal("test_launch_configuration")
|
||||||
|
|
||||||
|
client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName="test_launch_configuration_new",
|
||||||
|
InstanceType="t2.micro",
|
||||||
|
)
|
||||||
|
|
||||||
|
cf_template = """
|
||||||
|
Parameters:
|
||||||
|
SubnetId:
|
||||||
|
Type: AWS::EC2::Subnet::Id
|
||||||
|
Resources:
|
||||||
|
AutoScalingGroup:
|
||||||
|
Type: AWS::AutoScaling::AutoScalingGroup
|
||||||
|
Properties:
|
||||||
|
AutoScalingGroupName: test_auto_scaling_group
|
||||||
|
AvailabilityZones:
|
||||||
|
- us-east-1a
|
||||||
|
LaunchConfigurationName: test_launch_configuration_new
|
||||||
|
MaxSize: "6"
|
||||||
|
MinSize: "2"
|
||||||
|
VPCZoneIdentifier:
|
||||||
|
- !Ref SubnetId
|
||||||
|
Outputs:
|
||||||
|
AutoScalingGroupName:
|
||||||
|
Value: !Ref AutoScalingGroup
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
cf_client.update_stack(
|
||||||
|
StackName=stack_name,
|
||||||
|
TemplateBody=cf_template,
|
||||||
|
Parameters=[{"ParameterKey": "SubnetId", "ParameterValue": subnet_id}],
|
||||||
|
)
|
||||||
|
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
||||||
|
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
|
||||||
|
|
||||||
|
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
|
||||||
|
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
|
||||||
|
asg["MinSize"].should.be.equal(2)
|
||||||
|
asg["MaxSize"].should.be.equal(6)
|
||||||
|
asg["LaunchConfigurationName"].should.be.equal("test_launch_configuration_new")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
@mock_cloudformation
|
||||||
|
@mock_ec2
|
||||||
|
def test_autoscaling_group_from_launch_template():
|
||||||
|
subnet_id = setup_networking()["subnet1"]
|
||||||
|
|
||||||
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||||
|
|
||||||
|
template_response = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-0cc293023f983ed53",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
launch_template_id = template_response["LaunchTemplate"]["LaunchTemplateId"]
|
||||||
|
stack_name = "test-auto-scaling-group"
|
||||||
|
|
||||||
|
cf_template = """
|
||||||
|
Parameters:
|
||||||
|
SubnetId:
|
||||||
|
Type: AWS::EC2::Subnet::Id
|
||||||
|
LaunchTemplateId:
|
||||||
|
Type: String
|
||||||
|
Resources:
|
||||||
|
AutoScalingGroup:
|
||||||
|
Type: AWS::AutoScaling::AutoScalingGroup
|
||||||
|
Properties:
|
||||||
|
AutoScalingGroupName: test_auto_scaling_group
|
||||||
|
AvailabilityZones:
|
||||||
|
- us-east-1a
|
||||||
|
LaunchTemplate:
|
||||||
|
LaunchTemplateId: !Ref LaunchTemplateId
|
||||||
|
Version: "1"
|
||||||
|
MaxSize: "5"
|
||||||
|
MinSize: "1"
|
||||||
|
VPCZoneIdentifier:
|
||||||
|
- !Ref SubnetId
|
||||||
|
Outputs:
|
||||||
|
AutoScalingGroupName:
|
||||||
|
Value: !Ref AutoScalingGroup
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
cf_client.create_stack(
|
||||||
|
StackName=stack_name,
|
||||||
|
TemplateBody=cf_template,
|
||||||
|
Parameters=[
|
||||||
|
{"ParameterKey": "SubnetId", "ParameterValue": subnet_id},
|
||||||
|
{"ParameterKey": "LaunchTemplateId", "ParameterValue": launch_template_id},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
||||||
|
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
|
||||||
|
|
||||||
|
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
|
||||||
|
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
|
||||||
|
asg["MinSize"].should.be.equal(1)
|
||||||
|
asg["MaxSize"].should.be.equal(5)
|
||||||
|
lt = asg["LaunchTemplate"]
|
||||||
|
lt["LaunchTemplateId"].should.be.equal(launch_template_id)
|
||||||
|
lt["LaunchTemplateName"].should.be.equal("test_launch_template")
|
||||||
|
lt["Version"].should.be.equal("1")
|
||||||
|
|
||||||
|
template_response = ec2_client.create_launch_template(
|
||||||
|
LaunchTemplateName="test_launch_template_new",
|
||||||
|
LaunchTemplateData={
|
||||||
|
"ImageId": "ami-1ea5b10a3d8867db4",
|
||||||
|
"InstanceType": "m5.large",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
launch_template_id = template_response["LaunchTemplate"]["LaunchTemplateId"]
|
||||||
|
|
||||||
|
cf_template = """
|
||||||
|
Parameters:
|
||||||
|
SubnetId:
|
||||||
|
Type: AWS::EC2::Subnet::Id
|
||||||
|
LaunchTemplateId:
|
||||||
|
Type: String
|
||||||
|
Resources:
|
||||||
|
AutoScalingGroup:
|
||||||
|
Type: AWS::AutoScaling::AutoScalingGroup
|
||||||
|
Properties:
|
||||||
|
AutoScalingGroupName: test_auto_scaling_group
|
||||||
|
AvailabilityZones:
|
||||||
|
- us-east-1a
|
||||||
|
LaunchTemplate:
|
||||||
|
LaunchTemplateId: !Ref LaunchTemplateId
|
||||||
|
Version: "1"
|
||||||
|
MaxSize: "6"
|
||||||
|
MinSize: "2"
|
||||||
|
VPCZoneIdentifier:
|
||||||
|
- !Ref SubnetId
|
||||||
|
Outputs:
|
||||||
|
AutoScalingGroupName:
|
||||||
|
Value: !Ref AutoScalingGroup
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
cf_client.update_stack(
|
||||||
|
StackName=stack_name,
|
||||||
|
TemplateBody=cf_template,
|
||||||
|
Parameters=[
|
||||||
|
{"ParameterKey": "SubnetId", "ParameterValue": subnet_id},
|
||||||
|
{"ParameterKey": "LaunchTemplateId", "ParameterValue": launch_template_id},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
||||||
|
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
|
||||||
|
|
||||||
|
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
|
||||||
|
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
|
||||||
|
asg["MinSize"].should.be.equal(2)
|
||||||
|
asg["MaxSize"].should.be.equal(6)
|
||||||
|
lt = asg["LaunchTemplate"]
|
||||||
|
lt["LaunchTemplateId"].should.be.equal(launch_template_id)
|
||||||
|
lt["LaunchTemplateName"].should.be.equal("test_launch_template_new")
|
||||||
|
lt["Version"].should.be.equal("1")
|
Loading…
Reference in New Issue
Block a user