Repository: ansible/ansible

Issue:
Removing a public IPv4 address fails without warning in ec2 module
<!---
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.5.0
  config file = None
  configured module search path = [u'/Users/jvf/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/jvf/Library/Python/2.7/lib/python/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.10 (default, Feb  7 2017, 00:08:15) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
```

##### CONFIGURATION
No changes.

##### OS / ENVIRONMENT
macOS 10.12.6

##### SUMMARY
Changing `assign_public_ip` from `yes` to `no` silently fails

##### STEPS TO REPRODUCE
Create an instance with 
```yaml
      ec2:
         ...
        assign_public_ip: yes
```

Change to 
```yaml
      ec2:
         ...
        assign_public_ip: no
```

Run playbook again. 

##### EXPECTED RESULTS

Print out a warning that unassigning the public IPv4 address is not possible.

##### ACTUAL RESULTS
Nothing. Ansible does not display any warning or similar, running the playbook seems successful. But the instance still has a public IPv4 address assigned.
Removing a public IPv4 address fails without warning in ec2 module
<!---
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.5.0
  config file = None
  configured module search path = [u'/Users/jvf/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/jvf/Library/Python/2.7/lib/python/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.10 (default, Feb  7 2017, 00:08:15) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
```

##### CONFIGURATION
No changes.

##### OS / ENVIRONMENT
macOS 10.12.6

##### SUMMARY
Changing `assign_public_ip` from `yes` to `no` silently fails

##### STEPS TO REPRODUCE
Create an instance with 
```yaml
      ec2:
         ...
        assign_public_ip: yes
```

Change to 
```yaml
      ec2:
         ...
        assign_public_ip: no
```

Run playbook again. 

##### EXPECTED RESULTS

Print out a warning that unassigning the public IPv4 address is not possible.

##### ACTUAL RESULTS
Nothing. Ansible does not display any warning or similar, running the playbook seems successful. But the instance still has a public IPv4 address assigned.


Discussion:
cc @lwade @tgerla
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @lwade @tgerla
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

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
@@ -988,6 +988,8 @@ def enforce_count(module, ec2, vpc):
             inst = get_instance_info(inst)
         all_instances.append(inst)
 
+        warn_if_public_ip_assignment_changed(module, inst)
+
     return (all_instances, instance_dict_array, changed_instance_ids, changed)
 
 
@@ -1445,6 +1447,8 @@ def startstop_instances(module, ec2, instance_ids, state, instance_tags):
     for res in ec2.get_all_instances(instance_ids, filters=filters):
         for inst in res.instances:
 
+            warn_if_public_ip_assignment_changed(module, inst)
+
             # Check "source_dest_check" attribute
             try:
                 if inst.vpc_id is not None and inst.get_attribute('sourceDestCheck')['sourceDestCheck'] != source_dest_check:
@@ -1572,6 +1576,8 @@ def restart_instances(module, ec2, instance_ids, state, instance_tags):
     for res in ec2.get_all_instances(instance_ids, filters=filters):
         for inst in res.instances:
 
+            warn_if_public_ip_assignment_changed(module, inst)
+
             # Check "source_dest_check" attribute
             try:
                 if inst.vpc_id is not None and inst.get_attribute('sourceDestCheck')['sourceDestCheck'] != source_dest_check:
@@ -1607,6 +1613,16 @@ def restart_instances(module, ec2, instance_ids, state, instance_tags):
     return (changed, instance_dict_array, instance_ids)
 
 
+def warn_if_public_ip_assignment_changed(module, instance):
+    # This is a non-modifiable attribute.
+    assign_public_ip = module.params.get('assign_public_ip')
+
+    # Check that public ip assignment is the same and warn if not
+    if (assign_public_ip or instance.public_dns_name) and (not instance.public_dns_name or not assign_public_ip):
+        module.warn("Unable to modify public ip assignment to {0} for instance {1}. "
+                    "Whether or not to assign a public IP is determined during instance creation.".format(assign_public_ip, instance.id))
+
+
 def main():
     argument_spec = ec2_argument_spec()
     argument_spec.update(


Test patch: