Repository: ansible/ansible

Issue:
ec2_elb: Ansible claims changed=true when removing instance not in elb
##### ISSUE TYPE

bug report

##### COMPONENT NAME

ec2_elb module

##### ANSIBLE VERSION

ansible 1.7.2

##### OS / ENVIRONMENT

Mac OS X 10.9.5

##### SUMMARY

When using the ec2_elb module to remove an instance from a load balancer, if the instance was not in the load balancer before running the task, Ansible incorrectly reports the state has changed.

##### STEPS TO REPRODUCE

Invoke the ec2_elb module to remove an instance that's not in a load balancer (or just run it twice)

```

---
- name: remove instance from a load balancer
  hosts: localhost
  vars:
    instances:
      - i-123456ab
    lb: my-load-balancer
  tasks:
    - name: take the instances out of the load balancer
      local_action: ec2_elb
      args:
        instance_id: "{{ item }}"
        ec2_elbs: "{{ lb }}"
        state: absent
      with_items: instances
```

##### EXPECTED RESULTS

```
TASK: [take the instances out of the load balancer] ***************************
ok: [localhost -> 127.0.0.1] => (item=i-123456ab)

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0
```

##### ACTUAL RESULTS

```
TASK: [take the instances out of the load balancer] ***************************
changed: [localhost -> 127.0.0.1] => (item=i-123456ab)

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


Copied from original issue: ansible/ansible-modules-core#140


ec2_elb: Ansible claims changed=true when removing instance not in elb
##### ISSUE TYPE

bug report

##### COMPONENT NAME

ec2_elb module

##### ANSIBLE VERSION

ansible 1.7.2

##### OS / ENVIRONMENT

Mac OS X 10.9.5

##### SUMMARY

When using the ec2_elb module to remove an instance from a load balancer, if the instance was not in the load balancer before running the task, Ansible incorrectly reports the state has changed.

##### STEPS TO REPRODUCE

Invoke the ec2_elb module to remove an instance that's not in a load balancer (or just run it twice)

```

---
- name: remove instance from a load balancer
  hosts: localhost
  vars:
    instances:
      - i-123456ab
    lb: my-load-balancer
  tasks:
    - name: take the instances out of the load balancer
      local_action: ec2_elb
      args:
        instance_id: "{{ item }}"
        ec2_elbs: "{{ lb }}"
        state: absent
      with_items: instances
```

##### EXPECTED RESULTS

```
TASK: [take the instances out of the load balancer] ***************************
ok: [localhost -> 127.0.0.1] => (item=i-123456ab)

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0
```

##### ACTUAL RESULTS

```
TASK: [take the instances out of the load balancer] ***************************
changed: [localhost -> 127.0.0.1] => (item=i-123456ab)

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


Copied from original issue: ansible/ansible-modules-core#140




Discussion:
From @tpounds on 2014-10-06T00:56:37Z

So it looks like PR #867 doesn't actually fix the issue. I reread the documentation for DeregisterInstancesFromLoadBalancer and noticed the response contains "The remaining instances registered with the load balancer" not the instances that were deregistered. Unfortunately, the DescribeInstanceHealth will return an OutOfService state for valid instances that are not currently registered. The only way to determine whether an instance is OutOfService for a given reason is to parse the description (ignored by boto). Instances that are not currently registered with the load balancer will be returned with state OutOfService with the description "Instance is not currently registered with the LoadBalancer." The only way to determine the actual membership state is to either parse the description or query the load balancer prior to performing the deregistration action. Since boto doesn't expose the description the only course of action appears to be querying the load balancer to get the starting instance membership. 

From @defionscode on 2014-10-06T00:56:37Z

@tpounds so my line of thought ATM is to add something like the following to pick up the instance

``` python
loadbalancer = elb.get_all_load_balancers(load_balancer_names=[nameParameter])[0]
instance_ids = [ instance.id for instance in loadbalancer.instances ]
```

Looks like that should get you proper membership.

@ansibot Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information. 

Here are the items we could not find in your description:
- component name

Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE.md

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: issue_missing_data --->
From @tpounds on 2014-10-06T00:56:37Z

So it looks like PR #867 doesn't actually fix the issue. I reread the documentation for DeregisterInstancesFromLoadBalancer and noticed the response contains "The remaining instances registered with the load balancer" not the instances that were deregistered. Unfortunately, the DescribeInstanceHealth will return an OutOfService state for valid instances that are not currently registered. The only way to determine whether an instance is OutOfService for a given reason is to parse the description (ignored by boto). Instances that are not currently registered with the load balancer will be returned with state OutOfService with the description "Instance is not currently registered with the LoadBalancer." The only way to determine the actual membership state is to either parse the description or query the load balancer prior to performing the deregistration action. Since boto doesn't expose the description the only course of action appears to be querying the load balancer to get the starting instance membership. 

From @defionscode on 2014-10-06T00:56:37Z

@tpounds so my line of thought ATM is to add something like the following to pick up the instance

``` python
loadbalancer = elb.get_all_load_balancers(load_balancer_names=[nameParameter])[0]
instance_ids = [ instance.id for instance in loadbalancer.instances ]
```

Looks like that should get you proper membership.

@ansibot Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information. 

Here are the items we could not find in your description:
- component name

Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE.md

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: issue_missing_data --->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/ec2_elb.py b/lib/ansible/modules/cloud/amazon/ec2_elb.py
--- a/lib/ansible/modules/cloud/amazon/ec2_elb.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_elb.py
@@ -133,6 +133,10 @@ def deregister(self, wait, timeout):
                 # balancer. Ignore it and try the next one.
                 continue
 
+            # The instance is not associated with any load balancer so nothing to do
+            if not self._get_instance_lbs():
+                return
+
             lb.deregister_instances([self.instance_id])
 
             # The ELB is changing state in some way. Either an instance that's


Test patch: