Repository: ansible/ansible-modules-core

Issue:
ec2 termination timeout when instance_ids contains instances from multiple reservations
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### COMPONENT NAME

<!--- Name of the plugin/module/task -->

ec2
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
ansible 2.2.0 (devel 17447ff035) last updated 2016/06/20 11:08:27 (GMT -400)
  lib/ansible/modules/core: (detached HEAD f0f5272f90) last updated 2016/06/22 10:42:10 (GMT -400)
  lib/ansible/modules/extras: (detached HEAD 6cb6829384) last updated 2016/06/22 10:42:10 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

Linux minastirith 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
##### SUMMARY

<!--- Explain the problem briefly -->

Waiting for terminating instances with ec2 module will timeout if all instances specified in `instance_id` are not from the same reservation.
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

Using the following playbook:

<!--- Paste example playbooks or commands between quotes below -->

```
- hosts: localhost
  connection: local
  tasks:
    - name: Launch an instance
    - ec2:
        key_name: "{{ lookup('ENV', 'AWS_KEY_NAME') }}"
        aws_access_key: "{{ lookup('ENV', 'AWS_ACCESS_KEY_ID') }}"
        aws_secret_key: "{{ lookup('ENV', 'AWS_SECRET_ACCESS_KEY') }}"
        region: "us-west-2"
        state: present
        wait: yes
        image: ami-03de3c63
        instance_type: t2.nano
        wait_timeout: 300
      register: ec2
    - set_fact:
        instance_1: "{{ ec2.instances[0].id }}"

- hosts: localhost
  connection: local
  tasks:
    - name: Launch another instance from a different play
    - ec2:
        key_name: "{{ lookup('ENV', 'AWS_KEY_NAME') }}"
        aws_access_key: "{{ lookup('ENV', 'AWS_ACCESS_KEY_ID') }}"
        aws_secret_key: "{{ lookup('ENV', 'AWS_SECRET_ACCESS_KEY') }}"
        region: "us-west-2"
        state: present
        wait: yes
        image: ami-03de3c63
        instance_type: t2.nano
        wait_timeout: 300
      register: ec2
    - set_fact:
        instance_2: "{{ ec2.instances[0].id }}"


- hosts: localhost
  connection: local
  tasks:
    - name: Instances terminate in AWS but task times out
    - ec2:
        key_name: "{{ lookup('ENV', 'AWS_KEY_NAME') }}"
        aws_access_key: "{{ lookup('ENV', 'AWS_ACCESS_KEY_ID') }}"
        aws_secret_key: "{{ lookup('ENV', 'AWS_SECRET_ACCESS_KEY') }}"
        region: "us-west-2"
        instance_ids: ["{{ instance_1 }}", "{{ instance_2 }}"]
        state: 'absent'
        wait: yes
        wait_timeout: 60

```

I run: 

```
 ansible-playbook -i localhost, -e ansible_python_interpreter=python2 playbook.yml
```

This terminates the instances,  but the task times out.

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->

Successful execution of the termination task.
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->

```
(ansible)kotfic@minastirith:~/scratch/ec2_termination_playbooks ⇒ ansible-playbook -i localhost, -e ansible_python_interpreter=python2 playbook.yml

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Launch an instance] ******************************************************
changed: [localhost]

TASK [set_fact] ****************************************************************
ok: [localhost]

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Launch another instance from a different play] ***************************
changed: [localhost]

TASK [set_fact] ****************************************************************
ok: [localhost]

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Instances terminate in AWS but task times out] ***************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "wait for instance termination timeout on Wed Jun 22 11:22:28 2016"}

NO MORE HOSTS LEFT *************************************************************
 [WARNING]: Could not create retry file 'playbook.retry'.         Unable to create local directories(): [Errno 2] No such file or directory:
''


PLAY RECAP *********************************************************************
localhost                  : ok=7    changed=2    unreachable=0    failed=1   

```



Discussion:
I am putting together a PR that fixes this issue ATM


Resolving patch:
diff --git a/cloud/amazon/ec2.py b/cloud/amazon/ec2.py
--- a/cloud/amazon/ec2.py
+++ b/cloud/amazon/ec2.py
@@ -1218,7 +1218,7 @@ def terminate_instances(module, ec2, instance_ids):
                 instance_ids=terminated_instance_ids, \
                 filters={'instance-state-name':'terminated'})
             try:
-                num_terminated = len(response.pop().instances)
+                num_terminated = sum([len(res.instances) for res in response])
             except Exception as e:
                 # got a bad response of some sort, possibly due to
                 # stale/cached data. Wait a second and then try again


Test patch: