summaryrefslogtreecommitdiff
path: root/plugins/modules/vyos_command.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/modules/vyos_command.py')
-rw-r--r--plugins/modules/vyos_command.py228
1 files changed, 228 insertions, 0 deletions
diff --git a/plugins/modules/vyos_command.py b/plugins/modules/vyos_command.py
new file mode 100644
index 0000000..d688251
--- /dev/null
+++ b/plugins/modules/vyos_command.py
@@ -0,0 +1,228 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# GNU General Public License v3.0+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+---
+module: vyos_command
+short_description: Run show commands on VyOS devices using REST API
+description:
+ - Sends show commands to VyOS devices via the REST API C(/show) endpoint
+ and returns the output.
+ - Equivalent to C(vyos_command) in the CLI collection but uses the REST API.
+ - Uses REST API (C(connection=httpapi)) instead of CLI.
+version_added: "1.0.0"
+author:
+ - VyOS Community (@vyos)
+options:
+ commands:
+ description:
+ - List of show commands to run on the device.
+ - Each command is a list of path elements passed to the C(/show) endpoint.
+ - Commands may be specified as a string (space-separated) or a list.
+ type: list
+ elements: raw
+ required: true
+ wait_for:
+ description:
+ - Specifies what to evaluate from the output of the command and what
+ conditionals to apply. This argument will cause the task to wait for
+ a particular conditional to be true before moving forward.
+ type: list
+ elements: str
+ aliases: [waitfor]
+ match:
+ description:
+ - The C(match) argument is used in conjunction with the C(wait_for)
+ argument to specify the match policy.
+ type: str
+ choices: [any, all]
+ default: all
+ retries:
+ description:
+ - Specifies the number of retries a command should be run before it
+ is considered failed.
+ type: int
+ default: 10
+ interval:
+ description:
+ - Configures the interval in seconds to wait between retries of the
+ command.
+ type: int
+ default: 1
+notes:
+ - Requires C(ansible_connection=httpapi) with the VyOS httpapi plugin.
+ - C(ansible_network_os) must be set to C(vyos.rest.vyos).
+ - Only C(show) commands are supported via the REST API.
+ - Commands are passed as path lists to the C(/show) endpoint.
+"""
+
+EXAMPLES = r"""
+- name: Run show version
+ vyos.rest.vyos_command:
+ commands:
+ - - version
+ register: result
+
+- name: Run multiple show commands
+ vyos.rest.vyos_command:
+ commands:
+ - - interfaces
+ - - ip
+ - route
+ - - system
+ - uptime
+ register: result
+
+- name: Run show commands as strings
+ vyos.rest.vyos_command:
+ commands:
+ - "interfaces"
+ - "ip route"
+ - "version"
+ register: result
+
+- name: Wait for BGP to establish
+ vyos.rest.vyos_command:
+ commands:
+ - - ip
+ - bgp
+ - summary
+ wait_for:
+ - result[0] contains Established
+ retries: 10
+ interval: 5
+"""
+
+RETURN = r"""
+stdout:
+ description: List of output from each command.
+ returned: always
+ type: list
+ sample: ["VyOS 1.5.0\n...", "Interface IP Address\n..."]
+stdout_lines:
+ description: List of output split into lines for each command.
+ returned: always
+ type: list
+failed_conditions:
+ description: List of conditions that failed.
+ returned: failed
+ type: list
+"""
+
+import time
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.vyos.rest.plugins.module_utils.vyos import VyOSModule
+
+
+def parse_command(cmd):
+ """Convert a command to a path list."""
+ if isinstance(cmd, list):
+ return cmd
+ elif isinstance(cmd, str):
+ return cmd.split()
+ return list(cmd)
+
+
+def run_commands(vyos, commands):
+ """Run show commands and return stdout list."""
+ stdout = []
+ for cmd in commands:
+ path = parse_command(cmd)
+ try:
+ result = vyos.show(path)
+ stdout.append(result if result else "")
+ except Exception as e:
+ stdout.append("ERROR: %s" % str(e))
+ return stdout
+
+
+def evaluate_conditions(stdout, wait_for, match):
+ """Evaluate wait_for conditions against stdout."""
+ failed = []
+ results = []
+
+ for condition in wait_for:
+ # Parse simple conditions: "result[N] contains STRING"
+ if " contains " in condition:
+ parts = condition.split(" contains ", 1)
+ ref = parts[0].strip()
+ value = parts[1].strip()
+ # Extract index from result[N]
+ if ref.startswith("result[") and ref.endswith("]"):
+ try:
+ idx = int(ref[7:-1])
+ matched = value in stdout[idx]
+ results.append(matched)
+ if not matched:
+ failed.append(condition)
+ except (ValueError, IndexError):
+ failed.append(condition)
+ else:
+ failed.append(condition)
+ else:
+ # Unsupported condition format
+ failed.append(condition)
+
+ if match == "any":
+ return not any(results), failed
+ return bool(failed), failed
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ commands=dict(type="list", elements="raw", required=True),
+ wait_for=dict(type="list", elements="str", aliases=["waitfor"]),
+ match=dict(type="str", default="all", choices=["any", "all"]),
+ retries=dict(type="int", default=10),
+ interval=dict(type="int", default=1),
+ ),
+ supports_check_mode=True,
+ )
+
+ vyos = VyOSModule(module)
+ commands = module.params["commands"]
+ wait_for = module.params["wait_for"] or []
+ match = module.params["match"]
+ retries = module.params["retries"]
+ interval = module.params["interval"]
+
+ stdout = []
+ failed_conditions = []
+
+ for attempt in range(retries):
+ stdout = run_commands(vyos, commands)
+
+ if not wait_for:
+ break
+
+ failed_check, failed_conditions = evaluate_conditions(stdout, wait_for, match)
+ if not failed_check:
+ break
+
+ if attempt < retries - 1:
+ time.sleep(interval)
+ else:
+ if failed_conditions:
+ module.fail_json(
+ msg="One or more conditional statements have not been satisfied",
+ failed_conditions=failed_conditions,
+ )
+
+ stdout_lines = [out.splitlines() for out in stdout]
+
+ module.exit_json(
+ changed=False,
+ stdout=stdout,
+ stdout_lines=stdout_lines,
+ )
+
+
+if __name__ == "__main__":
+ main()