Repository: ansible/ansible

Issue:
ec2_asg fails to update existing ASG with new Launchconfig


##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
ec2_asg

##### ANSIBLE VERSION
```
ansible 2.4.0
  config file = /Users/byi470/Workspaces/Ansible_Developer/ansible.cfg
  configured module search path = [u'/Users/byi470/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/byi470/Workspaces/Ansible_Developer/.ansible_virtualenv/lib/python2.7/site-packages/ansible
  executable location = /Users/byi470/Workspaces/Ansible_Developer/.ansible_virtualenv/bin/ansible
  python version = 2.7.13 (default, Apr  4 2017, 08:47:57) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)]
```

##### CONFIGURATION
n/a no changes to ansible.cfg

##### OS / ENVIRONMENT
N/A

##### SUMMARY
ec2_asg unable to update an existing ASG with a new Launchconfig.

NOTE:  this operation works correctly in 2.3.1

##### STEPS TO REPRODUCE

My Goal:  update my ASGs and their launch_config to have the latest values from the Ansible Variables.  To achieve this, I :
- create new launch configs with '-temp' concatenated to the launch_config_name
- create/update asgs to use the '-temp' launch configs
- delete any launch configs using the launch_config_name
- create new launch configs using the launch_config_name
- update the asgs to use the launch_config_name
- delete the '-temp' launch configs

This process works on the first run of ansible-playbook.  The second one fails.

<!--- Paste example playbooks or commands between quotes below -->
```yaml

- name: create temp launch configs
  ec2_lc:
    name:                             "{{ launch_config_name }}-temp"
    image_id:                         "{{ ami_image }}"
    security_groups:                  "{{ security_groups }}"
    instance_type:                    "{{ instance_type }}"
    instance_monitoring:              true
    ebs_optimized:                    "{{ ebs_optimized_instances }}"
    region:                           "{{ region }}"
    instance_profile_name:            "{{ iam_role }}"
    state:                            present
    user_data:                        "{{ user_data }}"
    key_name:                         "{{ key_pair_name }}"
  with_items:
    - "{{ asg_list }}"

- name: create/update asg
  ec2_asg:
    name:                                   "{{ asg_name }}"
#    load_balancers:                         "{{ elb_names }}"
    launch_config_name:                     "{{ launch_config_name }}-temp"
    min_size:                               "{{ asg_min_size }}"
    max_size:                               "{{ asg_max_size }}"
    desired_capacity:                       "{{ asg_desired_size }}"
    health_check_period:                    "{{ asg_health_check_grace_period }}"
    health_check_type:                      "{{ asg_health_check_type }}"
    region:                                 "{{ region }}"
    vpc_zone_identifier:                     "{{ subnets }}"
    tags:                                    "{{ tags }} + {{ additional_tags }}"
    state:                                   present
    wait_for_instances:                      no
  with_items:
    - "{{ asg_list }}"

- name: delete launch_configs using the standard launch_config names
  ec2_lc:
    name:                                   "{{ launch_config_name }}"
    region:                                 "{{ region }}"
    state:                                  absent
  with_items:
    - "{{ asg_list }}"

- name: create launch configs using the standard launch_config names
  ec2_lc:
    name:                             "{{ launch_config_name }}"
    image_id:                         "{{ ami_image }}"
    security_groups:                  "{{ security_groups }}"
    instance_type:                    "{{ instance_type }}"
    instance_monitoring:              true
    ebs_optimized:                    "{{ ebs_optimized_instances }}"
    region:                           "{{ region }}"
    instance_profile_name:            "{{ iam_role }}"
    state:                            present
    user_data:                        "{{ user_data }}"
    key_name:                         "{{ key_pair_name }}"
  with_items:
    - "{{ asg_list }}"

- name: create/update asg
  ec2_asg:
    name:                                   "{{ asg_name }}"
    launch_config_name:                     "{{ launch_config_name }}"
    min_size:                               "{{ asg_min_size }}"
    max_size:                               "{{ asg_max_size }}"
    desired_capacity:                       "{{ asg_desired_size }}"
    health_check_period:                    "{{ asg_health_check_grace_period }}"
    health_check_type:                      "{{ asg_health_check_type }}"
    region:                                 "{{ region }}"
    vpc_zone_identifier:                     "{{ subnets }}"
    tags:                                    "{{ tags }} + {{ additional_tags }}"
    state:                                   present
    wait_for_instances:                      no

- name: delete launch_configs using the temp launch_config names
  ec2_lc:
    name:                                   "{{ launch_config_name }}-temp"
    region:                                 "{{ region }}"
    state:                                  absent

```

##### EXPECTED RESULTS

Ansible playbook execution completes.  And it can be run again and again.

##### ACTUAL RESULTS
```
"module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py\", line 1288, in <module>\n    main()\n  File \"/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py\", line 1277, in main\n    create_changed, asg_properties = create_autoscaling_group(connection, module)\n  File \"/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_modlib.zip/ansible/module_utils/cloud.py\", line 103, in retry_func\nKeyError: 'LaunchConfigurationName'\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}
```

ec2_asg fails to update existing ASG with new Launchconfig


##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
ec2_asg

##### ANSIBLE VERSION
```
ansible 2.4.0
  config file = /Users/byi470/Workspaces/Ansible_Developer/ansible.cfg
  configured module search path = [u'/Users/byi470/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/byi470/Workspaces/Ansible_Developer/.ansible_virtualenv/lib/python2.7/site-packages/ansible
  executable location = /Users/byi470/Workspaces/Ansible_Developer/.ansible_virtualenv/bin/ansible
  python version = 2.7.13 (default, Apr  4 2017, 08:47:57) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)]
```

##### CONFIGURATION
n/a no changes to ansible.cfg

##### OS / ENVIRONMENT
N/A

##### SUMMARY
ec2_asg unable to update an existing ASG with a new Launchconfig.

NOTE:  this operation works correctly in 2.3.1

##### STEPS TO REPRODUCE

My Goal:  update my ASGs and their launch_config to have the latest values from the Ansible Variables.  To achieve this, I :
- create new launch configs with '-temp' concatenated to the launch_config_name
- create/update asgs to use the '-temp' launch configs
- delete any launch configs using the launch_config_name
- create new launch configs using the launch_config_name
- update the asgs to use the launch_config_name
- delete the '-temp' launch configs

This process works on the first run of ansible-playbook.  The second one fails.

<!--- Paste example playbooks or commands between quotes below -->
```yaml

- name: create temp launch configs
  ec2_lc:
    name:                             "{{ launch_config_name }}-temp"
    image_id:                         "{{ ami_image }}"
    security_groups:                  "{{ security_groups }}"
    instance_type:                    "{{ instance_type }}"
    instance_monitoring:              true
    ebs_optimized:                    "{{ ebs_optimized_instances }}"
    region:                           "{{ region }}"
    instance_profile_name:            "{{ iam_role }}"
    state:                            present
    user_data:                        "{{ user_data }}"
    key_name:                         "{{ key_pair_name }}"
  with_items:
    - "{{ asg_list }}"

- name: create/update asg
  ec2_asg:
    name:                                   "{{ asg_name }}"
#    load_balancers:                         "{{ elb_names }}"
    launch_config_name:                     "{{ launch_config_name }}-temp"
    min_size:                               "{{ asg_min_size }}"
    max_size:                               "{{ asg_max_size }}"
    desired_capacity:                       "{{ asg_desired_size }}"
    health_check_period:                    "{{ asg_health_check_grace_period }}"
    health_check_type:                      "{{ asg_health_check_type }}"
    region:                                 "{{ region }}"
    vpc_zone_identifier:                     "{{ subnets }}"
    tags:                                    "{{ tags }} + {{ additional_tags }}"
    state:                                   present
    wait_for_instances:                      no
  with_items:
    - "{{ asg_list }}"

- name: delete launch_configs using the standard launch_config names
  ec2_lc:
    name:                                   "{{ launch_config_name }}"
    region:                                 "{{ region }}"
    state:                                  absent
  with_items:
    - "{{ asg_list }}"

- name: create launch configs using the standard launch_config names
  ec2_lc:
    name:                             "{{ launch_config_name }}"
    image_id:                         "{{ ami_image }}"
    security_groups:                  "{{ security_groups }}"
    instance_type:                    "{{ instance_type }}"
    instance_monitoring:              true
    ebs_optimized:                    "{{ ebs_optimized_instances }}"
    region:                           "{{ region }}"
    instance_profile_name:            "{{ iam_role }}"
    state:                            present
    user_data:                        "{{ user_data }}"
    key_name:                         "{{ key_pair_name }}"
  with_items:
    - "{{ asg_list }}"

- name: create/update asg
  ec2_asg:
    name:                                   "{{ asg_name }}"
    launch_config_name:                     "{{ launch_config_name }}"
    min_size:                               "{{ asg_min_size }}"
    max_size:                               "{{ asg_max_size }}"
    desired_capacity:                       "{{ asg_desired_size }}"
    health_check_period:                    "{{ asg_health_check_grace_period }}"
    health_check_type:                      "{{ asg_health_check_type }}"
    region:                                 "{{ region }}"
    vpc_zone_identifier:                     "{{ subnets }}"
    tags:                                    "{{ tags }} + {{ additional_tags }}"
    state:                                   present
    wait_for_instances:                      no

- name: delete launch_configs using the temp launch_config names
  ec2_lc:
    name:                                   "{{ launch_config_name }}-temp"
    region:                                 "{{ region }}"
    state:                                  absent

```

##### EXPECTED RESULTS

Ansible playbook execution completes.  And it can be run again and again.

##### ACTUAL RESULTS
```
"module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py\", line 1288, in <module>\n    main()\n  File \"/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py\", line 1277, in main\n    create_changed, asg_properties = create_autoscaling_group(connection, module)\n  File \"/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_modlib.zip/ansible/module_utils/cloud.py\", line 103, in retry_func\nKeyError: 'LaunchConfigurationName'\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}
```



Discussion:
cc @garethr
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
(traceback reformatted for easier reading)

```
Traceback (most recent call last):
  File "/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py", line 1288, in <module>
    main()
  File "/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py", line 1277, in main
    create_changed, asg_properties = create_autoscaling_group(connection, module)
  File "/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_modlib.zip/ansible/module_utils/cloud.py", line 103, in retry_func
KeyError: 'LaunchConfigurationName'

```
@waltersm1 Hi, I'm trying to reproduce this to fix it. I'm guessing at a lot of the variables in your playbook since you only provided a few static ones. Do you see anything I'm doing differently?
```
---
- hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: create temp launch configs
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc-1
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type: t1.micro
        instance_monitoring: true
        key_name: "{{ key }}"

    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc-1
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-XXXXXXXX
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: absent
        name: shertel-lc-2

    - name: create launch configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc-2
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type: t1.micro
        instance_monitoring: true
        key_name: "{{ key }}"

    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc-2
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-XXXXXXXX
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the temp launch_config names
      ec2_lc:
        name: shertel-lc-1
        region: us-east-1
        state: absent
```
needs_info
Took some testing to figure this out, but try adding a with_items.  

The playbook works on the first iteration, but then exceptions out on the second.

```
---
- hosts: localhost
  connection: local
  gather_facts: no

  vars:
    asg_list:
      - instance_type:                          t2.micro

  tasks:
    - name: create temp launch configs
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc-temp
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type:  "{{ item.instance_type }}"
        instance_monitoring: true
        user_data:                        "# empty"
        ebs_optimized:                    false
      with_items:
        - "{{ asg_list }}"



    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc-temp
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-XXXXXXXX
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: absent
        name: shertel-lc

    - name: create launch configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type: t1.micro
        instance_monitoring: true
        user_data:                        "# empty"
        ebs_optimized:                    false


    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the temp launch_config names
      ec2_lc:
        name: shertel-lc-temp
        region: us-east-1
        state: absent
```
cc @garethr
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
(traceback reformatted for easier reading)

```
Traceback (most recent call last):
  File "/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py", line 1288, in <module>
    main()
  File "/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_module_ec2_asg.py", line 1277, in main
    create_changed, asg_properties = create_autoscaling_group(connection, module)
  File "/var/folders/k5/tnq7hf_s3fjc59sxdmh2hb7c8q_pwy/T/ansible_Y9gNYv/ansible_modlib.zip/ansible/module_utils/cloud.py", line 103, in retry_func
KeyError: 'LaunchConfigurationName'

```
@waltersm1 Hi, I'm trying to reproduce this to fix it. I'm guessing at a lot of the variables in your playbook since you only provided a few static ones. Do you see anything I'm doing differently?
```
---
- hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: create temp launch configs
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc-1
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type: t1.micro
        instance_monitoring: true
        key_name: "{{ key }}"

    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc-1
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-XXXXXXXX
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: absent
        name: shertel-lc-2

    - name: create launch configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc-2
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type: t1.micro
        instance_monitoring: true
        key_name: "{{ key }}"

    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc-2
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-XXXXXXXX
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the temp launch_config names
      ec2_lc:
        name: shertel-lc-1
        region: us-east-1
        state: absent
```
needs_info
Took some testing to figure this out, but try adding a with_items.  

The playbook works on the first iteration, but then exceptions out on the second.

```
---
- hosts: localhost
  connection: local
  gather_facts: no

  vars:
    asg_list:
      - instance_type:                          t2.micro

  tasks:
    - name: create temp launch configs
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc-temp
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type:  "{{ item.instance_type }}"
        instance_monitoring: true
        user_data:                        "# empty"
        ebs_optimized:                    false
      with_items:
        - "{{ asg_list }}"



    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc-temp
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-XXXXXXXX
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: absent
        name: shertel-lc

    - name: create launch configs using the standard launch_config names
      ec2_lc:
        region: us-east-1
        state: present
        name: shertel-lc
        image_id: ami-9be6f38c
        security_groups:
          - sg-XXXXXXXX
        instance_type: t1.micro
        instance_monitoring: true
        user_data:                        "# empty"
        ebs_optimized:                    false


    - name: create/update asg
      ec2_asg:
        region: us-east-1
        state: present
        name: shertel-asg-1
        launch_config_name: shertel-lc
        min_size: 1
        max_size: 1
        desired_capacity: 1
        health_check_period: 60
        health_check_type: EC2
        vpc_zone_identifier:
          - subnet-
          - subnet-XXXXXXXX
        wait_for_instances: no

    - name: delete launch_configs using the temp launch_config names
      ec2_lc:
        name: shertel-lc-temp
        region: us-east-1
        state: absent
```

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/ec2_asg.py b/lib/ansible/modules/cloud/amazon/ec2_asg.py
--- a/lib/ansible/modules/cloud/amazon/ec2_asg.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_asg.py
@@ -423,7 +423,7 @@ def get_properties(autoscaling_group, module):
         for i in autoscaling_group_instances:
             instance_facts[i['InstanceId']] = {'health_status': i['HealthStatus'],
                                                'lifecycle_state': i['LifecycleState'],
-                                               'launch_config_name': i['LaunchConfigurationName']}
+                                               'launch_config_name': i.get('LaunchConfigurationName')}
             if i['HealthStatus'] == 'Healthy' and i['LifecycleState'] == 'InService':
                 properties['viable_instances'] += 1
             if i['HealthStatus'] == 'Healthy':


Test patch: