Repository: ansible/ansible

Issue:
AWS EC2 module ignores the idempotency ID when using status
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
ec2

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0.0
  config file = ${NOTHING_EXCITING_GOING_ON_HERE}
  configured module search path = Default w/o overrides
  python version = 3.5.3+ (default, Jun  7 2017, 23:23:48) [GCC 6.3.0 20170516]

```

##### CONFIGURATION
<!---
[Defaults]
pipelining = True
-->

##### OS / ENVIRONMENT
<!---
Running from Debian Stretch to AWS EC2, but I think it's likely not relevant
-->

##### SUMMARY
<!--- Explain the problem briefly -->

##### STEPS TO REPRODUCE
1. Create a playbook that consumes the following task:

```
- name: "Ensure the webserver is in the expected state"
  ec2:
    state: "running"
    key_name: "{{ ec2_key_name }}"
    instance_type: "t2.micro"
    image: "{{ ec2_ami_id }}"
    wait: "yes"
    wait_timeout: "300"
    count: 1
    instance_tags: "{{ ec2_tags }}"
    monitoring: "{{ ec2_monitoring }}"
    region: "{{ ec2_region }}"
    vpc_subnet_id: "{{ ec2_vpc_subnet_id }}"
    id: "__THIS_IS_A_UNIQUE_ID__"
  register: "ec2_provisioner"
```
2. Notice that it doesn't change anything. Weird, because that instance is stopped
3. Notice that during debugging all VMS are output by ec2_provisioner, rather than just the one that's supposed to be changed.
4. Modify the task by deleting `state`
5. Observe it works as expected.

<!--- Paste example playbooks or commands between quotes below -->
```yaml
ansible-playbook --inventory-file=inventory/static site.yaml  --limit=infrastructure  --flush-cache
```

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

I expected my machine to start back up again

##### ACTUAL RESULTS

Depending on how I worked it, a machine completely irrelevant was started and modified. (This was beyond terrifying for me!)
AWS EC2 module ignores the idempotency ID when using status
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
ec2

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0.0
  config file = ${NOTHING_EXCITING_GOING_ON_HERE}
  configured module search path = Default w/o overrides
  python version = 3.5.3+ (default, Jun  7 2017, 23:23:48) [GCC 6.3.0 20170516]

```

##### CONFIGURATION
<!---
[Defaults]
pipelining = True
-->

##### OS / ENVIRONMENT
<!---
Running from Debian Stretch to AWS EC2, but I think it's likely not relevant
-->

##### SUMMARY
<!--- Explain the problem briefly -->

##### STEPS TO REPRODUCE
1. Create a playbook that consumes the following task:

```
- name: "Ensure the webserver is in the expected state"
  ec2:
    state: "running"
    key_name: "{{ ec2_key_name }}"
    instance_type: "t2.micro"
    image: "{{ ec2_ami_id }}"
    wait: "yes"
    wait_timeout: "300"
    count: 1
    instance_tags: "{{ ec2_tags }}"
    monitoring: "{{ ec2_monitoring }}"
    region: "{{ ec2_region }}"
    vpc_subnet_id: "{{ ec2_vpc_subnet_id }}"
    id: "__THIS_IS_A_UNIQUE_ID__"
  register: "ec2_provisioner"
```
2. Notice that it doesn't change anything. Weird, because that instance is stopped
3. Notice that during debugging all VMS are output by ec2_provisioner, rather than just the one that's supposed to be changed.
4. Modify the task by deleting `state`
5. Observe it works as expected.

<!--- Paste example playbooks or commands between quotes below -->
```yaml
ansible-playbook --inventory-file=inventory/static site.yaml  --limit=infrastructure  --flush-cache
```

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

I expected my machine to start back up again

##### ACTUAL RESULTS

Depending on how I worked it, a machine completely irrelevant was started and modified. (This was beyond terrifying for me!)


Discussion:

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/ec2.py b/lib/ansible/modules/cloud/amazon/ec2.py
--- a/lib/ansible/modules/cloud/amazon/ec2.py
+++ b/lib/ansible/modules/cloud/amazon/ec2.py
@@ -698,6 +698,9 @@ def get_reservations(module, ec2, tags=None, state=None, zone=None):
     if zone:
         filters.update({'availability-zone': zone})
 
+    if module.params.get('id'):
+        filters['client-token'] = module.params['id']
+
     results = ec2.get_all_instances(filters=filters)
 
     return results
@@ -1414,6 +1417,8 @@ def startstop_instances(module, ec2, instance_ids, state, instance_tags):
         for key, value in instance_tags.items():
             filters["tag:" + key] = value
 
+    if module.params.get('id'):
+        filters['client-token'] = module.params['id']
     # Check that our instances are not in the state we want to take
 
     # Check (and eventually change) instances attributes and instances state
@@ -1539,6 +1544,8 @@ def restart_instances(module, ec2, instance_ids, state, instance_tags):
     if instance_tags:
         for key, value in instance_tags.items():
             filters["tag:" + key] = value
+    if module.params.get('id'):
+        filters['client-token'] = module.params['id']
 
     # Check that our instances are not in the state we want to take
 


Test patch: