Repository: ansible/ansible

Issue:
asa_config Python3 Compatibility Issue for "backup"
<!---
Verify first that your issue/request is not already reported on GitHub.
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
Also test if the latest release, and devel branch are affected too.
ALWAYS add information AFTER (OUTSIDE) these html comments.
Otherwise it may end up being automatically closed by our bot. -->

##### SUMMARY
"backup" in asa_config fails on Python 3.6.3 with Ansible 2.5.2. Same issue as [36717](https://github.com/ansible/ansible/issues/36717) but for asa_config.

Changing line 58 of asa_config.py from:` for key in result.keys()`
To either: `for key in result.copy().keys():`
Or: `for key in list(result)`

Should sort this out for py2 or py3.

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
asa_config

##### ANSIBLE VERSION
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.2
  config file = /home/ignw/my_network_as_code/ansible.cfg
  configured module search path = ['/usr/local/lib/python3.6/dist-packages/napalm_ansible/modules']
  ansible python module location = /usr/local/lib/python3.6/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.3 (default, Oct  3 2017, 21:45:48) [GCC 7.2.0]
```

##### CONFIGURATION
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).-->
DEFAULT_ACTION_PLUGIN_PATH(/home/ignw/my_network_as_code/ansible.cfg) = ['/usr/local/lib/python3.6/dist-packages/napalm_ansible/plug
DEFAULT_HOST_LIST(/home/ignw/my_network_as_code/ansible.cfg) = ['/home/ignw/my_network_as_code/inventory']
DEFAULT_MODULE_PATH(/home/ignw/my_network_as_code/ansible.cfg) = ['/usr/local/lib/python3.6/dist-packages/napalm_ansible/modules']
HOST_KEY_CHECKING(/home/ignw/my_network_as_code/ansible.cfg) = False
RETRY_FILES_ENABLED(/home/ignw/my_network_as_code/ansible.cfg) = False

##### OS / ENVIRONMENT
<!--- Mention, BELOW THIS COMMENT, the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.-->
Distributor ID:	Ubuntu
Description:	Ubuntu 17.10
Release:	17.10
Codename:	artful

Network device (Cisco ASAv):
Cisco Adaptive Security Appliance Software Version 9.9(2)
Firepower Extensible Operating System Version 2.3(1.84)
Device Manager Version 7.9(2)

Compiled on Sun 25-Mar-18 17:34 PDT by builders
System image file is "boot:/asa992-smp-k8.bin"
Config file at boot was "startup-config"

Hardware:   ASAv, 1024 MB RAM, CPU Clarkdale 2300 MHz,
Model Id:   ASAv5
Internal ATA Compact Flash, 1024MB
Slot 1: ATA Compact Flash, 8192MB
BIOS Flash Firmware Hub @ 0x0, 0KB

##### STEPS TO REPRODUCE
<!--- For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used. -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: Backup Cisco ASA Configurations
  connection: local
  hosts: cisco-asa
  gather_facts: no
  vars:
    creds:
      host: "{{ ansible_host }}"
      username: "{{ username }}"
      password: "{{ username }}"
      authorize: yes
      auth_pass: "{{ enable_password }}"
  tags: asa
  tasks:
    - asa_config:
        provider: "{{ creds }}"
        backup: yes
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Backup of configuration to be placed in backup directory

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
<10.0.0.8> <10.0.0.8> ssh connection has completed successfully
<10.0.0.8> connection to remote device started successfully
<10.0.0.8> local domain socket listeners started successfully
<10.0.0.8>
<10.0.0.8> local domain socket path is /home/ignw/.ansible/pc/8617761c70
<10.0.0.8> socket_path: /home/ignw/.ansible/pc/8617761c70
Using module file /usr/local/lib/python3.6/dist-packages/ansible/modules/network/asa/asa_config.py
<10.0.0.8> ESTABLISH LOCAL CONNECTION FOR USER: ignw
<10.0.0.8> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.0.0.8> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411 `" && echo ansible-tmp-1526941893.6014657-134187020317411="` echo /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411 `" ) && sleep 0'
<10.0.0.8> PUT /home/ignw/.ansible/tmp/ansible-local-24856l3y7x_n7/tmpq9jw7ue_ TO /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411/asa_config.py
<10.0.0.8> EXEC /bin/sh -c 'chmod u+x /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411/ /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411/asa_config.py && sleep 0'
<10.0.0.8> EXEC /bin/sh -c '/usr/bin/python3 /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411/asa_config.py && sleep 0'
<10.0.0.8> EXEC /bin/sh -c 'rm -f -r /home/ignw/.ansible/tmp/ansible-tmp-1526941893.6014657-134187020317411/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/ansible/executor/task_executor.py", line 138, in run
    res = self._execute()
  File "/usr/local/lib/python3.6/dist-packages/ansible/executor/task_executor.py", line 558, in _execute
    result = self._handler.run(task_vars=variables)
  File "/usr/local/lib/python3.6/dist-packages/ansible/plugins/action/asa_config.py", line 58, in run
    for key in result.keys().copy():
AttributeError: 'dict_keys' object has no attribute 'copy'

fatal: [acme-sea-asa1]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

PLAY RECAP *************************************************************************************************************************
acme-sea-asa1              : ok=0    changed=0    unreachable=0    failed=1
```



Discussion:
Files identified in the description:
* [lib/ansible/modules/network/asa/asa_config.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/asa/asa_config.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @ogenstad @privateip
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Would you like to raise a PR to fix this?

Resolving patch:
diff --git a/lib/ansible/plugins/action/asa_config.py b/lib/ansible/plugins/action/asa_config.py
--- a/lib/ansible/plugins/action/asa_config.py
+++ b/lib/ansible/plugins/action/asa_config.py
@@ -55,7 +55,7 @@ def run(self, tmp=None, task_vars=None):
 
         # strip out any keys that have two leading and two trailing
         # underscore characters
-        for key in result.keys():
+        for key in list(result):
             if PRIVATE_KEYS_RE.match(key):
                 del result[key]
 


Test patch: