Skip to content

Commit

Permalink
ec2_instance: fix to handle create instance in specified AZ (#1150)
Browse files Browse the repository at this point in the history
ec2_instance: fix to handle create instance in specified AZ

SUMMARY

This PR adds a fix to allow launching an instance in specified AZ when vpc_subnet_id is not specified.
The current code does not consider the AZ and launches the instance in default subnet of default vpc for the specified region.
https://github.com/ansible-collections/amazon.aws/blob/main/plugins/modules/ec2_instance.py#L1584-L1593

Fixes #1120
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

ec2_instance
ADDITIONAL INFORMATION


Without the fix, the below playbook will launch instance in default subnet ignoring specified AZ.
Example Playbook to launch instance in us-west-2b AZ.

---
- name: Spin up ec2 instance
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Launch regular ec2 instances in us-west-1b
      amazon.aws.ec2_instance:
        name: "test-instance-us-west-1b"
        instance_type: t2.micro
        image_id: ami-xxxxx
        state: present
        availability_zone: us-west-1b
        region: us-west-1
        tags:
          terminate-this: yes
        network:
          assign_public_ip: yes
      register: create_result

    - ec2_instance_info:
        instance_ids:
          - "{{ create_result.instance_ids[0] }}"
        region: us-west-1
      register: info_result
    - assert:
        that: info_result.instances[0].placement.availability_zone == 'us-west-1b'

Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Gonéri Le Bouder <goneri@lebouder.net>
  • Loading branch information
mandar242 authored Oct 11, 2022
1 parent 90eda33 commit 395d4fd
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ec2_instance - minor fix for launching an instance in specified AZ when `vpc_subnet_id` is not provided (https://github.com/ansible-collections/amazon.aws/pull/1150).
2 changes: 1 addition & 1 deletion plugins/modules/ec2_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,7 @@ def build_network_spec(params):
module.fail_json(
msg="No default subnet could be found - you must include a VPC subnet ID (vpc_subnet_id parameter) to create an instance")
else:
sub = get_default_subnet(default_vpc)
sub = get_default_subnet(default_vpc, availability_zone=module.params.get('availability_zone'))
spec['SubnetId'] = sub['SubnetId']

if network.get('private_ip_address'):
Expand Down
216 changes: 216 additions & 0 deletions tests/integration/targets/ec2_instance_instance_minimal/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,74 @@
- create_instance_tag.instance_ids | length == 1
- create_instance_tag.instance_ids[0] == create_instance_id_tag

###############################################################

- name: "Create a new instance in AZ {{ aws_region }}a"
ec2_instance:
state: present
name: "{{ resource_prefix }}-test-basic-{{ aws_region }}a"
instance_type: "{{ ec2_instance_type }}"
image_id: "{{ ec2_ami_id }}"
region: "{{ aws_region }}"
availability_zone: "{{ aws_region }}a"
tags:
TestId: "{{ ec2_instance_tag_TestId }}"
wait: true
register: create_instance

- name: "Save instance ID"
set_fact:
create_instance_id_3: "{{ create_instance.instance_ids[0] }}"

- name: Get instance info
ec2_instance_info:
instance_ids:
- "{{ create_instance_id_3 }}"
register: info_result

- assert:
that:
- create_instance is not failed
- create_instance is changed
- '"ec2:RunInstances" in create_instance.resource_actions'
- '"instance_ids" in create_instance'
- create_instance.instance_ids | length == 1
- create_instance.instance_ids[0].startswith("i-")
- info_result.instances[0].placement.availability_zone == '{{ aws_region }}a'

- name: "Create a new instance in AZ {{ aws_region }}b"
ec2_instance:
state: present
name: "{{ resource_prefix }}-test-basic-{{ aws_region }}b"
instance_type: "{{ ec2_instance_type }}"
image_id: "{{ ec2_ami_id }}"
region: "{{ aws_region }}"
availability_zone: "{{ aws_region }}b"
tags:
TestId: "{{ ec2_instance_tag_TestId }}"
wait: true
register: create_instance

- name: "Save instance ID"
set_fact:
create_instance_id_4: "{{ create_instance.instance_ids[0] }}"

- name: Get instance info
ec2_instance_info:
instance_ids:
- "{{ create_instance_id_4 }}"
register: info_result

- assert:
that:
- create_instance is not failed
- create_instance is changed
- '"ec2:RunInstances" in create_instance.resource_actions'
- '"instance_ids" in create_instance'
- create_instance.instance_ids | length == 1
- create_instance.instance_ids[0].startswith("i-")
- info_result.instances[0].placement.availability_zone == '{{ aws_region }}b'

################################################################

- name: "Terminate instance based on name parameter (check_mode)"
Expand Down Expand Up @@ -481,3 +549,151 @@
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" not in terminate_id'
- '"terminate_success" not in terminate_id'

################################################################

- name: "Terminate instance based on id (check_mode)"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_3 }}"
wait: true
register: terminate_id
check_mode: true

- assert:
that:
- terminate_id is not failed
- terminate_id is changed
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" in terminate_id'
- '"terminate_success" in terminate_id'
- terminate_id.terminate_failed | length == 0
- terminate_id.terminate_success | length == 1
- terminate_id.terminate_success[0] == create_instance_id_3

- name: "Terminate instance based on id"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_3 }}"
wait: true
register: terminate_id

- assert:
that:
- terminate_id is not failed
- terminate_id is changed
- '"ec2:TerminateInstances" in terminate_id.resource_actions'
- '"terminate_failed" in terminate_id'
- '"terminate_success" in terminate_id'
- terminate_id.terminate_failed | length == 0
- terminate_id.terminate_success | length == 1
- terminate_id.terminate_success[0] == create_instance_id_3

- name: "Terminate instance based on id - idempotency (check_mode)"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_3 }}"
wait: true
register: terminate_id
check_mode: true

- assert:
that:
- terminate_id is not failed
- terminate_id is not changed
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" not in terminate_id'
- '"terminate_success" not in terminate_id'

- name: "Terminate instance based on id - idempotency"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_3 }}"
wait: true
register: terminate_id

- assert:
that:
- terminate_id is not failed
- terminate_id is not changed
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" not in terminate_id'
- '"terminate_success" not in terminate_id'

################################################################

- name: "Terminate instance based on id (check_mode)"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_4 }}"
wait: true
register: terminate_id
check_mode: true

- assert:
that:
- terminate_id is not failed
- terminate_id is changed
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" in terminate_id'
- '"terminate_success" in terminate_id'
- terminate_id.terminate_failed | length == 0
- terminate_id.terminate_success | length == 1
- terminate_id.terminate_success[0] == create_instance_id_4

- name: "Terminate instance based on id"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_4 }}"
wait: true
register: terminate_id

- assert:
that:
- terminate_id is not failed
- terminate_id is changed
- '"ec2:TerminateInstances" in terminate_id.resource_actions'
- '"terminate_failed" in terminate_id'
- '"terminate_success" in terminate_id'
- terminate_id.terminate_failed | length == 0
- terminate_id.terminate_success | length == 1
- terminate_id.terminate_success[0] == create_instance_id_4

- name: "Terminate instance based on id - idempotency (check_mode)"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_4 }}"
wait: true
register: terminate_id
check_mode: true

- assert:
that:
- terminate_id is not failed
- terminate_id is not changed
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" not in terminate_id'
- '"terminate_success" not in terminate_id'

- name: "Terminate instance based on id - idempotency"
ec2_instance:
state: absent
instance_ids:
- "{{ create_instance_id_4 }}"
wait: true
register: terminate_id

- assert:
that:
- terminate_id is not failed
- terminate_id is not changed
- '"ec2:TerminateInstances" not in terminate_id.resource_actions'
- '"terminate_failed" not in terminate_id'
- '"terminate_success" not in terminate_id'

0 comments on commit 395d4fd

Please sign in to comment.