#!/usr/bin/python # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'network'} DOCUMENTATION = """ --- module: cli_command version_added: "2.7" author: "Nathaniel Case (@qalthos)" short_description: Run a cli command on cli-based network devices description: - Sends a command to a network device and returns the result read from the device. options: command: description: - The command to send to the remote network device. The resulting output from the command is returned, unless I(sendonly) is set. required: true prompt: description: - A single regex pattern or a sequence of patterns to evaluate the expected prompt from I(command). required: false type: list answer: description: - The answer to reply with if I(prompt) is matched. The value can be a single answer or a list of answer for multiple prompts. In case the command execution results in multiple prompts the sequence of the prompt and excepted answer should be in same order. required: false type: list sendonly: description: - The boolean value, that when set to true will send I(command) to the device but not wait for a result. type: bool default: false required: false """ EXAMPLES = """ - name: run show version on remote devices cli_command: command: show version - name: run command with json formatted output cli_command: command: show version | json - name: run command expecting user confirmation cli_command: command: commit replace prompt: This commit will replace or remove the entire running configuration answer: yes - name: run config mode command and handle prompt/answer cli_command: command: "{{ item }}" prompt: - "Exit with uncommitted changes" answer: 'y' loop: - configure - set system syslog file test any any - exit - name: multiple prompt, multiple answer cli_command: command: "copy sftp sftp://user@host//user/test.img" prompt: - "Confirm download operation" - "Password" - "Do you want to change that to the standby image" answer: - 'y' - - 'y' """ RETURN = """ stdout: description: The response from the command returned: when sendonly is false type: string sample: 'Version: VyOS 1.1.7[...]' json: description: A dictionary representing a JSON-formatted response returned: when the device response is valid JSON type: dict sample: | { "architecture": "i386", "bootupTimestamp": 1532649700.56, "modelName": "vEOS", "version": "4.15.9M" [...] } """ from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.connection import Connection, ConnectionError def main(): """entry point for module execution """ argument_spec = dict( command=dict(type='str', required=True), prompt=dict(type='list', required=False), answer=dict(type='list', required=False), sendonly=dict(type='bool', default=False, required=False), ) required_together = [['prompt', 'answer']] module = AnsibleModule(argument_spec=argument_spec, required_together=required_together, supports_check_mode=True) if module.check_mode and not module.params['command'].startswith('show'): module.fail_json( msg='Only show commands are supported when using check_mode, not ' 'executing %s' % module.params['command'] ) warnings = list() result = {'changed': False, 'warnings': warnings} connection = Connection(module._socket_path) response = '' try: response = connection.get(**module.params) except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) if not module.params['sendonly']: try: result['json'] = module.from_json(response) except ValueError: pass result.update({ 'stdout': response, }) module.exit_json(**result) if __name__ == '__main__': main()