Repository: ansible/ansible-modules-core

Issue:
ec2_asg Unable to use Default as default termination_policies policy
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME

ec2_asg
##### ANSIBLE VERSION

$ ansible --version
ansible 2.0.0.2 (detached HEAD 7de237c5a1) last updated 2016/01/27 17:54:03 (GMT +000)
  lib/ansible/modules/core: (detached HEAD ce6619bf5d) last updated 2016/01/27 17:56:41 (GMT +000)
  lib/ansible/modules/extras: (detached HEAD 29af26884e) last updated 2016/01/27 17:56:45 (GMT +000)
  config file = /home/ubuntu/infrastructure-devops/ansible/ansible.cfg
  configured module search path = modules
##### CONFIGURATION
##### OS / ENVIRONMENT

Ubuntu 14.04 LTS
##### SUMMARY

Unable to specify ordered list of termination_policies
##### STEPS TO REPRODUCE

Specify any of the following:

```
termination_policies: ['Default', 'OldestLaunchConfiguration']
termination_policies: ['OldestLaunchConfiguration', 'Default']
termination_policies:
- OldestLaunchConfiguration
- Default
termination_policies:
- Default
- OldestLaunchConfiguration
```

They all fail with the same message:

```
{"msg": "BotoServerError: 400 Bad Request\n<ErrorResponse xmlns=\"http://autoscaling.amazonaws.com/doc/2011-01-01/\">\n  <Error>\n    <Type>Sender</Type>\n    <Code>ValidationError</Code>\n    <Message>If Default termination policy is specified, it must be at the end of list of termination policies.</Message>\n  </Error>\n  <RequestId>9b7985e4-3de0-11e6-a3b4-378ee1b9bcf4</RequestId>\n</ErrorResponse>\n"}
```

The ansible -vvvv output also always contains this element: `{"termination_policies": ["Default", "OldestLaunchConfiguration"]}`
##### EXPECTED RESULTS

To have termination_policies set correctly.
##### ACTUAL RESULTS

Fails with error.



Discussion:
<!-- @morganchristiansson: Thanks for filing this bug report! -->

@ansible ping, this issue is waiting for your response.
[click here for bot help](https://github.com/jctanner/ansibullbot/blob/ISSUE_TRIAGE_CLASS/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

@ansible, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

Hi, I've been able to reproduce this against `devel` today, still looking for the reason it happens. 

Found the problem. For all attributes, the module params and group params are sorted before being compared, so if you provide `["OldestLaunchConfiguration", "Default"]`it gets sorted so default is first, and because all lists that have default _must_ end in default, this causes that boto error. I'll PR a fix shortly. 


Resolving patch:
diff --git a/cloud/amazon/ec2_asg.py b/cloud/amazon/ec2_asg.py
--- a/cloud/amazon/ec2_asg.py
+++ b/cloud/amazon/ec2_asg.py
@@ -203,6 +203,7 @@
 
 import time
 import logging as log
+import traceback
 
 from ansible.module_utils.basic import *
 from ansible.module_utils.ec2 import *
@@ -441,7 +442,7 @@ def create_autoscaling_group(connection, module):
             changed = True
             return(changed, asg_properties)
         except BotoServerError as e:
-            module.fail_json(msg=str(e))
+            module.fail_json(msg="Failed to create Autoscaling Group: %s" % str(e), exception=traceback.format_exc(e))
     else:
         as_group = as_groups[0]
         changed = False
@@ -453,14 +454,15 @@ def create_autoscaling_group(connection, module):
                 group_attr = getattr(as_group, attr)
                 # we do this because AWS and the module may return the same list
                 # sorted differently
-                try:
-                    module_attr.sort()
-                except:
-                    pass
-                try:
-                    group_attr.sort()
-                except:
-                    pass
+                if attr != 'termination_policies':
+                    try:
+                        module_attr.sort()
+                    except:
+                        pass
+                    try:
+                        group_attr.sort()
+                    except:
+                        pass
                 if group_attr != module_attr:
                     changed = True
                     setattr(as_group, attr, module_attr)
@@ -496,7 +498,7 @@ def create_autoscaling_group(connection, module):
             try:
                 as_group.update()
             except BotoServerError as e:
-                module.fail_json(msg=str(e))
+                module.fail_json(msg="Failed to update Autoscaling Group: %s" % str(e), exception=traceback.format_exc(e))
 
         if wait_for_instances:
             wait_for_new_inst(module, connection, group_name, wait_timeout, desired_capacity, 'viable_instances')
@@ -505,7 +507,7 @@ def create_autoscaling_group(connection, module):
             as_group = connection.get_all_groups(names=[group_name])[0]
             asg_properties = get_properties(as_group)
         except BotoServerError as e:
-            module.fail_json(msg=str(e))
+            module.fail_json(msg="Failed to read existing Autoscaling Groups: %s" % str(e), exception=traceback.format_exc(e))
         return(changed, asg_properties)
 
 


Test patch: