Repository: ansible/ansible

Issue:
python3 support for ec2.py inventory script
<!---
Please do not report issues/requests related to Ansible modules here !!

Report them to the appropriate modules-core or modules-extras project:
  - https://github.com/ansible/ansible-modules-core/issues
  - https://github.com/ansible/ansible-modules-extras/issues

Also verify first that your issue/request is not already reported in GitHub
-->


##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!--- Name of the plugin/task/feature -->
ec2.py inventory script

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.0.0
  config file = /Users/akinsley/code/src/git.viasat.com/databus/databox/ansible.cfg
  configured module search path = ['./library']
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
Python 3.5.2
Ansible installed with pip in a python3 -m venv.

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
MacOS El Capitan

##### SUMMARY
<!--- Explain the problem briefly -->
Our ec2 inventory takes advantage of splitting tags into groups using a comma separated list. To do the split the ec2.py script runs `map(lambda x: x.strip(), v.split(','))` to split the tag up. In python 3 this returns a generator but does not actually do the split. The generator is then not json serializable causing a failure.

Wrapping the call in `list()` fixes this problem for me.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

1. Setup ansible to run with python3
2. Use the expand_csv_tags option
3. run `python ec2.py --list`

<!--- Paste example playbooks or commands between quotes below -->
```
 $  python ec2.py.2 --list
Traceback (most recent call last):
  File "ec2.py.2", line 1510, in <module>
    Ec2Inventory()
  File "ec2.py.2", line 188, in __init__
    self.do_api_calls_update_cache()
  File "ec2.py.2", line 496, in do_api_calls_update_cache
    self.write_to_cache(self.inventory, self.cache_path_cache)
  File "ec2.py.2", line 1483, in write_to_cache
    json_data = self.json_format_dict(data, True)
  File "ec2.py.2", line 1504, in json_format_dict
    return json.dumps(data, sort_keys=True, indent=2)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 200, in encode
    chunks = list(chunks)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 429, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 436, in _iterencode
    o = _default(o)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 179, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <map object at 0x10a433438> is not JSON serializable
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
ec2.py works with python3

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
See above
```

```

python3 support for ec2.py inventory script
<!---
Please do not report issues/requests related to Ansible modules here !!

Report them to the appropriate modules-core or modules-extras project:
  - https://github.com/ansible/ansible-modules-core/issues
  - https://github.com/ansible/ansible-modules-extras/issues

Also verify first that your issue/request is not already reported in GitHub
-->


##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!--- Name of the plugin/task/feature -->
ec2.py inventory script

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.0.0
  config file = /Users/akinsley/code/src/git.viasat.com/databus/databox/ansible.cfg
  configured module search path = ['./library']
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
Python 3.5.2
Ansible installed with pip in a python3 -m venv.

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
MacOS El Capitan

##### SUMMARY
<!--- Explain the problem briefly -->
Our ec2 inventory takes advantage of splitting tags into groups using a comma separated list. To do the split the ec2.py script runs `map(lambda x: x.strip(), v.split(','))` to split the tag up. In python 3 this returns a generator but does not actually do the split. The generator is then not json serializable causing a failure.

Wrapping the call in `list()` fixes this problem for me.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

1. Setup ansible to run with python3
2. Use the expand_csv_tags option
3. run `python ec2.py --list`

<!--- Paste example playbooks or commands between quotes below -->
```
 $  python ec2.py.2 --list
Traceback (most recent call last):
  File "ec2.py.2", line 1510, in <module>
    Ec2Inventory()
  File "ec2.py.2", line 188, in __init__
    self.do_api_calls_update_cache()
  File "ec2.py.2", line 496, in do_api_calls_update_cache
    self.write_to_cache(self.inventory, self.cache_path_cache)
  File "ec2.py.2", line 1483, in write_to_cache
    json_data = self.json_format_dict(data, True)
  File "ec2.py.2", line 1504, in json_format_dict
    return json.dumps(data, sort_keys=True, indent=2)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 200, in encode
    chunks = list(chunks)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 429, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 436, in _iterencode
    o = _default(o)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/json/encoder.py", line 179, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <map object at 0x10a433438> is not JSON serializable
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
ec2.py works with python3

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
See above
```

```



Discussion:

Resolving patch:
diff --git a/contrib/inventory/ec2.py b/contrib/inventory/ec2.py
--- a/contrib/inventory/ec2.py
+++ b/contrib/inventory/ec2.py
@@ -1313,7 +1313,7 @@ def get_host_info_dict_from_instance(self, instance):
             elif key == 'ec2_tags':
                 for k, v in value.items():
                     if self.expand_csv_tags and ',' in v:
-                        v = map(lambda x: x.strip(), v.split(','))
+                        v = list(map(lambda x: x.strip(), v.split(',')))
                     key = self.to_safe('ec2_tag_' + k)
                     instance_vars[key] = v
             elif key == 'ec2_groups':


Test patch: