Repository: ansible/ansible

Issue:
ios_config: ValueError: Circular reference detected
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
ios_config

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0 (test_ios_again 554ea67e6a) last updated 2017/02/14 10:28:55 (GMT +100)

```

##### CONFIGURATION

##### OS / ENVIRONMENT

##### SUMMARY
Backtrace when running the 2.2 test cases.


##### STEPS TO REPRODUCE
Running the existing test cases from `test-network-modules`
`time ANSIBLE_DEBUG=True  ansible-playbook -vvvvv  -i  ../ansible/test/integration/inventory.network-jobarker ios.yaml  --limit ios -e "limit_to=ios_config" -u cisco -k`

```yaml
[ios]
ios01 ansible_network_os=ios
```

```yaml
- name: setup
  ios_config:
    lines: ['hostname {{ inventory_hostname }}']
    provider: "{{ cli }}"
    match: none

```

##### EXPECTED RESULTS

##### ACTUAL RESULTS
**syslog
```
Feb 14 11:24:01 x260 ansible-connection: <ios01> setup connection network_cli
Feb 14 11:24:01 x260 ansible-connection: <ios01> Traceback (most recent call last):#012  File "/home/johnb/git/ansible-inc/ansible/bin/ansible-connection", line 280, in main#012    server = Server(sf_path, pc)#012  File "/home/johnb/git/ansible-inc/ansible/bin/ansible-connection", line 123, in __init__#012    self.conn = connection_loader.get(play_context.connection, play_context, sys.stdin)#012  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/__init__.py", line 372, in get#012    found_in_cache=found_in_cache, class_only=class_only)#012  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/__init__.py", line 387, in _display_plugin_load#012    display.debug(msg)#012  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/utils/display.py", line 175, in debug#012    self.display("%6d %0.5f: %s" % (os.getpid(), time.time(), msg), color=C.COLOR_DEBUG)#012  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/utils/display.py", line 133, in display#012    fileobj.flush()#012IOError: [Errno 9] Bad file descriptor
```

```yaml
TASK [test_ios_config : setup] *******************************************************************************************************************************************************************************************************************
task path: /home/johnb/git/ansible-inc/test-network-modules-ansible/roles/test_ios_config/tests/cli/toplevel_nonidempotent.yaml:4
 17144 1487071441.50574: sending task start callback
 17144 1487071441.50576: entering _queue_task() for ios01/ios_config
 17144 1487071441.50578: Creating lock for ios_config
 17144 1487071441.50677: worker is 1 (out of 1 available)
 17144 1487071441.50697: exiting _queue_task() for ios01/ios_config
 17144 1487071441.50783: done queuing things up, now waiting for results queue to drain
 17144 1487071441.50791: waiting for pending results...
 17185 1487071441.51212: running TaskExecutor() for ios01/TASK: test_ios_config : setup
 17185 1487071441.51395: in run()
 17185 1487071441.51478: calling self._execute()
 17185 1487071441.52070: Loading FilterModule 'core' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/core.py
 17185 1487071441.53222: Loading FilterModule 'ipaddr' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/ipaddr.py
 17185 1487071441.53255: Loading FilterModule 'json_query' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/json_query.py
 17185 1487071441.53272: Loading FilterModule 'mathstuff' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/mathstuff.py
 17185 1487071441.53345: Loading TestModule 'core' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/test/core.py
 17185 1487071441.53357: Loading TestModule 'files' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/test/files.py
 17185 1487071441.53369: Loading TestModule 'mathstuff' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/test/mathstuff.py
 17185 1487071441.54305: Loading FilterModule 'core' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/core.py (found_in_cache=True, class_only=False)
 17185 1487071441.54317: Loading FilterModule 'ipaddr' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/ipaddr.py (found_in_cache=True, class_only=False)
 17185 1487071441.54334: Loading FilterModule 'json_query' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/json_query.py (found_in_cache=True, class_only=False)
 17185 1487071441.54347: Loading FilterModule 'mathstuff' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/filter/mathstuff.py (found_in_cache=True, class_only=False)
 17185 1487071441.54389: Loading TestModule 'core' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/test/core.py (found_in_cache=True, class_only=False)
 17185 1487071441.54404: Loading TestModule 'files' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/test/files.py (found_in_cache=True, class_only=False)
 17185 1487071441.54419: Loading TestModule 'mathstuff' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/test/mathstuff.py (found_in_cache=True, class_only=False)
 17185 1487071441.55000: Loading Connection 'local' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/connection/local.py
 17185 1487071441.55234: Loading ShellModule 'csh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/csh.py
 17185 1487071441.55285: Loading ShellModule 'fish' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/fish.py
 17185 1487071441.55357: Loading ShellModule 'powershell' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/powershell.py
 17185 1487071441.55375: Loading ShellModule 'sh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/sh.py
 17185 1487071441.55397: Loading ShellModule 'sh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/sh.py (found_in_cache=True, class_only=False)
 17185 1487071441.55408: in VariableManager get_vars()
 17185 1487071441.55439: done with get_vars()
 17185 1487071441.55448: Loading ActionModule 'ios_config' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/action/ios_config.py (found_in_cache=True, class_only=False)
 17185 1487071441.55454: starting attempt loop
 17185 1487071441.55458: running the handler
 17185 1487071441.55602: Loading Connection 'ssh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/connection/ssh.py (found_in_cache=False, class_only=True)
 17185 1487071441.55671: Loading Connection 'persistent' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/connection/persistent.py
 17185 1487071441.55691: Loading ShellModule 'csh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/csh.py (found_in_cache=True, class_only=False)
 17185 1487071441.55695: Loading ShellModule 'fish' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/fish.py (found_in_cache=True, class_only=False)
 17185 1487071441.55699: Loading ShellModule 'powershell' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/powershell.py (found_in_cache=True, class_only=False)
 17185 1487071441.55705: Loading ShellModule 'sh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/sh.py (found_in_cache=True, class_only=False)
 17185 1487071441.55710: Loading ShellModule 'sh' from /home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/shell/sh.py (found_in_cache=True, class_only=False)
 17185 1487071451.96930: done running TaskExecutor() for ios01/TASK: test_ios_config : setup
 17185 1487071451.96943: sending task result
 17185 1487071451.96989: done sending task result
 17185 1487071451.96995: WORKER PROCESS EXITING
 17144 1487071451.97045: in VariableManager get_vars()
 17144 1487071451.97149: done with get_vars()
 17144 1487071451.97175: marking ios01 as failed
 17144 1487071451.97187: marking host ios01 failed, current state: HOST STATE: block=3, task=1, rescue=0, always=0, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? (HOST STATE: block=0, task=4, rescue=0, always=0, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? (HOST STATE: block=0, task=2, rescue=0, always=0, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? (None), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False
 17144 1487071451.97196: ^ failed state is now: HOST STATE: block=3, task=1, rescue=0, always=0, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? (HOST STATE: block=0, task=4, rescue=0, always=0, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? (HOST STATE: block=0, task=2, rescue=0, always=0, run_state=ITERATING_COMPLETE, fail_state=FAILED_TASKS, pending_setup=False, tasks child state? (None), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False
 17144 1487071451.97204: getting the next task for host ios01
 17144 1487071451.97212: done getting next task for host ios01
 17144 1487071451.97215:  ^ task is: None
 17144 1487071451.97220:  ^ state is: HOST STATE: block=3, task=1, rescue=0, always=0, run_state=ITERATING_COMPLETE, fail_state=FAILED_TASKS, pending_setup=False, tasks child state? (None), rescue child state? (None), always child state? (None), did rescue? False, did start at task? False
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/executor/task_executor.py", line 126, in run
    res = self._execute()
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/executor/task_executor.py", line 504, in _execute
    result = self._handler.run(task_vars=variables)
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/action/ios_config.py", line 45, in run
    result = super(ActionModule, self).run(tmp, task_vars)
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/action/ios.py", line 63, in run
    return super(ActionModule, self).run(tmp, task_vars)
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/action/normal.py", line 42, in run
    results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars, wrap_async=self._task.async))
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/action/__init__.py", line 613, in _execute_module
    (module_style, shebang, module_data, module_path) = self._configure_module(module_name=module_name, module_args=module_args, task_vars=task_vars)
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/plugins/action/__init__.py", line 160, in _configure_module
    task_vars=task_vars, module_compression=self._play_context.module_compression)
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/executor/module_common.py", line 815, in modify_module
    (b_module_data, module_style, shebang) = _find_module_utils(module_name, b_module_data, module_path, module_args, task_vars, module_compression)
  File "/home/johnb/git/ansible-inc/ansible/lib/ansible/executor/module_common.py", line 626, in _find_module_utils
    python_repred_params = repr(json.dumps(params))
  File "/usr/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
ValueError: Circular reference detected

fatal: [ios01]: FAILED! => {
    "failed": true, 
    "msg": "Unexpected failure during module execution.", 
    "stdout": ""
}

```



Discussion:
This bug is about the function issues

https://github.com/ansible/ansible/issues/21400 is about backtraces ending up syslog
cc @Qalthos
[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/network/ios/ios_config.py b/lib/ansible/modules/network/ios/ios_config.py
--- a/lib/ansible/modules/network/ios/ios_config.py
+++ b/lib/ansible/modules/network/ios/ios_config.py
@@ -365,6 +365,7 @@ def main():
                     commands.extend(module.params['after'])
 
             result['commands'] = commands
+            result['updates'] = commands
             result['banners'] = banners
 
             # send the configuration commands to the device and merge
diff --git a/lib/ansible/plugins/action/ios.py b/lib/ansible/plugins/action/ios.py
--- a/lib/ansible/plugins/action/ios.py
+++ b/lib/ansible/plugins/action/ios.py
@@ -35,9 +35,7 @@ class ActionModule(_ActionModule):
 
     def run(self, tmp=None, task_vars=None):
 
-        self.load_provider()
-
-        provider = self._task.args['provider']
+        provider = self.load_provider()
 
         pc = copy.deepcopy(self._play_context)
         pc.connection = 'network_cli'
@@ -60,6 +58,7 @@ def run(self, tmp=None, task_vars=None):
             self._play_context.become = False
             self._play_context.become_method = None
 
+
         return super(ActionModule, self).run(tmp, task_vars)
 
     def _get_socket_path(self, play_context):
@@ -71,13 +70,14 @@ def _get_socket_path(self, play_context):
     def load_provider(self):
         provider = self._task.args.get('provider', {})
         for key, value in iteritems(ios_argument_spec):
-            if key in self._task.args:
-                provider[key] = self._task.args[key]
-            elif 'fallback' in value:
-                provider[key] = self._fallback(value['fallback'])
-            elif key not in provider:
-                provider[key] = None
-        self._task.args['provider'] = provider
+            if key != 'provider' and key not in provider:
+                if key in self._task.args:
+                    provider[key] = self._task.args[key]
+                elif 'fallback' in value:
+                    provider[key] = self._fallback(value['fallback'])
+                elif key not in provider:
+                    provider[key] = None
+        return provider
 
     def _fallback(self, fallback):
         strategy = fallback[0]


Test patch: