Asg mixed instance types (#67045)
* merge from origin pr 55067 * handle update existing asg with mixed-instance-policy * fix documentation and append output * update output documentation * update documentation version added * add integration test for mixed instance policy using launch template * add changelog fragment * Update lib/ansible/modules/cloud/amazon/ec2_asg.py Co-Authored-By: Mark Chappell <mchappel@redhat.com> * Update lib/ansible/modules/cloud/amazon/ec2_asg.py Co-Authored-By: Mark Chappell <mchappel@redhat.com> * Update lib/ansible/modules/cloud/amazon/ec2_asg.py Co-Authored-By: Jill R <4121322+jillr@users.noreply.github.com> * add warning about botocore version and add expand example documentation * Update changelogs/fragments/67045-ec2_asg_mixed_instance_policy.yml Co-Authored-By: Mark Chappell <mchappel@redhat.com> * Update lib/ansible/modules/cloud/amazon/ec2_asg.py Co-Authored-By: Mark Chappell <mchappel@redhat.com> * Update lib/ansible/modules/cloud/amazon/ec2_asg.py Co-Authored-By: Mark Chappell <mchappel@redhat.com> * remove useless line Co-authored-by: Yi-Tse Hong <yitse.hong@soocii.me> Co-authored-by: Mark Chappell <mchappel@redhat.com> Co-authored-by: Jill R <4121322+jillr@users.noreply.github.com>
This commit is contained in:
parent
f23cee2145
commit
822077fefd
3 changed files with 129 additions and 3 deletions
changelogs/fragments
lib/ansible/modules/cloud/amazon
test/integration/targets/ec2_asg/tasks
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- ec2_asg - Add the ability to use mixed_instance_policy in launch template driven autoscaling groups
|
|
@ -81,6 +81,20 @@ options:
|
|||
description:
|
||||
- Maximum number of instances in group, if unspecified then the current group value will be used.
|
||||
type: int
|
||||
mixed_instances_policy:
|
||||
description:
|
||||
- A mixed instance policy to use for the ASG.
|
||||
- Only used when the ASG is configured to use a Launch Template (I(launch_template)).
|
||||
- 'See also U(https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-autoscalinggroup-mixedinstancespolicy.html)'
|
||||
required: false
|
||||
version_added: "2.10"
|
||||
suboptions:
|
||||
instance_types:
|
||||
description:
|
||||
- A list of instance_types.
|
||||
type: list
|
||||
elements: str
|
||||
type: dict
|
||||
placement_group:
|
||||
description:
|
||||
- Physical location of your cluster placement group created in Amazon EC2.
|
||||
|
@ -329,6 +343,28 @@ EXAMPLES = '''
|
|||
- environment: production
|
||||
propagate_at_launch: no
|
||||
|
||||
# Basic Configuration with Launch Template using mixed instance policy
|
||||
|
||||
- ec2_asg:
|
||||
name: special
|
||||
load_balancers: [ 'lb1', 'lb2' ]
|
||||
availability_zones: [ 'eu-west-1a', 'eu-west-1b' ]
|
||||
launch_template:
|
||||
version: '1'
|
||||
launch_template_name: 'lt-example'
|
||||
launch_template_id: 'lt-123456'
|
||||
mixed_instances_policy:
|
||||
instance_types:
|
||||
- t3a.large
|
||||
- t3.large
|
||||
- t2.large
|
||||
min_size: 1
|
||||
max_size: 10
|
||||
desired_capacity: 5
|
||||
vpc_zone_identifier: [ 'subnet-abcd1234', 'subnet-1a2b3c4d' ]
|
||||
tags:
|
||||
- environment: production
|
||||
propagate_at_launch: no
|
||||
|
||||
'''
|
||||
|
||||
|
@ -426,6 +462,11 @@ min_size:
|
|||
returned: success
|
||||
type: int
|
||||
sample: 1
|
||||
mixed_instance_policy:
|
||||
description: Returns the list of instance types if a mixed instance policy is set.
|
||||
returned: success
|
||||
type: list
|
||||
sample: ["t3.micro", "t3a.micro"]
|
||||
pending_instances:
|
||||
description: Number of instances in pending state
|
||||
returned: success
|
||||
|
@ -511,6 +552,8 @@ try:
|
|||
except ImportError:
|
||||
pass # will be detected by imported HAS_BOTO3
|
||||
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
|
||||
ASG_ATTRIBUTES = ('AvailabilityZones', 'DefaultCooldown', 'DesiredCapacity',
|
||||
'HealthCheckGracePeriod', 'HealthCheckType', 'LaunchConfigurationName',
|
||||
'LoadBalancerNames', 'MaxSize', 'MinSize', 'AutoScalingGroupName', 'PlacementGroup',
|
||||
|
@ -711,6 +754,10 @@ def get_properties(autoscaling_group):
|
|||
properties['termination_policies'] = autoscaling_group.get('TerminationPolicies')
|
||||
properties['target_group_arns'] = autoscaling_group.get('TargetGroupARNs')
|
||||
properties['vpc_zone_identifier'] = autoscaling_group.get('VPCZoneIdentifier')
|
||||
raw_mixed_instance_object = autoscaling_group.get('MixedInstancesPolicy')
|
||||
if raw_mixed_instance_object:
|
||||
properties['mixed_instances_policy'] = [x['InstanceType'] for x in raw_mixed_instance_object.get('LaunchTemplate').get('Overrides')]
|
||||
|
||||
metrics = autoscaling_group.get('EnabledMetrics')
|
||||
if metrics:
|
||||
metrics.sort(key=lambda x: x["Metric"])
|
||||
|
@ -738,6 +785,7 @@ def get_launch_object(connection, ec2_connection):
|
|||
launch_object = dict()
|
||||
launch_config_name = module.params.get('launch_config_name')
|
||||
launch_template = module.params.get('launch_template')
|
||||
mixed_instances_policy = module.params.get('mixed_instances_policy')
|
||||
if launch_config_name is None and launch_template is None:
|
||||
return launch_object
|
||||
elif launch_config_name:
|
||||
|
@ -756,6 +804,20 @@ def get_launch_object(connection, ec2_connection):
|
|||
launch_object = {"LaunchTemplate": {"LaunchTemplateId": lt['LaunchTemplateId'], "Version": launch_template['version']}}
|
||||
else:
|
||||
launch_object = {"LaunchTemplate": {"LaunchTemplateId": lt['LaunchTemplateId'], "Version": str(lt['LatestVersionNumber'])}}
|
||||
|
||||
if mixed_instances_policy:
|
||||
instance_types = mixed_instances_policy.get('instance_types', [])
|
||||
policy = {
|
||||
'LaunchTemplate': {
|
||||
'LaunchTemplateSpecification': launch_object['LaunchTemplate']
|
||||
}
|
||||
}
|
||||
if instance_types:
|
||||
policy['LaunchTemplate']['Overrides'] = []
|
||||
for instance_type in instance_types:
|
||||
instance_type_dict = {'InstanceType': instance_type}
|
||||
policy['LaunchTemplate']['Overrides'].append(instance_type_dict)
|
||||
launch_object['MixedInstancesPolicy'] = policy
|
||||
return launch_object
|
||||
|
||||
|
||||
|
@ -951,6 +1013,7 @@ def create_autoscaling_group(connection):
|
|||
availability_zones = module.params['availability_zones']
|
||||
launch_config_name = module.params.get('launch_config_name')
|
||||
launch_template = module.params.get('launch_template')
|
||||
mixed_instances_policy = module.params.get('mixed_instances_policy')
|
||||
min_size = module.params['min_size']
|
||||
max_size = module.params['max_size']
|
||||
placement_group = module.params.get('placement_group')
|
||||
|
@ -1028,7 +1091,10 @@ def create_autoscaling_group(connection):
|
|||
if 'LaunchConfigurationName' in launch_object:
|
||||
ag['LaunchConfigurationName'] = launch_object['LaunchConfigurationName']
|
||||
elif 'LaunchTemplate' in launch_object:
|
||||
ag['LaunchTemplate'] = launch_object['LaunchTemplate']
|
||||
if 'MixedInstancesPolicy' in launch_object:
|
||||
ag['MixedInstancesPolicy'] = launch_object['MixedInstancesPolicy']
|
||||
else:
|
||||
ag['LaunchTemplate'] = launch_object['LaunchTemplate']
|
||||
else:
|
||||
module.fail_json(msg="Missing LaunchConfigurationName or LaunchTemplate",
|
||||
exception=traceback.format_exc())
|
||||
|
@ -1201,7 +1267,10 @@ def create_autoscaling_group(connection):
|
|||
if 'LaunchConfigurationName' in launch_object:
|
||||
ag['LaunchConfigurationName'] = launch_object['LaunchConfigurationName']
|
||||
elif 'LaunchTemplate' in launch_object:
|
||||
ag['LaunchTemplate'] = launch_object['LaunchTemplate']
|
||||
if 'MixedInstancesPolicy' in launch_object:
|
||||
ag['MixedInstancesPolicy'] = launch_object['MixedInstancesPolicy']
|
||||
else:
|
||||
ag['LaunchTemplate'] = launch_object['LaunchTemplate']
|
||||
else:
|
||||
try:
|
||||
ag['LaunchConfigurationName'] = as_group['LaunchConfigurationName']
|
||||
|
@ -1639,6 +1708,11 @@ def main():
|
|||
launch_template_id=dict(type='str'),
|
||||
),
|
||||
),
|
||||
mixed_instances_policy=dict(type='dict',
|
||||
default=None,
|
||||
options=dict(
|
||||
instance_types=dict(type='list', elements='str'),
|
||||
)),
|
||||
min_size=dict(type='int'),
|
||||
max_size=dict(type='int'),
|
||||
placement_group=dict(type='str'),
|
||||
|
@ -1681,7 +1755,7 @@ def main():
|
|||
)
|
||||
|
||||
global module
|
||||
module = AnsibleModule(
|
||||
module = AnsibleAWSModule(
|
||||
argument_spec=argument_spec,
|
||||
mutually_exclusive=[
|
||||
['replace_all_instances', 'replace_instances'],
|
||||
|
@ -1691,6 +1765,9 @@ def main():
|
|||
if not HAS_BOTO3:
|
||||
module.fail_json(msg='boto3 required for this module')
|
||||
|
||||
if module.params.get('mixed_instance_type') and not module.botocore_at_least('1.12.45'):
|
||||
module.fail_json(msg="mixed_instance_type is only supported with botocore >= 1.12.45")
|
||||
|
||||
state = module.params.get('state')
|
||||
replace_instances = module.params.get('replace_instances')
|
||||
replace_all_instances = module.params.get('replace_all_instances')
|
||||
|
|
|
@ -585,6 +585,44 @@
|
|||
until: status is finished
|
||||
retries: 200
|
||||
delay: 15
|
||||
|
||||
# we need a launch template, otherwise we cannot test the mixed instance policy
|
||||
- name: create launch template for autoscaling group to test its mixed instance policy
|
||||
ec2_launch_template:
|
||||
template_name: "{{ resource_prefix }}-lt"
|
||||
image_id: "{{ ec2_ami_image }}"
|
||||
instance_type: t3.micro
|
||||
credit_specification:
|
||||
cpu_credits: standard
|
||||
network_interfaces:
|
||||
- associate_public_ip_address: yes
|
||||
delete_on_termination: yes
|
||||
device_index: 0
|
||||
groups:
|
||||
- "{{ sg.group_id }}"
|
||||
|
||||
- name: update autoscaling group with mixed-instance policy
|
||||
ec2_asg:
|
||||
name: "{{ resource_prefix }}-asg"
|
||||
launch_template:
|
||||
launch_template_name: "{{ resource_prefix }}-lt"
|
||||
desired_capacity: 1
|
||||
min_size: 1
|
||||
max_size: 1
|
||||
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
|
||||
state: present
|
||||
mixed_instances_policy:
|
||||
instance_types:
|
||||
- t3.micro
|
||||
- t3a.micro
|
||||
wait_for_instances: yes
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "output.mixed_instances_policy | length == 2"
|
||||
- "output.mixed_instances_policy[0] == 't3.micro'"
|
||||
- "output.mixed_instances_policy[1] == 't3a.micro'"
|
||||
|
||||
# ============================================================
|
||||
|
||||
|
@ -639,6 +677,15 @@
|
|||
- "{{ resource_prefix }}-lc"
|
||||
- "{{ resource_prefix }}-lc-2"
|
||||
|
||||
- name: delete launch template
|
||||
ec2_launch_template:
|
||||
name: "{{ resource_prefix }}-lt"
|
||||
state: absent
|
||||
register: del_lt
|
||||
retries: 10
|
||||
until: del_lt is not failed
|
||||
ignore_errors: true
|
||||
|
||||
- name: remove the security group
|
||||
ec2_group:
|
||||
name: "{{ resource_prefix }}-sg"
|
||||
|
|
Loading…
Add table
Reference in a new issue