Repository: ansible/ansible-modules-core

Issue:
eos_command does not work with --check ansible-playbook option
<!--- Verify first that your issue/request is not already reported in GitHub -->

**Yes**
##### ISSUE TYPE

**Bug Report**
##### COMPONENT NAME

eos_command
##### ANSIBLE VERSION

2.1
##### CONFIGURATION

N/A
##### OS / ENVIRONMENT

N/A
##### SUMMARY

when i use eos_command for configuring arista devices or running commands like " write mem"  with the --check option  , what ever list of commands specified under eos_command still gets applied to the devices .  whereas --check documentation indicates the following

  -C, --check           don't make any changes; instead, try to predict some
                        of the changes that may occur

```
##### STEPS TO REPRODUCE
Sample playbook:

- name: Play to configure Vlans on arista devices
  connection: local
  gather_facts: no
  hosts: "{{  arista }}"
  tags: 
    - arista

  tasks:
     - name: Prechecks to verify vlan does not exist
       eos_command:
         commands:
           - show vlan {{vlan}} | json
         provider: "{{ cli }}"
       failed_when: "'not found in current VLAN' not in output.msg"
       register: output
     - debug: var=output       


     - name: Configure Vlans
       eos_command:
         commands:
           - enable 
           - configure terminal
           - vlan {{ vlan }}
           - name {{ vlan_desc }}
           - exit
           - exit
           - write memory
         provider: "{{ cli }}"

     - name: Postchecks to verify vlan exists
       eos_command:
         commands:
           - show vlan  {{vlan}} | json
         provider: "{{ cli }}"
       register: output
     - debug: var=output 

```
##### EXPECTED RESULTS

See problem description
##### ACTUAL RESULTS

See problem description



Discussion:
Verified that module has `supports_check_mode=True` but does not appear to check `module.check_mode` so that it only makes changes when check_mode is False.  A quick grep of networking/_/_command\* shows that all the command modules have a similar pattern.   @Qalthos, @privateip This might need to be fixed in all of the networking command modules.

@petereh I would highly recommend that you use eos_config for performing configuration operations and not eos_command.


Resolving patch:
diff --git a/network/eos/eos_command.py b/network/eos/eos_command.py
--- a/network/eos/eos_command.py
+++ b/network/eos/eos_command.py
@@ -20,7 +20,7 @@
 ---
 module: eos_command
 version_added: "2.1"
-author: "Peter sprygada (@privateip)"
+author: "Peter Sprygada (@privateip)"
 short_description: Run arbitrary command on EOS device
 description:
   - Sends an aribtrary set of commands to an EOS node and returns the results
@@ -37,7 +37,7 @@
         module is not returned until the condition is satisfied or
         the number of retries has been exceeded.
     required: true
-  waitfor:
+  wait_for:
     description:
       - Specifies what to evaluate from the output of the command
         and what conditionals to apply.  This argument will cause
@@ -46,6 +46,8 @@
         by the configured retries, the task fails.  See examples.
     required: false
     default: null
+    aliases: ['waitfor']
+    version_added: "2.2"
   retries:
     description:
       - Specifies the number of retries a command should be tried
@@ -65,9 +67,6 @@
 """
 
 EXAMPLES = """
-- eos_command:
-    commands: "{{ lookup('file', 'commands.txt') }}"
-
 - eos_command:
     commands:
         - show interface {{ item }}
@@ -109,14 +108,12 @@
   type: list
   sample: ['...', '...']
 """
+from ansible.module_utils.basic import get_exception
+from ansible.module_utils.netcmd import CommandRunner, FailedConditionsError
+from ansible.module_utils.network import NetworkError
+from ansible.module_utils.eos import get_module
 
-import time
-import shlex
-import re
-
-INDEX_RE = re.compile(r'(\[\d+\])')
-
-def iterlines(stdout):
+def to_lines(stdout):
     for item in stdout:
         if isinstance(item, basestring):
             item = str(item).split('\n')
@@ -124,8 +121,8 @@ def iterlines(stdout):
 
 def main():
     spec = dict(
-        commands=dict(type='list'),
-        waitfor=dict(type='list'),
+        commands=dict(type='list', required=True),
+        wait_for=dict(type='list', aliases=['waitfor']),
         retries=dict(default=10, type='int'),
         interval=dict(default=1, type='int')
     )
@@ -134,50 +131,54 @@ def main():
                         supports_check_mode=True)
 
     commands = module.params['commands']
+    conditionals = module.params['wait_for'] or list()
+
+    warnings = list()
 
-    retries = module.params['retries']
-    interval = module.params['interval']
+    runner = CommandRunner(module)
+
+    for cmd in commands:
+        if module.check_mode and not cmd.startswith('show'):
+            warnings.append('only show commands are supported when using '
+                            'check mode, not executing `%s`' % cmd)
+        else:
+            runner.add_command(cmd)
+
+    for item in conditionals:
+        runner.add_conditional(item)
+
+    runner.retries = module.params['retries']
+    runner.interval = module.params['interval']
 
     try:
-        queue = set()
-        for entry in (module.params['waitfor'] or list()):
-            queue.add(Conditional(entry))
-    except AttributeError:
+        runner.run()
+    except FailedConditionsError:
         exc = get_exception()
-        module.fail_json(msg=exc.message)
+        module.fail_json(msg=str(exc), failed_conditions=exc.failed_conditions)
+    except NetworkError:
+        exc = get_exception()
+        module.fail_json(msg=str(exc))
 
     result = dict(changed=False)
 
-    while retries > 0:
-        response = module.execute(commands)
-        result['stdout'] = response
-
-        for index, cmd in enumerate(commands):
+    result['stdout'] = list()
+    for cmd in commands:
+        try:
+            output = runner.get_command(cmd)
             if cmd.endswith('json'):
-                response[index] = module.from_json(response[index])
-
-        for item in list(queue):
-            if item(response):
-                queue.remove(item)
+                output = module.from_json(output)
+        except ValueError:
+            output = 'command not executed due to check_mode, see warnings'
+        result['stdout'].append(output)
 
-        if not queue:
-            break
 
-        time.sleep(interval)
-        retries -= 1
-    else:
-        failed_conditions = [item.raw for item in queue]
-        module.fail_json(msg='timeout waiting for value', failed_conditions=failed_conditions)
+    result['warnings'] = warnings
+    result['connected'] = module.connected
+    result['stdout_lines'] = list(to_lines(result['stdout']))
 
-    result['stdout_lines'] = list(iterlines(result['stdout']))
-    return module.exit_json(**result)
+    module.exit_json(**result)
 
 
-from ansible.module_utils.basic import *
-from ansible.module_utils.urls import *
-from ansible.module_utils.shell import *
-from ansible.module_utils.netcfg import *
-from ansible.module_utils.eos import *
 if __name__ == '__main__':
-        main()
+    main()
 


Test patch: