ansible/test/integration/targets/ec2_asg/tasks/main.yml
Andrej Svenke f98874e4f9
ec2_asg: max_instance_lifetime and respect wait on replace (#66863)
* ec2_asg: max_instance_lifetime and respect wait on replace

* ec2_asg: max_instance_lifetime integration tests

* ec2_asg: address review comments
2020-02-15 12:56:39 +00:00

782 lines
22 KiB
YAML

---
# tasks file for test_ec2_asg
- name: Test incomplete credentials with ec2_asg
block:
# ============================================================
- name: test invalid profile
ec2_asg:
name: "{{ resource_prefix }}-asg"
region: "{{ aws_region }}"
profile: notavalidprofile
ignore_errors: yes
register: result
- name:
assert:
that:
- "'The config profile (notavalidprofile) could not be found' in result.msg"
- name: test partial credentials
ec2_asg:
name: "{{ resource_prefix }}-asg"
region: "{{ aws_region }}"
aws_access_key: "{{ aws_access_key }}"
ignore_errors: yes
register: result
- name:
assert:
that:
- "'Partial credentials found in explicit, missing: aws_secret_access_key' in result.msg"
- name: test without specifying region
ec2_asg:
name: "{{ resource_prefix }}-asg"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
ignore_errors: yes
register: result
- name:
assert:
that:
- result.msg == 'The ec2_asg module requires a region and none was found in configuration, environment variables or module parameters'
# ============================================================
- name: Test incomplete arguments with ec2_asg
block:
# ============================================================
- name: test without specifying required module options
ec2_asg:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
ignore_errors: yes
register: result
- name: assert name is a required module option
assert:
that:
- "result.msg == 'missing required arguments: name'"
- name: Run ec2_asg integration tests.
module_defaults:
group/aws:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
region: "{{ aws_region }}"
block:
# ============================================================
- name: Find AMI to use
ec2_ami_info:
owners: 'amazon'
filters:
name: '{{ ec2_ami_name }}'
register: ec2_amis
- set_fact:
ec2_ami_image: '{{ ec2_amis.images[0].image_id }}'
- name: load balancer name has to be less than 32 characters
# the 8 digit identifier at the end of resource_prefix helps determine during which test something
# was created
set_fact:
load_balancer_name: "{{ item }}-lb"
loop: "{{ resource_prefix | regex_findall('.{8}$') }}"
# Set up the testing dependencies: VPC, subnet, security group, and two launch configurations
- name: Create VPC for use in testing
ec2_vpc_net:
name: "{{ resource_prefix }}-vpc"
cidr_block: 10.55.77.0/24
tenancy: default
register: testing_vpc
- name: Create internet gateway for use in testing
ec2_vpc_igw:
vpc_id: "{{ testing_vpc.vpc.id }}"
state: present
register: igw
- name: Create subnet for use in testing
ec2_vpc_subnet:
state: present
vpc_id: "{{ testing_vpc.vpc.id }}"
cidr: 10.55.77.0/24
az: "{{ aws_region }}a"
resource_tags:
Name: "{{ resource_prefix }}-subnet"
register: testing_subnet
- name: create routing rules
ec2_vpc_route_table:
vpc_id: "{{ testing_vpc.vpc.id }}"
tags:
created: "{{ resource_prefix }}-route"
routes:
- dest: 0.0.0.0/0
gateway_id: "{{ igw.gateway_id }}"
subnets:
- "{{ testing_subnet.subnet.id }}"
- name: create a security group with the vpc created in the ec2_setup
ec2_group:
name: "{{ resource_prefix }}-sg"
description: a security group for ansible tests
vpc_id: "{{ testing_vpc.vpc.id }}"
rules:
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
register: sg
- name: ensure launch configs exist
ec2_lc:
name: "{{ item }}"
assign_public_ip: true
image_id: "{{ ec2_ami_image }}"
user_data: |
#cloud-config
package_upgrade: true
package_update: true
packages:
- httpd
runcmd:
- "service httpd start"
security_groups: "{{ sg.group_id }}"
instance_type: t3.micro
loop:
- "{{ resource_prefix }}-lc"
- "{{ resource_prefix }}-lc-2"
# ============================================================
- name: launch asg and wait for instances to be deemed healthy (no ELB)
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
desired_capacity: 1
min_size: 1
max_size: 1
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
state: present
wait_for_instances: yes
register: output
- assert:
that:
- "output.viable_instances == 1"
- name: Tag asg
ec2_asg:
name: "{{ resource_prefix }}-asg"
tags:
- tag_a: 'value 1'
propagate_at_launch: no
- tag_b: 'value 2'
propagate_at_launch: yes
register: output
- assert:
that:
- "output.tags | length == 2"
- output is changed
- name: Re-Tag asg (different order)
ec2_asg:
name: "{{ resource_prefix }}-asg"
tags:
- tag_b: 'value 2'
propagate_at_launch: yes
- tag_a: 'value 1'
propagate_at_launch: no
register: output
- assert:
that:
- "output.tags | length == 2"
- output is not changed
- name: Re-Tag asg new tags
ec2_asg:
name: "{{ resource_prefix }}-asg"
tags:
- tag_c: 'value 3'
propagate_at_launch: no
register: output
- assert:
that:
- "output.tags | length == 1"
- output is changed
- name: Re-Tag asg update propagate_at_launch
ec2_asg:
name: "{{ resource_prefix }}-asg"
tags:
- tag_c: 'value 3'
propagate_at_launch: yes
register: output
- assert:
that:
- "output.tags | length == 1"
- output is changed
- name: Enable metrics collection
ec2_asg:
name: "{{ resource_prefix }}-asg"
metrics_collection: yes
register: output
- assert:
that:
- output is changed
- name: Enable metrics collection (check idempotency)
ec2_asg:
name: "{{ resource_prefix }}-asg"
metrics_collection: yes
register: output
- assert:
that:
- output is not changed
- name: Disable metrics collection
ec2_asg:
name: "{{ resource_prefix }}-asg"
metrics_collection: no
register: output
- assert:
that:
- output is changed
- name: Disable metrics collection (check idempotency)
ec2_asg:
name: "{{ resource_prefix }}-asg"
metrics_collection: no
register: output
- assert:
that:
- output is not changed
# - name: pause for a bit to make sure that the group can't be trivially deleted
# pause: seconds=30
- name: kill asg
ec2_asg:
name: "{{ resource_prefix }}-asg"
state: absent
wait_timeout: 800
async: 400
# ============================================================
- name: launch asg and do not wait for instances to be deemed healthy (no ELB)
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
desired_capacity: 1
min_size: 1
max_size: 1
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
wait_for_instances: no
state: present
register: output
- assert:
that:
- "output.viable_instances == 0"
- name: kill asg
ec2_asg:
name: "{{ resource_prefix }}-asg"
state: absent
wait_timeout: 800
register: output
retries: 3
until: output is succeeded
delay: 10
async: 400
# ============================================================
- name: create asg with asg metrics enabled
ec2_asg:
name: "{{ resource_prefix }}-asg"
metrics_collection: true
launch_config_name: "{{ resource_prefix }}-lc"
desired_capacity: 0
min_size: 0
max_size: 0
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
state: present
register: output
- assert:
that:
- "'Group' in output.metrics_collection.0.Metric"
- name: kill asg
ec2_asg:
name: "{{ resource_prefix }}-asg"
state: absent
wait_timeout: 800
async: 400
# ============================================================
- name: launch load balancer
ec2_elb_lb:
name: "{{ load_balancer_name }}"
state: present
security_group_ids:
- "{{ sg.group_id }}"
subnets: "{{ testing_subnet.subnet.id }}"
connection_draining_timeout: 60
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
health_check:
ping_protocol: tcp
ping_port: 80
ping_path: "/"
response_timeout: 5
interval: 10
unhealthy_threshold: 4
healthy_threshold: 2
register: load_balancer
- name: launch asg and wait for instances to be deemed healthy (ELB)
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
health_check_type: ELB
desired_capacity: 1
min_size: 1
max_size: 1
health_check_period: 300
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
load_balancers: "{{ load_balancer_name }}"
wait_for_instances: yes
wait_timeout: 900
state: present
register: output
- assert:
that:
- "output.viable_instances == 1"
# ============================================================
# grow scaling group to 3
- name: add 2 more instances wait for instances to be deemed healthy (ELB)
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
health_check_type: ELB
desired_capacity: 3
min_size: 3
max_size: 5
health_check_period: 600
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
load_balancers: "{{ load_balancer_name }}"
wait_for_instances: yes
wait_timeout: 1200
state: present
register: output
- assert:
that:
- "output.viable_instances == 3"
# ============================================================
# Test max_instance_lifetime option
- name: enable asg max_instance_lifetime
ec2_asg:
name: "{{ resource_prefix }}-asg"
max_instance_lifetime: 604801
register: output
- name: ensure max_instance_lifetime is set
assert:
that:
- output.max_instance_lifetime == 604801
- name: run without max_instance_lifetime
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
- name: ensure max_instance_lifetime not affected by defaults
assert:
that:
- output.max_instance_lifetime == 604801
- name: disable asg max_instance_lifetime
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
max_instance_lifetime: 0
register: output
- name: ensure max_instance_lifetime is not set
assert:
that:
- not output.max_instance_lifetime
# ============================================================
# # perform rolling replace with different launch configuration
- name: perform rolling update to new AMI
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc-2"
health_check_type: ELB
desired_capacity: 3
min_size: 1
max_size: 5
health_check_period: 900
load_balancers: "{{ load_balancer_name }}"
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
wait_for_instances: yes
replace_all_instances: yes
wait_timeout: 1800
state: present
register: output
# ensure that all instances have new launch config
- assert:
that:
- "item.value.launch_config_name == '{{ resource_prefix }}-lc-2'"
loop: "{{ output.instance_facts | dict2items }}"
# assert they are all healthy and that the rolling update resulted in the appropriate number of instances
- assert:
that:
- "output.viable_instances == 3"
# ============================================================
# perform rolling replace with the original launch configuration
- name: perform rolling update to new AMI while removing the load balancer
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
health_check_type: EC2
desired_capacity: 3
min_size: 1
max_size: 5
health_check_period: 900
load_balancers: []
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
wait_for_instances: yes
replace_all_instances: yes
wait_timeout: 1800
state: present
register: output
# ensure that all instances have new launch config
- assert:
that:
- "item.value.launch_config_name == '{{ resource_prefix }}-lc'"
loop: "{{ output.instance_facts | dict2items }}"
# assert they are all healthy and that the rolling update resulted in the appropriate number of instances
# there should be the same number of instances as there were before the rolling update was performed
- assert:
that:
- "output.viable_instances == 3"
# ============================================================
# perform rolling replace with new launch configuration and lc_check:false
# Note - this is done async so we can query asg_facts during
# the execution. Issues #28087 and #35993 result in correct
# end result, but spin up extraneous instances during execution.
- name: "perform rolling update to new AMI with lc_check: false"
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc-2"
health_check_type: EC2
desired_capacity: 3
min_size: 1
max_size: 5
health_check_period: 900
load_balancers: []
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
wait_for_instances: yes
replace_all_instances: yes
replace_batch_size: 3
lc_check: false
wait_timeout: 1800
state: present
async: 1800
poll: 0
register: asg_job
- name: get ec2_asg info for 3 minutes
ec2_asg_info:
name: "{{ resource_prefix }}-asg"
register: output
loop_control:
pause: 15
loop: "{{ range(12) | list }}"
# Since we started with 3 servers and replace all of them.
# We should see 6 servers total.
- assert:
that:
- output | json_query(inst_id_json_query) | unique | length == 6
vars:
inst_id_json_query: results[].results[].instances[].instance_id
- name: Ensure ec2_asg task completes
async_status: jid="{{ asg_job.ansible_job_id }}"
register: status
until: status is finished
retries: 200
delay: 15
# ============================================================
- name: kill asg
ec2_asg:
name: "{{ resource_prefix }}-asg"
state: absent
wait_timeout: 800
async: 400
# Create new asg with replace_all_instances and lc_check:false
# Note - this is done async so we can query asg_facts during
# the execution. Issues #28087 results in correct
# end result, but spin up extraneous instances during execution.
- name: "new asg with lc_check: false"
ec2_asg:
name: "{{ resource_prefix }}-asg"
launch_config_name: "{{ resource_prefix }}-lc"
health_check_type: EC2
desired_capacity: 3
min_size: 1
max_size: 5
health_check_period: 900
load_balancers: []
vpc_zone_identifier: "{{ testing_subnet.subnet.id }}"
wait_for_instances: yes
replace_all_instances: yes
replace_batch_size: 3
lc_check: false
wait_timeout: 1800
state: present
async: 1800
poll: 0
register: asg_job
# Collect ec2_asg_info for 3 minutes
- name: get ec2_asg information
ec2_asg_info:
name: "{{ resource_prefix }}-asg"
register: output
loop_control:
pause: 15
loop: "{{ range(12) | list }}"
# Get all instance_ids we saw and assert we saw number expected
# Should only see 3 (don't replace instances we just created)
- assert:
that:
- output | json_query(inst_id_json_query) | unique | length == 3
vars:
inst_id_json_query: results[].results[].instances[].instance_id
- name: Ensure ec2_asg task completes
async_status: jid="{{ asg_job.ansible_job_id }}"
register: status
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'"
# ============================================================
always:
- name: kill asg
ec2_asg:
name: "{{ resource_prefix }}-asg"
state: absent
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
# Remove the testing dependencies
- name: remove the load balancer
ec2_elb_lb:
name: "{{ load_balancer_name }}"
state: absent
security_group_ids:
- "{{ sg.group_id }}"
subnets: "{{ testing_subnet.subnet.id }}"
wait: yes
connection_draining_timeout: 60
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
health_check:
ping_protocol: tcp
ping_port: 80
ping_path: "/"
response_timeout: 5
interval: 10
unhealthy_threshold: 4
healthy_threshold: 2
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
- name: remove launch configs
ec2_lc:
name: "{{ resource_prefix }}-lc"
state: absent
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
loop:
- "{{ 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"
description: a security group for ansible tests
vpc_id: "{{ testing_vpc.vpc.id }}"
state: absent
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
- name: remove routing rules
ec2_vpc_route_table:
state: absent
vpc_id: "{{ testing_vpc.vpc.id }}"
tags:
created: "{{ resource_prefix }}-route"
routes:
- dest: 0.0.0.0/0
gateway_id: "{{ igw.gateway_id }}"
subnets:
- "{{ testing_subnet.subnet.id }}"
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
- name: remove internet gateway
ec2_vpc_igw:
vpc_id: "{{ testing_vpc.vpc.id }}"
state: absent
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
- name: remove the subnet
ec2_vpc_subnet:
state: absent
vpc_id: "{{ testing_vpc.vpc.id }}"
cidr: 10.55.77.0/24
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10
- name: remove the VPC
ec2_vpc_net:
name: "{{ resource_prefix }}-vpc"
cidr_block: 10.55.77.0/24
state: absent
register: removed
until: removed is not failed
ignore_errors: yes
retries: 10