summaryrefslogtreecommitdiff
path: root/plugins/modules
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/modules')
-rw-r--r--plugins/modules/vyos_bgp_address_family.py.preview354
-rw-r--r--plugins/modules/vyos_bgp_global.py.preview365
-rw-r--r--plugins/modules/vyos_config_file.py.preview130
-rw-r--r--plugins/modules/vyos_configure.py.preview259
-rw-r--r--plugins/modules/vyos_facts.py.preview161
-rw-r--r--plugins/modules/vyos_firewall_global.py.preview360
-rw-r--r--plugins/modules/vyos_firewall_interfaces.py.preview244
-rw-r--r--plugins/modules/vyos_firewall_rules.py.preview492
-rw-r--r--plugins/modules/vyos_generate.py.preview102
-rw-r--r--plugins/modules/vyos_image.py.preview131
-rw-r--r--plugins/modules/vyos_interfaces.py.preview401
-rw-r--r--plugins/modules/vyos_l3_interfaces.py.preview381
-rw-r--r--plugins/modules/vyos_lag_interfaces.py.preview228
-rw-r--r--plugins/modules/vyos_lldp_interfaces.py.preview227
-rw-r--r--plugins/modules/vyos_ospf_interfaces.py.preview290
-rw-r--r--plugins/modules/vyos_ospfv2.py.preview487
-rw-r--r--plugins/modules/vyos_ospfv3.py.preview257
-rw-r--r--plugins/modules/vyos_ping.py.preview180
-rw-r--r--plugins/modules/vyos_prefix_lists.py.preview412
-rw-r--r--plugins/modules/vyos_reset.py.preview108
-rw-r--r--plugins/modules/vyos_show.py.preview119
-rw-r--r--plugins/modules/vyos_static_routes.py.preview397
-rw-r--r--plugins/modules/vyos_system.py.preview147
-rw-r--r--plugins/modules/vyos_user.py.preview282
-rw-r--r--plugins/modules/vyos_vlan.py.preview197
25 files changed, 0 insertions, 6711 deletions
diff --git a/plugins/modules/vyos_bgp_address_family.py.preview b/plugins/modules/vyos_bgp_address_family.py.preview
deleted file mode 100644
index ff80053..0000000
--- a/plugins/modules/vyos_bgp_address_family.py.preview
+++ /dev/null
@@ -1,354 +0,0 @@
-#!/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_bgp_address_family
-short_description: BGP Address Family resource module via REST API.
-description:
- - Manages BGP address-family configuration (networks, redistribute,
- aggregate-address, per-neighbor AFI settings) via the VyOS HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: BGP address-family configuration.
- type: dict
- suboptions:
- as_number:
- description: Local AS number.
- type: int
- required: true
- address_family:
- description: Global address-family parameters.
- type: list
- elements: dict
- suboptions:
- afi:
- description: Address family (ipv4 or ipv6).
- type: str
- choices: [ipv4, ipv6]
- aggregate_address:
- description: List of BGP aggregate networks.
- type: list
- elements: dict
- suboptions:
- prefix:
- type: str
- as_set:
- type: bool
- summary_only:
- type: bool
- networks:
- description: Networks to originate.
- type: list
- elements: dict
- suboptions:
- prefix:
- type: str
- path_limit:
- type: int
- backdoor:
- type: bool
- route_map:
- type: str
- redistribute:
- description: Protocols to redistribute.
- type: list
- elements: dict
- suboptions:
- protocol:
- type: str
- choices: [connected, kernel, ospf, ospfv3, rip, ripng, static]
- table:
- type: str
- route_map:
- type: str
- metric:
- type: int
- neighbors:
- description: Per-neighbor address-family settings.
- type: list
- elements: dict
- suboptions:
- neighbor_address:
- description: Neighbor IP.
- type: str
- address_family:
- type: list
- elements: dict
- suboptions:
- afi:
- type: str
- choices: [ipv4, ipv6]
- allowas_in:
- type: int
- as_override:
- type: bool
- route_map:
- description: Route-map settings.
- type: dict
- suboptions:
- import_map:
- type: str
- export_map:
- type: str
- soft_reconfiguration:
- type: bool
- nexthop_self:
- type: bool
- remove_private_as:
- type: bool
- state:
- description: Desired state.
- type: str
- choices: [merged, replaced, deleted, gathered]
- default: merged
- hostname:
- description: Device IP or FQDN.
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- description: Config before module ran.
- returned: always
- type: dict
-after:
- description: Config after module ran.
- returned: when changed
- type: dict
-commands:
- description: Commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def _get_bgp(client):
- try:
- result = client.retrieve_show_config(["protocols", "bgp"])
- return result.get("data") or {}
- except VyOSRestError:
- return {}
-
-
-def _afi_unicast_key(afi):
- return "ipv4-unicast" if afi == "ipv4" else "ipv6-unicast"
-
-
-def _apply(client, config, commands):
- asn = str(config["as_number"])
- base = ["protocols", "bgp", asn]
-
- for af in config.get("address_family") or []:
- afi = af["afi"]
- af_base = base + ["address-family", _afi_unicast_key(afi)]
-
- for agg in af.get("aggregate_address") or []:
- p = agg["prefix"]
- agg_base = af_base + ["aggregate-address", p]
- client.configure_set(agg_base)
- commands.append("set {b}".format(b=" ".join(agg_base)))
- if agg.get("as_set"):
- client.configure_set(agg_base + ["as-set"])
- if agg.get("summary_only"):
- client.configure_set(agg_base + ["summary-only"])
-
- for net in af.get("networks") or []:
- net_base = af_base + ["network", net["prefix"]]
- client.configure_set(net_base)
- commands.append("set {b}".format(b=" ".join(net_base)))
- if net.get("route_map"):
- client.configure_set(net_base + ["route-map"], net["route_map"])
- if net.get("backdoor"):
- client.configure_set(net_base + ["backdoor"])
-
- for redist in af.get("redistribute") or []:
- r_base = af_base + ["redistribute", redist["protocol"]]
- client.configure_set(r_base)
- commands.append("set {b}".format(b=" ".join(r_base)))
- if redist.get("metric"):
- client.configure_set(r_base + ["metric"], str(redist["metric"]))
- if redist.get("route_map"):
- client.configure_set(r_base + ["route-map"], redist["route_map"])
-
- for nbr in config.get("neighbors") or []:
- n_base = base + ["neighbor", nbr["neighbor_address"]]
- for af in nbr.get("address_family") or []:
- afi = af["afi"]
- n_af_base = n_base + ["address-family", _afi_unicast_key(afi)]
- client.configure_set(n_af_base)
- commands.append("set {b}".format(b=" ".join(n_af_base)))
- if af.get("allowas_in"):
- client.configure_set(n_af_base + ["allowas-in", "number"], str(af["allowas_in"]))
- if af.get("as_override"):
- client.configure_set(n_af_base + ["as-override"])
- if af.get("nexthop_self"):
- client.configure_set(n_af_base + ["nexthop-self"])
- if af.get("remove_private_as"):
- client.configure_set(n_af_base + ["remove-private-as"])
- if af.get("soft_reconfiguration"):
- client.configure_set(n_af_base + ["soft-reconfiguration", "inbound"])
- rm = af.get("route_map") or {}
- if rm.get("import_map"):
- client.configure_set(n_af_base + ["route-map", "import"], rm["import_map"])
- if rm.get("export_map"):
- client.configure_set(n_af_base + ["route-map", "export"], rm["export_map"])
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="dict",
- options=dict(
- as_number=dict(type="int", required=True),
- address_family=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", choices=["ipv4", "ipv6"]),
- aggregate_address=dict(
- type="list",
- elements="dict",
- options=dict(
- prefix=dict(type="str"),
- as_set=dict(type="bool"),
- summary_only=dict(type="bool"),
- ),
- ),
- networks=dict(
- type="list",
- elements="dict",
- options=dict(
- prefix=dict(type="str"),
- path_limit=dict(type="int"),
- backdoor=dict(type="bool"),
- route_map=dict(type="str"),
- ),
- ),
- redistribute=dict(
- type="list",
- elements="dict",
- options=dict(
- protocol=dict(
- type="str",
- choices=[
- "connected",
- "kernel",
- "ospf",
- "ospfv3",
- "rip",
- "ripng",
- "static",
- ],
- ),
- table=dict(type="str"),
- route_map=dict(type="str"),
- metric=dict(type="int"),
- ),
- ),
- ),
- ),
- neighbors=dict(
- type="list",
- elements="dict",
- options=dict(
- neighbor_address=dict(type="str"),
- address_family=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", choices=["ipv4", "ipv6"]),
- allowas_in=dict(type="int"),
- as_override=dict(type="bool"),
- nexthop_self=dict(type="bool"),
- remove_private_as=dict(type="bool"),
- soft_reconfiguration=dict(type="bool"),
- route_map=dict(
- type="dict",
- options=dict(
- import_map=dict(type="str"),
- export_map=dict(type="str"),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[("state", "merged", ["config"]), ("state", "replaced", ["config"])],
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config")
- commands = []
- changed = False
- before = _get_bgp(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- if before:
- client.configure_delete(["protocols", "bgp"])
- commands.append("delete protocols bgp")
- changed = True
- elif state in ("merged", "replaced"):
- if state == "replaced" and before:
- client.configure_delete(["protocols", "bgp"])
- commands.append("delete protocols bgp")
- _apply(client, config, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get_bgp(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_bgp_global.py.preview b/plugins/modules/vyos_bgp_global.py.preview
deleted file mode 100644
index 6a08f4f..0000000
--- a/plugins/modules/vyos_bgp_global.py.preview
+++ /dev/null
@@ -1,365 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_bgp_global
-short_description: Manage BGP global configuration on VyOS via the REST API.
-description:
- - Manages BGP global parameters on VyOS devices using the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_bgp_global) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: BGP global configuration.
- type: dict
- suboptions:
- as_number:
- description: Local BGP AS number.
- type: int
- required: true
- router_id:
- description: BGP router ID (IPv4 address).
- type: str
- neighbors:
- description: List of BGP neighbor configurations.
- type: list
- elements: dict
- suboptions:
- neighbor:
- description: Neighbor IP address.
- type: str
- required: true
- remote_as:
- description: Neighbor's AS number.
- type: int
- description:
- description: Neighbor description.
- type: str
- password:
- description: MD5 authentication password.
- type: str
- no_log: true
- update_source:
- description: Local interface or address for BGP session.
- type: str
- ebgp_multihop:
- description: Maximum hops for eBGP sessions.
- type: int
- shutdown:
- description: Whether to administratively shut down the neighbor.
- type: bool
- networks:
- description: List of networks to originate.
- type: list
- elements: dict
- suboptions:
- prefix:
- description: Network prefix to advertise.
- type: str
- required: true
- route_map:
- description: Route map to apply.
- type: str
- redistribute:
- description: List of protocols to redistribute into BGP.
- type: list
- elements: dict
- suboptions:
- protocol:
- description: Protocol to redistribute.
- type: str
- choices: [connected, kernel, ospf, ospfv3, rip, ripng, static]
- required: true
- metric:
- description: Metric for redistributed routes.
- type: int
- route_map:
- description: Route map to apply.
- type: str
- state:
- description:
- - C(merged): Merge BGP config with existing.
- - C(replaced): Replace entire BGP config.
- - C(deleted): Remove BGP configuration.
- - C(gathered): Read BGP config from device.
- type: str
- choices: [merged, replaced, deleted, gathered]
- default: merged
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.vyos.vyos_bgp_global
-examples: |
- - name: Configure BGP
- vyos.rest.vyos_bgp_global:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- as_number: 65001
- router_id: 192.168.1.1
- neighbors:
- - neighbor: 192.168.2.1
- remote_as: 65002
- description: "Peer AS65002"
- networks:
- - prefix: 10.0.0.0/8
- redistribute:
- - protocol: connected
- state: merged
-
- - name: Remove BGP configuration
- vyos.rest.vyos_bgp_global:
- hostname: 192.168.1.1
- api_key: MY-KEY
- state: deleted
-"""
-
-RETURN = r"""
-before:
- description: BGP config before the module ran.
- returned: always
- type: dict
-after:
- description: BGP config after the module ran.
- returned: when changed
- type: dict
-gathered:
- description: BGP config read from device (state=gathered).
- returned: when state is gathered
- type: dict
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_BGP_BASE = ["protocols", "bgp"]
-
-
-def _get_bgp(client):
- try:
- result = client.retrieve_show_config(_BGP_BASE)
- return result.get("data") or {}
- except VyOSRestError:
- return {}
-
-
-def _apply_bgp(client, config, commands):
- asn = str(config["as_number"])
- base = _BGP_BASE + [asn]
- client.configure_set(base)
- commands.append("set protocols bgp {a}".format(a=asn))
-
- if config.get("router_id"):
- client.configure_set(base + ["parameters", "router-id"], config["router_id"])
- commands.append(
- "set protocols bgp {a} parameters router-id {r}".format(
- a=asn,
- r=config["router_id"],
- ),
- )
-
- for nbr in config.get("neighbors") or []:
- nbase = base + ["neighbor", nbr["neighbor"]]
- client.configure_set(nbase)
- commands.append("set protocols bgp {a} neighbor {n}".format(a=asn, n=nbr["neighbor"]))
- if nbr.get("remote_as"):
- client.configure_set(nbase + ["remote-as"], str(nbr["remote_as"]))
- commands.append(
- "set protocols bgp {a} neighbor {n} remote-as {r}".format(
- a=asn,
- n=nbr["neighbor"],
- r=nbr["remote_as"],
- ),
- )
- if nbr.get("description"):
- client.configure_set(nbase + ["description"], nbr["description"])
- if nbr.get("password"):
- client.configure_set(nbase + ["password"], nbr["password"])
- if nbr.get("update_source"):
- client.configure_set(nbase + ["update-source"], nbr["update_source"])
- if nbr.get("ebgp_multihop"):
- client.configure_set(nbase + ["ebgp-multihop"], str(nbr["ebgp_multihop"]))
- if nbr.get("shutdown"):
- client.configure_set(nbase + ["shutdown"])
- commands.append(
- "set protocols bgp {a} neighbor {n} shutdown".format(
- a=asn,
- n=nbr["neighbor"],
- ),
- )
-
- for net in config.get("networks") or []:
- nbase = base + ["address-family", "ipv4-unicast", "network", net["prefix"]]
- client.configure_set(nbase)
- commands.append(
- "set protocols bgp {a} address-family ipv4-unicast network {p}".format(
- a=asn,
- p=net["prefix"],
- ),
- )
- if net.get("route_map"):
- client.configure_set(nbase + ["route-map"], net["route_map"])
-
- for redist in config.get("redistribute") or []:
- rbase = base + [
- "address-family",
- "ipv4-unicast",
- "redistribute",
- redist["protocol"],
- ]
- client.configure_set(rbase)
- commands.append(
- "set protocols bgp {a} address-family ipv4-unicast redistribute {p}".format(
- a=asn,
- p=redist["protocol"],
- ),
- )
- if redist.get("metric"):
- client.configure_set(rbase + ["metric"], str(redist["metric"]))
- if redist.get("route_map"):
- client.configure_set(rbase + ["route-map"], redist["route_map"])
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="dict",
- options=dict(
- as_number=dict(type="int", required=True),
- router_id=dict(type="str"),
- neighbors=dict(
- type="list",
- elements="dict",
- options=dict(
- neighbor=dict(type="str", required=True),
- remote_as=dict(type="int"),
- description=dict(type="str"),
- password=dict(type="str", no_log=True),
- update_source=dict(type="str"),
- ebgp_multihop=dict(type="int"),
- shutdown=dict(type="bool"),
- ),
- ),
- networks=dict(
- type="list",
- elements="dict",
- options=dict(
- prefix=dict(type="str", required=True),
- route_map=dict(type="str"),
- ),
- ),
- redistribute=dict(
- type="list",
- elements="dict",
- options=dict(
- protocol=dict(
- type="str",
- required=True,
- choices=[
- "connected",
- "kernel",
- "ospf",
- "ospfv3",
- "rip",
- "ripng",
- "static",
- ],
- ),
- metric=dict(type="int"),
- route_map=dict(type="str"),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[
- ("state", "merged", ["config"]),
- ("state", "replaced", ["config"]),
- ],
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config")
- commands = []
- changed = False
-
- before = _get_bgp(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
-
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- if before:
- client.configure_delete(_BGP_BASE)
- commands.append("delete protocols bgp")
- changed = True
-
- elif state in ("merged", "replaced"):
- if state == "replaced" and before:
- client.configure_delete(_BGP_BASE)
- commands.append("delete protocols bgp")
- _apply_bgp(client, config, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get_bgp(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_config_file.py.preview b/plugins/modules/vyos_config_file.py.preview
deleted file mode 100644
index 9d5e48a..0000000
--- a/plugins/modules/vyos_config_file.py.preview
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_config_file
-short_description: Save or load VyOS configuration files via the REST API.
-description:
- - Manages VyOS configuration persistence via the HTTPS REST API
- (C(/config-file) endpoint).
- - Use I(op=save) to write the running configuration to a file.
- - Use I(op=load) to load a configuration from a file and apply it.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- op:
- description:
- - C(save) - Save the running configuration to I(file) or the default C(/config/config.boot).
- - C(load) - Load and commit the configuration from I(file).
- type: str
- choices: [save, load]
- default: save
- file:
- description:
- - Path on the VyOS device for save/load target.
- - If omitted for C(save), the device uses its default boot config path.
- type: str
- hostname:
- description:
- - IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description:
- - HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description:
- - API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description:
- - Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description:
- - Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+"""
-
-RETURN = r"""
-output:
- description: Text output from the config-file operation.
- returned: success
- type: str
-"""
-
-EXAMPLES = r"""
-- name: Save running config (default location)
- vyos.rest.vyos_config_file:
- hostname: 192.168.1.1
- api_key: MY-KEY
- op: save
-
-- name: Save running config to a custom file
- vyos.rest.vyos_config_file:
- hostname: 192.168.1.1
- api_key: MY-KEY
- op: save
- file: /config/backups/config.boot.bak
-
-- name: Load a configuration from file
- vyos.rest.vyos_config_file:
- hostname: 192.168.1.1
- api_key: MY-KEY
- op: load
- file: /config/backups/config.boot.bak
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def main():
- argument_spec = dict(
- op=dict(type="str", default="save", choices=["save", "load"]),
- file=dict(type="str"),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[("op", "load", ["file"])],
- supports_check_mode=False,
- )
-
- client = VyOSRestClient(module)
- op = module.params["op"]
- file_path = module.params.get("file")
-
- try:
- if op == "save":
- result = client.config_file_save(file_path)
- else:
- result = client.config_file_load(file_path)
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=True, output=result.get("data", ""))
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_configure.py.preview b/plugins/modules/vyos_configure.py.preview
deleted file mode 100644
index 355a78c..0000000
--- a/plugins/modules/vyos_configure.py.preview
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_configure
-short_description: Manage VyOS device configuration via the REST API.
-description:
- - Sends one or more C(set) or C(delete) configuration commands to a VyOS
- device via its HTTPS REST API (C(/configure) endpoint).
- - Each command in I(commands) is executed and committed atomically.
- - Supports Ansible check-mode (C(check_mode=yes)) - no changes are applied.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- commands:
- description:
- - List of VyOS configuration commands.
- - Each item may be either a plain string in VyOS CLI syntax
- (e.g. C(set interfaces ethernet eth0 description 'WAN'))
- or a dict with keys C(op), C(path), and optionally C(value).
- type: list
- elements: raw
- required: true
- save:
- description:
- - Whether to save the configuration to disk after a successful commit.
- type: bool
- default: false
- hostname:
- description:
- - IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description:
- - HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description:
- - API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description:
- - Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description:
- - Validate the device's TLS certificate.
- type: bool
- default: false
-notes:
- - The VyOS HTTP API must be enabled on the device before using this module.
- - Enable with C(set service https api keys id <ID> key <KEY>) and
- C(set service https api rest), then C(commit && save).
- - Tested against VyOS 1.3 and 1.4.
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.rest.vyos_retrieve
- - module: vyos.rest.vyos_show"""
-
-RETURN = r"""
-commands_sent:
- description: The list of commands dispatched to the API.
- returned: always
- type: list
- elements: dict
- sample:
- - op: set
- path: ["system", "host-name"]
- value: vyos-router
-changed:
- description: Whether the device configuration was modified.
- returned: always
- type: bool
-saved:
- description: Whether the configuration was saved to disk.
- returned: always
- type: bool
-"""
-
-import re
-
-
-EXAMPLES = r"""
-- name: Set hostname via REST API
- vyos.rest.vyos_configure:
- hostname: 192.168.1.1
- api_key: MY-KEY
- commands:
- - "set system host-name vyos-router"
-
-- name: Configure an interface description and address
- vyos.rest.vyos_configure:
- hostname: 192.168.1.1
- api_key: MY-KEY
- commands:
- - "set interfaces ethernet eth1 description 'UPLINK'"
- - "set interfaces ethernet eth1 address 10.0.0.1/30"
- save: true
-
-- name: Delete a static route using dict syntax
- vyos.rest.vyos_configure:
- hostname: 192.168.1.1
- api_key: MY-KEY
- commands:
- - op: delete
- path: ["protocols", "static", "route", "192.0.2.0/24"]
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def _parse_cli_command(cmd_str):
- """Parse a VyOS CLI-syntax string into an API payload dict.
-
- Supports:
- set <path> [<value>]
- delete <path>
- comment <path> <comment>
-
- Args:
- cmd_str (str): e.g. "set interfaces ethernet eth0 description 'WAN'"
-
- Returns:
- dict: e.g. {"op": "set", "path": [...], "value": "WAN"}
- """
- cmd_str = cmd_str.strip()
- op_match = re.match(r"^(set|delete|comment)\s+(.+)$", cmd_str, re.IGNORECASE)
- if not op_match:
- raise ValueError(
- "Cannot parse command '{cmd}'. Must start with set/delete/comment.".format(
- cmd=cmd_str,
- ),
- )
- op = op_match.group(1).lower()
- rest = op_match.group(2).strip()
-
- # Extract a quoted or bare trailing value for 'set'
- value = None
- if op == "set":
- # Look for a trailing quoted value: '...' or "..."
- quoted = re.search(r"""(['"])(.*?)\1\s*$""", rest)
- if quoted:
- value = quoted.group(2)
- rest = rest[: quoted.start()].strip()
- else:
- # Bare final token may be the value if the second-to-last token
- # is a known leaf keyword – use a simple heuristic: if the
- # last segment has no sub-tokens we treat it as value.
- tokens = rest.split()
- # We cannot know the schema here, so we pass the full path and
- # no value; the device will decide.
- path = tokens
- return {"op": op, "path": path}
-
- path = rest.split()
- payload = {"op": op, "path": path}
- if value is not None:
- payload["value"] = value
- return payload
-
-
-def _normalise_commands(raw_commands):
- """Normalise the mixed list of str/dict commands into API dicts."""
- result = []
- for item in raw_commands:
- if isinstance(item, dict):
- if "op" not in item or "path" not in item:
- raise ValueError(
- "Command dict must have 'op' and 'path' keys: {item}".format(
- item=item,
- ),
- )
- result.append(item)
- elif isinstance(item, str):
- result.append(_parse_cli_command(item))
- else:
- raise ValueError(
- "Command must be a string or dict, got: {t}".format(t=type(item)),
- )
- return result
-
-
-def main():
- argument_spec = dict(
- commands=dict(type="list", elements="raw", required=True),
- save=dict(type="bool", default=False),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- try:
- commands = _normalise_commands(module.params["commands"])
- except ValueError as exc:
- module.fail_json(msg=str(exc))
-
- if module.check_mode:
- module.exit_json(
- changed=True,
- commands_sent=commands,
- saved=False,
- msg="Check mode: no changes applied.",
- )
-
- client = VyOSRestClient(module)
- changed = False
- saved = False
-
- try:
- for cmd in commands:
- op = cmd["op"].lower()
- path = cmd["path"]
- value = cmd.get("value")
- if op == "set":
- client.configure_set(path, value)
- elif op == "delete":
- client.configure_delete(path)
- elif op == "comment":
- client.configure_comment(path, value or "")
- else:
- module.fail_json(
- msg="Unsupported op '{op}'".format(op=op),
- )
- changed = True
-
- if module.params["save"]:
- client.config_file_save()
- saved = True
-
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc), commands_sent=commands)
-
- module.exit_json(changed=changed, commands_sent=commands, saved=saved)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_facts.py.preview b/plugins/modules/vyos_facts.py.preview
deleted file mode 100644
index 66e684b..0000000
--- a/plugins/modules/vyos_facts.py.preview
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/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_facts
-short_description: Get facts about VyOS devices via REST API.
-description:
- - Collects facts from VyOS devices using the HTTPS REST API.
- - Returns system info and optionally per-resource configuration facts.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- gather_subset:
- description:
- - Restrict facts to a subset. Use C(all), C(default), C(config), or C(min).
- type: list
- elements: str
- default: ["min"]
- gather_network_resources:
- description:
- - Which network resource facts to gather.
- type: list
- elements: str
- available_network_resources:
- description:
- - When true, return a list of available resource names.
- type: bool
- default: false
- hostname:
- description:
- - Device IP or FQDN.
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-ansible_facts:
- description: Dictionary of facts keyed by resource name.
- returned: always
- type: dict
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_NETWORK_RESOURCES = [
- "interfaces",
- "l3_interfaces",
- "lag_interfaces",
- "lldp_global",
- "lldp_interfaces",
- "static_routes",
- "firewall_rules",
- "firewall_global",
- "firewall_interfaces",
- "ospfv2",
- "ospfv3",
-]
-
-_RESOURCE_PATHS = {
- "interfaces": ["interfaces"],
- "l3_interfaces": ["interfaces"],
- "lag_interfaces": ["interfaces", "bonding"],
- "lldp_global": ["service", "lldp"],
- "lldp_interfaces": ["service", "lldp"],
- "static_routes": ["protocols", "static"],
- "firewall_rules": ["firewall"],
- "firewall_global": ["firewall"],
- "firewall_interfaces": ["firewall"],
- "ospfv2": ["protocols", "ospf"],
- "ospfv3": ["protocols", "ospfv3"],
-}
-
-
-def _get_subset(client, resource):
- path = _RESOURCE_PATHS.get(resource, [])
- try:
- result = client.retrieve_show_config(path)
- return result.get("data") or {}
- except VyOSRestError:
- return {}
-
-
-def main():
- argument_spec = dict(
- gather_subset=dict(type="list", elements="str", default=["min"]),
- gather_network_resources=dict(type="list", elements="str"),
- available_network_resources=dict(type="bool", default=False),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- client = VyOSRestClient(module)
- facts = {}
-
- if module.params["available_network_resources"]:
- facts["available_network_resources"] = _NETWORK_RESOURCES
-
- gather_subset = module.params["gather_subset"]
- get_all = "all" in gather_subset
-
- # Always gather system info for "min" or "all"
- if get_all or "min" in gather_subset or "default" in gather_subset:
- try:
- info = client.info()
- facts["version"] = info.get("data", {}).get("version", "")
- facts["hostname"] = info.get("data", {}).get("hostname", "")
- except VyOSRestError:
- pass
-
- # Config subset
- if get_all or "config" in gather_subset:
- try:
- result = client.retrieve_show_config([])
- facts["config"] = result.get("data") or {}
- except VyOSRestError:
- facts["config"] = {}
-
- # Network resources
- requested = module.params.get("gather_network_resources") or []
- if "all" in requested:
- requested = _NETWORK_RESOURCES
-
- for resource in requested:
- if resource.startswith("!"):
- continue
- if resource in _NETWORK_RESOURCES:
- facts["network_resources"] = facts.get("network_resources", {})
- facts["network_resources"][resource] = _get_subset(client, resource)
-
- module.exit_json(changed=False, ansible_facts=facts)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_firewall_global.py.preview b/plugins/modules/vyos_firewall_global.py.preview
deleted file mode 100644
index a3974fd..0000000
--- a/plugins/modules/vyos_firewall_global.py.preview
+++ /dev/null
@@ -1,360 +0,0 @@
-#!/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_firewall_global
-short_description: Firewall global resource module via REST API.
-description:
- - Manages global VyOS firewall parameters (groups, ICMP redirect policy,
- source validation, ping policy) via the HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: Global firewall configuration.
- type: dict
- suboptions:
- validation:
- description: Source-validation policy (strict/loose/disable).
- type: str
- choices: [strict, loose, disable]
- config_trap:
- description: SNMP trap on firewall config changes.
- type: bool
- ping:
- description: ICMP echo policy.
- type: dict
- suboptions:
- all:
- type: bool
- broadcast:
- type: bool
- route_redirects:
- description: ICMP redirect / source-route options per AFI.
- type: list
- elements: dict
- suboptions:
- afi:
- type: str
- choices: [ipv4, ipv6]
- required: true
- icmp_redirects:
- type: dict
- suboptions:
- send:
- type: bool
- receive:
- type: bool
- ip_src_route:
- type: bool
- group:
- description: Firewall object groups.
- type: dict
- suboptions:
- address_group:
- type: list
- elements: dict
- suboptions:
- name:
- type: str
- required: true
- description:
- type: str
- members:
- description: List of IP addresses or ranges.
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- afi:
- type: str
- default: ipv4
- choices: [ipv4, ipv6]
- network_group:
- type: list
- elements: dict
- suboptions:
- name:
- type: str
- required: true
- description:
- type: str
- members:
- description: List of network prefixes.
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- port_group:
- type: list
- elements: dict
- suboptions:
- name:
- type: str
- required: true
- description:
- type: str
- members:
- description: List of port numbers or ranges.
- type: list
- elements: dict
- suboptions:
- port:
- type: str
- state:
- description: Desired state.
- type: str
- choices: [merged, replaced, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: dict
-after:
- returned: when changed
- type: dict
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_FW_BASE = ["firewall"]
-
-
-def _get(client):
- try:
- r = client.retrieve_show_config(_FW_BASE)
- return r.get("data") or {}
- except VyOSRestError:
- return {}
-
-
-def _apply(client, config, commands):
- if config.get("validation"):
- path = (
- _FW_BASE + ["ip", "src-route"]
- if config["validation"] == "disable"
- else _FW_BASE + ["ip", "enable-default-log"]
- )
- # Use the proper path
- p = (
- ["firewall", "global-options", "source-validation"]
- if client.retrieve_exists(["firewall", "global-options"])
- else ["firewall", "ip", "src-route"]
- )
- client.configure_set(["firewall", "ip", "source-validation"], config["validation"])
- commands.append("set firewall ip source-validation {v}".format(v=config["validation"]))
-
- if config.get("config_trap") is not None:
- val = "enable" if config["config_trap"] else "disable"
- client.configure_set(["firewall", "config-trap"], val)
- commands.append("set firewall config-trap {v}".format(v=val))
-
- ping = config.get("ping") or {}
- if ping.get("all") is not None:
- action = "enable" if ping["all"] else "disable"
- client.configure_set(["firewall", "ip", "ping", "all"], action)
- commands.append("set firewall ip ping all {a}".format(a=action))
- if ping.get("broadcast") is not None:
- action = "enable" if ping["broadcast"] else "disable"
- client.configure_set(["firewall", "ip", "ping", "broadcast"], action)
- commands.append("set firewall ip ping broadcast {a}".format(a=action))
-
- for rr in config.get("route_redirects") or []:
- afi = rr["afi"]
- ip_key = "ip" if afi == "ipv4" else "ipv6"
- icmp = rr.get("icmp_redirects") or {}
- if icmp.get("send") is not None:
- p = ["firewall", ip_key, "send-redirects"]
- client.configure_set(p, "enable" if icmp["send"] else "disable")
- commands.append(
- "set {p} {v}".format(p=" ".join(p), v="enable" if icmp["send"] else "disable"),
- )
- if icmp.get("receive") is not None:
- p = ["firewall", ip_key, "disable-forwarding"]
- client.configure_set(p, "enable" if not icmp["receive"] else "disable")
- if rr.get("ip_src_route") is not None:
- p = ["firewall", ip_key, "source-route"]
- client.configure_set(p, "enable" if rr["ip_src_route"] else "disable")
-
- grp = config.get("group") or {}
- for ag in grp.get("address_group") or []:
- gpath = ["firewall", "group", "address-group", ag["name"]]
- client.configure_set(gpath)
- commands.append("set {p}".format(p=" ".join(gpath)))
- if ag.get("description"):
- client.configure_set(gpath + ["description"], ag["description"])
- for m in ag.get("members") or []:
- client.configure_set(gpath + ["address"], m["address"])
- commands.append("set {p} address {a}".format(p=" ".join(gpath), a=m["address"]))
-
- for ng in grp.get("network_group") or []:
- gpath = ["firewall", "group", "network-group", ng["name"]]
- client.configure_set(gpath)
- commands.append("set {p}".format(p=" ".join(gpath)))
- if ng.get("description"):
- client.configure_set(gpath + ["description"], ng["description"])
- for m in ng.get("members") or []:
- client.configure_set(gpath + ["network"], m["address"])
-
- for pg in grp.get("port_group") or []:
- gpath = ["firewall", "group", "port-group", pg["name"]]
- client.configure_set(gpath)
- commands.append("set {p}".format(p=" ".join(gpath)))
- if pg.get("description"):
- client.configure_set(gpath + ["description"], pg["description"])
- for m in pg.get("members") or []:
- client.configure_set(gpath + ["port"], str(m["port"]))
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="dict",
- options=dict(
- validation=dict(type="str", choices=["strict", "loose", "disable"]),
- config_trap=dict(type="bool"),
- ping=dict(
- type="dict",
- options=dict(all=dict(type="bool"), broadcast=dict(type="bool")),
- ),
- route_redirects=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", required=True, choices=["ipv4", "ipv6"]),
- icmp_redirects=dict(
- type="dict",
- options=dict(send=dict(type="bool"), receive=dict(type="bool")),
- ),
- ip_src_route=dict(type="bool"),
- ),
- ),
- group=dict(
- type="dict",
- options=dict(
- address_group=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- description=dict(type="str"),
- afi=dict(type="str", default="ipv4"),
- members=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str")),
- ),
- ),
- ),
- network_group=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- description=dict(type="str"),
- members=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str")),
- ),
- ),
- ),
- port_group=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- description=dict(type="str"),
- members=dict(
- type="list",
- elements="dict",
- options=dict(port=dict(type="str")),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[("state", "merged", ["config"]), ("state", "replaced", ["config"])],
- supports_check_mode=True,
- )
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config")
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- if before:
- client.configure_delete(_FW_BASE)
- commands.append("delete firewall")
- changed = True
- elif state in ("merged", "replaced"):
- if state == "replaced" and before:
- client.configure_delete(_FW_BASE)
- commands.append("delete firewall")
- _apply(client, config, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_firewall_interfaces.py.preview b/plugins/modules/vyos_firewall_interfaces.py.preview
deleted file mode 100644
index d9085a6..0000000
--- a/plugins/modules/vyos_firewall_interfaces.py.preview
+++ /dev/null
@@ -1,244 +0,0 @@
-#!/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_firewall_interfaces
-short_description: Firewall interfaces resource module via REST API.
-description:
- - Attaches or detaches named firewall rule sets to/from interface
- directions (in/out/local) using the VyOS HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of interface firewall attachment configurations.
- type: list
- elements: dict
- suboptions:
- name:
- description: Interface name.
- type: str
- required: true
- access_rules:
- description: Firewall rule sets per AFI.
- type: list
- elements: dict
- suboptions:
- afi:
- description: Address family.
- type: str
- choices: [ipv4, ipv6]
- required: true
- rules:
- description: Rule sets and directions.
- type: list
- elements: dict
- suboptions:
- name:
- description: Rule set name.
- type: str
- direction:
- description: Traffic direction.
- type: str
- choices: [in, local, out]
- required: true
- state:
- description: Desired state.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: list
-after:
- returned: when changed
- type: list
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_IFACE_TYPES = {
- "eth": "ethernet",
- "bond": "bonding",
- "vti": "vti",
- "vxlan": "vxlan",
- "lo": "loopback",
- "dummy": "dummy",
- "br": "bridge",
- "wg": "wireguard",
- "tun": "tunnel",
-}
-
-
-def _itype(name):
- for p, t in _IFACE_TYPES.items():
- if name.startswith(p):
- return t
- return "ethernet"
-
-
-def _fw_direction_key(afi, direction):
- if afi == "ipv4":
- return {"in": "in", "out": "out", "local": "local"}[direction]
- return {"in": "in", "out": "out", "local": "local"}[direction]
-
-
-def _apply(client, iface_cfg, commands):
- name = iface_cfg["name"]
- itype = _itype(name)
- ibase = ["interfaces", itype, name, "firewall"]
-
- for ar in iface_cfg.get("access_rules") or []:
- afi = ar["afi"]
- fw_key = "firewall" if afi == "ipv4" else "ipv6"
- for rule in ar.get("rules") or []:
- direction = rule["direction"]
- rs_name = rule.get("name")
- if rs_name:
- path = ibase + [direction, fw_key if afi == "ipv6" else "name"]
- client.configure_set(path, rs_name)
- commands.append(
- "set interfaces {t} {n} firewall {d} {k} '{rs}'".format(
- t=itype,
- n=name,
- d=direction,
- k="ipv6-name" if afi == "ipv6" else "name",
- rs=rs_name,
- ),
- )
-
-
-def _delete_iface_fw(client, name, commands):
- itype = _itype(name)
- path = ["interfaces", itype, name, "firewall"]
- try:
- client.configure_delete(path)
- commands.append("delete interfaces {t} {n} firewall".format(t=itype, n=name))
- except VyOSRestError:
- pass
-
-
-def _get(client):
- try:
- result = client.retrieve_show_config(["interfaces"])
- raw = result.get("data") or {}
- out = []
- for itype, itype_data in raw.items():
- if not isinstance(itype_data, dict):
- continue
- for iname, idata in itype_data.items():
- fw = idata.get("firewall") if isinstance(idata, dict) else None
- if fw:
- out.append({"name": iname, "firewall": fw})
- return out
- except VyOSRestError:
- return []
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- access_rules=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", required=True, choices=["ipv4", "ipv6"]),
- rules=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str"),
- direction=dict(
- type="str",
- required=True,
- choices=["in", "local", "out"],
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- targets = {i["name"] for i in config} if config else {i["name"] for i in before}
- for iface in before:
- if iface["name"] in targets:
- _delete_iface_fw(client, iface["name"], commands)
- changed = True
- elif state in ("merged", "replaced", "overridden"):
- if state in ("replaced", "overridden"):
- for cfg in config:
- _delete_iface_fw(client, cfg["name"], commands)
- for cfg in config:
- _apply(client, cfg, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_firewall_rules.py.preview b/plugins/modules/vyos_firewall_rules.py.preview
deleted file mode 100644
index f535f3a..0000000
--- a/plugins/modules/vyos_firewall_rules.py.preview
+++ /dev/null
@@ -1,492 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_firewall_rules
-short_description: Manage firewall rules on VyOS via the REST API.
-description:
- - Manages VyOS firewall rule sets and individual rules using the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_firewall_rules) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of firewall rule set configurations.
- type: list
- elements: dict
- suboptions:
- afi:
- description: Address family.
- type: str
- choices: [ipv4, ipv6]
- required: true
- rule_sets:
- description: List of named rule sets.
- type: list
- elements: dict
- suboptions:
- name:
- description: Rule set name.
- type: str
- required: true
- default_action:
- description: Default action for unmatched traffic.
- type: str
- choices: [drop, reject, accept]
- default: drop
- description:
- description: Rule set description.
- type: str
- rules:
- description: List of firewall rules.
- type: list
- elements: dict
- suboptions:
- number:
- description: Rule number (1-999999).
- type: int
- required: true
- action:
- description: Rule action.
- type: str
- choices: [drop, reject, accept, inspect]
- description:
- description: Rule description.
- type: str
- protocol:
- description: Protocol (e.g. C(tcp), C(udp), C(icmp), C(all)).
- type: str
- source:
- description: Source match criteria.
- type: dict
- suboptions:
- address:
- description: Source IP address or network.
- type: str
- port:
- description: Source port or port range.
- type: str
- group:
- description: Address or network group.
- type: dict
- suboptions:
- address_group:
- type: str
- network_group:
- type: str
- destination:
- description: Destination match criteria.
- type: dict
- suboptions:
- address:
- description: Destination IP address or network.
- type: str
- port:
- description: Destination port or port range.
- type: str
- group:
- description: Address or network group.
- type: dict
- suboptions:
- address_group:
- type: str
- network_group:
- type: str
- state:
- description: Connection state matching.
- type: dict
- suboptions:
- established:
- type: bool
- new:
- type: bool
- related:
- type: bool
- invalid:
- type: bool
- enabled:
- description: Whether the rule is active.
- type: bool
- default: true
- state:
- description:
- - C(merged): Add/update listed rule sets and rules.
- - C(replaced): Replace listed rule sets entirely.
- - C(overridden): Replace the entire firewall rule config.
- - C(deleted): Remove listed (or all) rule sets.
- - C(gathered): Read firewall rule config from device.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.vyos.vyos_firewall_rules
-examples: |
- - name: Create an IPv4 firewall rule set
- vyos.rest.vyos_firewall_rules:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - afi: ipv4
- rule_sets:
- - name: OUTSIDE-IN
- default_action: drop
- rules:
- - number: 10
- action: accept
- protocol: tcp
- destination:
- port: "80,443"
- state:
- established: true
- related: true
- state: merged
-
- - name: Delete all firewall rules
- vyos.rest.vyos_firewall_rules:
- hostname: 192.168.1.1
- api_key: MY-KEY
- state: deleted
-"""
-
-RETURN = r"""
-before:
- description: Firewall rule config before the module ran.
- returned: always
- type: list
-after:
- description: Firewall rule config after the module ran.
- returned: when changed
- type: list
-gathered:
- description: Firewall config read from device (state=gathered).
- returned: when state is gathered
- type: list
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_FW_PATH = {
- "ipv4": ["firewall", "name"],
- "ipv6": ["firewall", "ipv6-name"],
-}
-
-
-def _get_fw_rules(client):
- try:
- result = client.retrieve_show_config(["firewall"])
- data = result.get("data") or {}
- out = []
- for afi, key in [("ipv4", "name"), ("ipv6", "ipv6-name")]:
- sets_data = data.get(key, {})
- if not isinstance(sets_data, dict):
- continue
- rule_sets = []
- for rs_name, rs_data in sets_data.items():
- if not isinstance(rs_data, dict):
- continue
- rs = {
- "name": rs_name,
- "default_action": rs_data.get("default-action", "drop"),
- }
- if "description" in rs_data:
- rs["description"] = rs_data["description"]
- rules = []
- for rnum, rdata in (rs_data.get("rule") or {}).items():
- if not isinstance(rdata, dict):
- continue
- rule = {"number": int(rnum)}
- if "action" in rdata:
- rule["action"] = rdata["action"]
- if "description" in rdata:
- rule["description"] = rdata["description"]
- if "protocol" in rdata:
- rule["protocol"] = rdata["protocol"]
- rule["enabled"] = "disable" not in rdata
- rules.append(rule)
- if rules:
- rs["rules"] = sorted(rules, key=lambda r: r["number"])
- rule_sets.append(rs)
- if rule_sets:
- out.append({"afi": afi, "rule_sets": rule_sets})
- return out
- except VyOSRestError:
- return []
-
-
-def _apply_rule_set(client, afi, rs, commands):
- base = _FW_PATH[afi] + [rs["name"]]
- client.configure_set(base)
- commands.append("set {p}".format(p=" ".join(base)))
-
- if rs.get("default_action"):
- client.configure_set(base + ["default-action"], rs["default_action"])
- commands.append(
- "set {p} default-action {a}".format(
- p=" ".join(base),
- a=rs["default_action"],
- ),
- )
- if rs.get("description"):
- client.configure_set(base + ["description"], rs["description"])
- commands.append(
- "set {p} description '{d}'".format(
- p=" ".join(base),
- d=rs["description"],
- ),
- )
-
- for rule in rs.get("rules") or []:
- rbase = base + ["rule", str(rule["number"])]
- client.configure_set(rbase)
- commands.append("set {p}".format(p=" ".join(rbase)))
-
- if rule.get("action"):
- client.configure_set(rbase + ["action"], rule["action"])
- commands.append(
- "set {p} action {a}".format(p=" ".join(rbase), a=rule["action"]),
- )
- if rule.get("description"):
- client.configure_set(rbase + ["description"], rule["description"])
- if rule.get("protocol"):
- client.configure_set(rbase + ["protocol"], rule["protocol"])
- commands.append(
- "set {p} protocol {pr}".format(
- p=" ".join(rbase),
- pr=rule["protocol"],
- ),
- )
- for direction in ("source", "destination"):
- match = rule.get(direction)
- if not match:
- continue
- mbase = rbase + [direction]
- if match.get("address"):
- client.configure_set(mbase + ["address"], match["address"])
- commands.append(
- "set {p} address '{a}'".format(
- p=" ".join(mbase),
- a=match["address"],
- ),
- )
- if match.get("port"):
- client.configure_set(mbase + ["port"], match["port"])
- commands.append(
- "set {p} port {pt}".format(
- p=" ".join(mbase),
- pt=match["port"],
- ),
- )
-
- state_match = rule.get("state")
- if state_match:
- sbase = rbase + ["state"]
- for st_name in ("established", "new", "related", "invalid"):
- if state_match.get(st_name):
- client.configure_set(sbase + [st_name], "enable")
- commands.append(
- "set {p} {s} enable".format(
- p=" ".join(sbase),
- s=st_name,
- ),
- )
-
- if "enabled" in rule and not rule["enabled"]:
- client.configure_set(rbase + ["disable"])
- commands.append("set {p} disable".format(p=" ".join(rbase)))
-
-
-def main():
- rule_spec = dict(
- number=dict(type="int", required=True),
- action=dict(type="str", choices=["drop", "reject", "accept", "inspect"]),
- description=dict(type="str"),
- protocol=dict(type="str"),
- source=dict(
- type="dict",
- options=dict(
- address=dict(type="str"),
- port=dict(type="str"),
- group=dict(
- type="dict",
- options=dict(
- address_group=dict(type="str"),
- network_group=dict(type="str"),
- ),
- ),
- ),
- ),
- destination=dict(
- type="dict",
- options=dict(
- address=dict(type="str"),
- port=dict(type="str"),
- group=dict(
- type="dict",
- options=dict(
- address_group=dict(type="str"),
- network_group=dict(type="str"),
- ),
- ),
- ),
- ),
- state=dict(
- type="dict",
- options=dict(
- established=dict(type="bool"),
- new=dict(type="bool"),
- related=dict(type="bool"),
- invalid=dict(type="bool"),
- ),
- ),
- enabled=dict(type="bool", default=True),
- )
-
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", required=True, choices=["ipv4", "ipv6"]),
- rule_sets=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- default_action=dict(
- type="str",
- choices=["drop", "reject", "accept"],
- default="drop",
- ),
- description=dict(type="str"),
- rules=dict(type="list", elements="dict", options=rule_spec),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
-
- before = _get_fw_rules(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
-
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state in ("deleted", "overridden") and not config:
- for afi_key in ("name", "ipv6-name"):
- try:
- client.configure_delete(["firewall", afi_key])
- commands.append(
- "delete firewall {k}".format(k=afi_key),
- )
- except VyOSRestError:
- pass
- changed = True
-
- elif state == "deleted" and config:
- for entry in config:
- afi = entry["afi"]
- base_path = _FW_PATH[afi]
- for rs in entry.get("rule_sets") or []:
- try:
- client.configure_delete(base_path + [rs["name"]])
- commands.append(
- "delete {p} {n}".format(
- p=" ".join(base_path),
- n=rs["name"],
- ),
- )
- changed = True
- except VyOSRestError:
- pass
-
- elif state in ("merged", "replaced", "overridden"):
- if state == "replaced":
- for entry in config:
- afi = entry["afi"]
- base_path = _FW_PATH[afi]
- for rs in entry.get("rule_sets") or []:
- try:
- client.configure_delete(base_path + [rs["name"]])
- commands.append(
- "delete {p} {n}".format(
- p=" ".join(base_path),
- n=rs["name"],
- ),
- )
- except VyOSRestError:
- pass
- for entry in config:
- afi = entry["afi"]
- for rs in entry.get("rule_sets") or []:
- _apply_rule_set(client, afi, rs, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get_fw_rules(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_generate.py.preview b/plugins/modules/vyos_generate.py.preview
deleted file mode 100644
index 448575a..0000000
--- a/plugins/modules/vyos_generate.py.preview
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_generate
-short_description: Execute generate commands on a VyOS device via REST API.
-description:
- - Sends a C(generate) operational command to a VyOS device via the HTTPS
- REST API (C(/generate) endpoint).
- - Commonly used to generate WireGuard keypairs, TLS certificates, etc.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- path:
- description:
- - Generate command tokens.
- - E.g. C(["wireguard", "default-keypair"]).
- type: list
- elements: str
- required: true
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-examples: |
- - name: Generate WireGuard default keypair
- vyos.rest.vyos_generate:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["wireguard", "default-keypair"]
-
- - name: Generate a new SSH host key
- vyos.rest.vyos_generate:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["ssh-server", "host-key", "rsa"]
-"""
-
-RETURN = r"""
-output:
- description: Text output produced by the generate command (may be empty).
- returned: success
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def main():
- argument_spec = dict(
- path=dict(type="list", elements="str", required=True),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=False,
- )
-
- client = VyOSRestClient(module)
- try:
- result = client.generate(module.params["path"])
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=True, output=result.get("data", ""))
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_image.py.preview b/plugins/modules/vyos_image.py.preview
deleted file mode 100644
index be12705..0000000
--- a/plugins/modules/vyos_image.py.preview
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_image
-short_description: Manage VyOS system images via the REST API.
-description:
- - Adds or removes VyOS system images using the HTTPS REST API
- (C(/image) endpoint).
- - Use I(state=present) to download and install an image from a URL.
- - Use I(state=absent) to delete an installed image by name.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- state:
- description:
- - C(present): Download and install the image from I(url).
- - C(absent): Delete the image specified by I(name).
- type: str
- choices: [present, absent]
- required: true
- url:
- description:
- - HTTP(S) URL of the VyOS C(.iso) file to install.
- - Required when I(state=present).
- type: str
- name:
- description:
- - Version name of the image to remove (e.g. C(1.4-rolling-202401010000)).
- - Required when I(state=absent).
- type: str
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: >
- Request timeout in seconds. Image downloads can take several minutes;
- increase this value accordingly.
- type: int
- default: 300
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-examples: |
- - name: Install the latest rolling release
- vyos.rest.vyos_image:
- hostname: 192.168.1.1
- api_key: MY-KEY
- state: present
- url: "https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso"
- timeout: 600
-
- - name: Remove an old image
- vyos.rest.vyos_image:
- hostname: 192.168.1.1
- api_key: MY-KEY
- state: absent
- name: "1.4-rolling-202312010000"
-"""
-
-RETURN = r"""
-output:
- description: Text output from the image add/delete operation.
- returned: success
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def main():
- argument_spec = dict(
- state=dict(type="str", required=True, choices=["present", "absent"]),
- url=dict(type="str"),
- name=dict(type="str"),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- # Override default timeout to 300s for image downloads
- argument_spec["timeout"]["default"] = 300
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[
- ("state", "present", ["url"]),
- ("state", "absent", ["name"]),
- ],
- supports_check_mode=False,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
-
- try:
- if state == "present":
- result = client.image_add(module.params["url"])
- else:
- result = client.image_delete(module.params["name"])
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=True, output=result.get("data", ""))
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_interfaces.py.preview b/plugins/modules/vyos_interfaces.py.preview
deleted file mode 100644
index 9edc1da..0000000
--- a/plugins/modules/vyos_interfaces.py.preview
+++ /dev/null
@@ -1,401 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_interfaces
-short_description: Manage interface attributes on a VyOS device via the REST API.
-description:
- - Manages interface base attributes (description, MTU, enabled state, VIFs,
- duplex, speed) on VyOS devices using the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_interfaces) but uses HTTP API.
- - Supports Ethernet, Bonding, VXLAN, Loopback, and Virtual Tunnel interfaces.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of interface configurations.
- type: list
- elements: dict
- suboptions:
- name:
- description: >
- Full interface name (e.g. C(eth0), C(bond0), C(vti1), C(vxlan2)).
- type: str
- required: true
- description:
- description: Interface description.
- type: str
- enabled:
- description: >
- Administrative state. C(true) = up, C(false) = admin-down.
- type: bool
- default: true
- mtu:
- description: MTU in bytes. Applicable for Ethernet, Bonding, VXLAN, VTI.
- type: int
- duplex:
- description: Duplex mode. Only for Ethernet interfaces.
- type: str
- choices: [auto, full, half]
- speed:
- description: Link speed. Only for Ethernet interfaces.
- type: str
- vifs:
- description: List of VLAN sub-interface configurations.
- type: list
- elements: dict
- suboptions:
- vlan_id:
- description: 802.1Q VLAN ID.
- type: int
- required: true
- description:
- description: VIF description.
- type: str
- enabled:
- description: Administrative state of the VIF.
- type: bool
- default: true
- state:
- description:
- - C(merged): Merge the provided config with existing interface config.
- - C(replaced): Replace per-interface config with provided values.
- - C(overridden): Override all interface config with provided values.
- - C(deleted): Delete interface config for listed interfaces (or all).
- - C(gathered): Read current interface config from device.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.vyos.vyos_interfaces
- - module: vyos.rest.vyos_l3_interfaces
-examples: |
- - name: Set description and MTU on eth1
- vyos.rest.vyos_interfaces:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - name: eth1
- description: "WAN uplink"
- mtu: 1500
- enabled: true
- state: merged
-
- - name: Disable eth2
- vyos.rest.vyos_interfaces:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - name: eth2
- enabled: false
- state: merged
-
- - name: Create a VLAN sub-interface
- vyos.rest.vyos_interfaces:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - name: eth1
- vifs:
- - vlan_id: 100
- description: "VLAN 100"
- state: merged
-"""
-
-RETURN = r"""
-before:
- description: Interface configuration before the module ran.
- returned: always
- type: list
-after:
- description: Interface configuration after the module ran.
- returned: when changed
- type: list
-gathered:
- description: Interface config read from device (state=gathered).
- returned: when state is gathered
- type: list
-commands:
- description: REST API set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_IFACE_TYPES = {
- "eth": "ethernet",
- "bond": "bonding",
- "vti": "vti",
- "vxlan": "vxlan",
- "lo": "loopback",
- "dummy": "dummy",
- "peth": "pseudo-ethernet",
- "vtun": "openvpn",
- "wg": "wireguard",
- "br": "bridge",
- "macsec": "macsec",
- "tun": "tunnel",
-}
-
-
-def _iface_type(name):
- """Infer the VyOS interface type from its name prefix."""
- for prefix, itype in _IFACE_TYPES.items():
- if name.startswith(prefix):
- return itype
- return "ethernet"
-
-
-def _iface_base_path(name):
- return ["interfaces", _iface_type(name), name]
-
-
-def _get_interfaces(client):
- try:
- result = client.retrieve_show_config(["interfaces"])
- ifaces_raw = result.get("data") or {}
- interfaces = []
- for itype, itype_data in ifaces_raw.items():
- if not isinstance(itype_data, dict):
- continue
- for iname, idata in itype_data.items():
- if not isinstance(idata, dict):
- continue
- entry = {"name": iname}
- if "description" in idata:
- entry["description"] = idata["description"]
- if "mtu" in idata:
- entry["mtu"] = int(idata["mtu"])
- entry["enabled"] = "disable" not in idata
- if "duplex" in idata:
- entry["duplex"] = idata["duplex"]
- if "speed" in idata:
- entry["speed"] = idata["speed"]
- if "vif" in idata:
- vifs = []
- for vid, vdata in idata["vif"].items():
- vif_entry = {"vlan_id": int(vid)}
- if isinstance(vdata, dict):
- if "description" in vdata:
- vif_entry["description"] = vdata["description"]
- vif_entry["enabled"] = "disable" not in vdata
- vifs.append(vif_entry)
- entry["vifs"] = vifs
- interfaces.append(entry)
- return interfaces
- except VyOSRestError:
- return []
-
-
-def _apply_interface(client, iface_cfg, commands):
- name = iface_cfg["name"]
- base = _iface_base_path(name)
-
- if iface_cfg.get("description") is not None:
- client.configure_set(base + ["description"], iface_cfg["description"])
- commands.append(
- "set interfaces {t} {n} description '{d}'".format(
- t=_iface_type(name),
- n=name,
- d=iface_cfg["description"],
- ),
- )
- if iface_cfg.get("mtu") is not None:
- client.configure_set(base + ["mtu"], str(iface_cfg["mtu"]))
- commands.append(
- "set interfaces {t} {n} mtu {m}".format(
- t=_iface_type(name),
- n=name,
- m=iface_cfg["mtu"],
- ),
- )
- if "enabled" in iface_cfg:
- if not iface_cfg["enabled"]:
- client.configure_set(base + ["disable"])
- commands.append(
- "set interfaces {t} {n} disable".format(t=_iface_type(name), n=name),
- )
- else:
- try:
- client.configure_delete(base + ["disable"])
- commands.append(
- "delete interfaces {t} {n} disable".format(
- t=_iface_type(name),
- n=name,
- ),
- )
- except VyOSRestError:
- pass
- if iface_cfg.get("duplex"):
- client.configure_set(base + ["duplex"], iface_cfg["duplex"])
- commands.append(
- "set interfaces {t} {n} duplex {d}".format(
- t=_iface_type(name),
- n=name,
- d=iface_cfg["duplex"],
- ),
- )
- if iface_cfg.get("speed"):
- client.configure_set(base + ["speed"], iface_cfg["speed"])
- commands.append(
- "set interfaces {t} {n} speed {s}".format(
- t=_iface_type(name),
- n=name,
- s=iface_cfg["speed"],
- ),
- )
- for vif in iface_cfg.get("vifs") or []:
- vid = str(vif["vlan_id"])
- vif_base = base + ["vif", vid]
- client.configure_set(vif_base)
- commands.append(
- "set interfaces {t} {n} vif {v}".format(
- t=_iface_type(name),
- n=name,
- v=vid,
- ),
- )
- if vif.get("description"):
- client.configure_set(vif_base + ["description"], vif["description"])
- commands.append(
- "set interfaces {t} {n} vif {v} description '{d}'".format(
- t=_iface_type(name),
- n=name,
- v=vid,
- d=vif["description"],
- ),
- )
- if "enabled" in vif and not vif["enabled"]:
- client.configure_set(vif_base + ["disable"])
- commands.append(
- "set interfaces {t} {n} vif {v} disable".format(
- t=_iface_type(name),
- n=name,
- v=vid,
- ),
- )
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- description=dict(type="str"),
- enabled=dict(type="bool", default=True),
- mtu=dict(type="int"),
- duplex=dict(type="str", choices=["auto", "full", "half"]),
- speed=dict(type="str"),
- vifs=dict(
- type="list",
- elements="dict",
- options=dict(
- vlan_id=dict(type="int", required=True),
- description=dict(type="str"),
- enabled=dict(type="bool", default=True),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
-
- before = _get_interfaces(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
-
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- targets = {i["name"] for i in config} if config else {i["name"] for i in before}
- for iface in before:
- if iface["name"] in targets:
- base = _iface_base_path(iface["name"])
- # Only delete mutable attributes, not the interface itself
- for attr in ["description", "mtu", "duplex", "speed"]:
- if attr in iface:
- try:
- client.configure_delete(base + [attr])
- commands.append(
- "delete interfaces {t} {n} {a}".format(
- t=_iface_type(iface["name"]),
- n=iface["name"],
- a=attr,
- ),
- )
- except VyOSRestError:
- pass
- changed = True
-
- elif state in ("merged", "replaced", "overridden"):
- for iface_cfg in config:
- _apply_interface(client, iface_cfg, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get_interfaces(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_l3_interfaces.py.preview b/plugins/modules/vyos_l3_interfaces.py.preview
deleted file mode 100644
index f6d4e6c..0000000
--- a/plugins/modules/vyos_l3_interfaces.py.preview
+++ /dev/null
@@ -1,381 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_l3_interfaces
-short_description: Manage L3 interface attributes on VyOS via the REST API.
-description:
- - Manages IPv4 and IPv6 addresses on VyOS interfaces via the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_l3_interfaces) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of L3 interface configurations.
- type: list
- elements: dict
- suboptions:
- name:
- description: Full interface name (e.g. C(eth0), C(eth1)).
- type: str
- required: true
- ipv4:
- description: List of IPv4 address assignments.
- type: list
- elements: dict
- suboptions:
- address:
- description: IPv4 address in CIDR notation or C(dhcp).
- type: str
- required: true
- ipv6:
- description: List of IPv6 address assignments.
- type: list
- elements: dict
- suboptions:
- address:
- description: IPv6 address in CIDR notation or C(dhcpv6) or C(autoconf).
- type: str
- required: true
- vifs:
- description: VLAN sub-interface L3 settings.
- type: list
- elements: dict
- suboptions:
- vlan_id:
- description: 802.1Q VLAN ID.
- type: int
- required: true
- ipv4:
- description: IPv4 addresses for this VIF.
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- required: true
- ipv6:
- description: IPv6 addresses for this VIF.
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- required: true
- state:
- description:
- - C(merged): Add addresses to the interface (preserve existing).
- - C(replaced): Replace all addresses on each listed interface.
- - C(overridden): Replace all addresses on all interfaces.
- - C(deleted): Remove all addresses from listed (or all) interfaces.
- - C(gathered): Read L3 config from device without changes.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.vyos.vyos_l3_interfaces
- - module: vyos.rest.vyos_interfaces
-examples: |
- - name: Assign addresses to eth1 and eth2
- vyos.rest.vyos_l3_interfaces:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - name: eth1
- ipv4:
- - address: 10.0.1.1/24
- ipv6:
- - address: "2001:db8::1/64"
- - name: eth2
- ipv4:
- - address: dhcp
- state: merged
-
- - name: Remove all addresses from eth1
- vyos.rest.vyos_l3_interfaces:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - name: eth1
- state: deleted
-"""
-
-RETURN = r"""
-before:
- description: L3 interface config before the module ran.
- returned: always
- type: list
-after:
- description: L3 interface config after the module ran.
- returned: when changed
- type: list
-gathered:
- description: L3 config read from device (state=gathered).
- returned: when state is gathered
- type: list
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_IFACE_TYPES = {
- "eth": "ethernet",
- "bond": "bonding",
- "vti": "vti",
- "vxlan": "vxlan",
- "lo": "loopback",
- "dummy": "dummy",
- "br": "bridge",
- "wg": "wireguard",
- "tun": "tunnel",
-}
-
-
-def _iface_type(name):
- for prefix, t in _IFACE_TYPES.items():
- if name.startswith(prefix):
- return t
- return "ethernet"
-
-
-def _base(name):
- return ["interfaces", _iface_type(name), name]
-
-
-def _get_l3_interfaces(client):
- try:
- result = client.retrieve_show_config(["interfaces"])
- raw = result.get("data") or {}
- out = []
- for itype, itype_data in raw.items():
- if not isinstance(itype_data, dict):
- continue
- for iname, idata in itype_data.items():
- if not isinstance(idata, dict):
- continue
- entry = {"name": iname, "ipv4": [], "ipv6": []}
- for addr in _listify(idata.get("address")):
- if ":" in addr:
- entry["ipv6"].append({"address": addr})
- elif addr == "dhcp":
- entry["ipv4"].append({"address": addr})
- else:
- entry["ipv4"].append({"address": addr})
- # VIFs
- if "vif" in idata:
- vifs = []
- for vid, vdata in idata["vif"].items():
- vif_e = {"vlan_id": int(vid), "ipv4": [], "ipv6": []}
- if isinstance(vdata, dict):
- for addr in _listify(vdata.get("address")):
- if ":" in addr:
- vif_e["ipv6"].append({"address": addr})
- else:
- vif_e["ipv4"].append({"address": addr})
- vifs.append(vif_e)
- entry["vifs"] = vifs
- if entry["ipv4"] or entry["ipv6"] or entry.get("vifs"):
- out.append(entry)
- return out
- except VyOSRestError:
- return []
-
-
-def _listify(val):
- """Return val as a list regardless of whether it's a str or list."""
- if val is None:
- return []
- if isinstance(val, list):
- return val
- return [val]
-
-
-def _set_addresses(client, name, ipv4, ipv6, commands):
- base = _base(name)
- itype = _iface_type(name)
- for a in ipv4 or []:
- client.configure_set(base + ["address"], a["address"])
- commands.append(
- "set interfaces {t} {n} address '{a}'".format(
- t=itype,
- n=name,
- a=a["address"],
- ),
- )
- for a in ipv6 or []:
- client.configure_set(base + ["address"], a["address"])
- commands.append(
- "set interfaces {t} {n} address '{a}'".format(
- t=itype,
- n=name,
- a=a["address"],
- ),
- )
-
-
-def _delete_addresses(client, name, commands):
- base = _base(name)
- itype = _iface_type(name)
- try:
- client.configure_delete(base + ["address"])
- commands.append(
- "delete interfaces {t} {n} address".format(t=itype, n=name),
- )
- except VyOSRestError:
- pass
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- ipv4=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str", required=True)),
- ),
- ipv6=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str", required=True)),
- ),
- vifs=dict(
- type="list",
- elements="dict",
- options=dict(
- vlan_id=dict(type="int", required=True),
- ipv4=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str", required=True)),
- ),
- ipv6=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str", required=True)),
- ),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
-
- before = _get_l3_interfaces(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
-
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- targets = {i["name"] for i in config} if config else {i["name"] for i in before}
- for iface in before:
- if iface["name"] in targets:
- _delete_addresses(client, iface["name"], commands)
- changed = True
-
- elif state in ("merged", "replaced", "overridden"):
- if state in ("replaced", "overridden"):
- # First remove existing addresses on targeted interfaces
- targets = {i["name"] for i in config}
- if state == "overridden":
- targets = {i["name"] for i in before}
- for iface in before:
- if iface["name"] in targets:
- _delete_addresses(client, iface["name"], commands)
-
- for iface_cfg in config:
- name = iface_cfg["name"]
- _set_addresses(
- client,
- name,
- iface_cfg.get("ipv4"),
- iface_cfg.get("ipv6"),
- commands,
- )
- for vif in iface_cfg.get("vifs") or []:
- vid = str(vif["vlan_id"])
- base = _base(name) + ["vif", vid]
- itype = _iface_type(name)
- for a in (vif.get("ipv4") or []) + (vif.get("ipv6") or []):
- client.configure_set(base + ["address"], a["address"])
- commands.append(
- "set interfaces {t} {n} vif {v} address '{a}'".format(
- t=itype,
- n=name,
- v=vid,
- a=a["address"],
- ),
- )
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get_l3_interfaces(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_lag_interfaces.py.preview b/plugins/modules/vyos_lag_interfaces.py.preview
deleted file mode 100644
index 15fe1f3..0000000
--- a/plugins/modules/vyos_lag_interfaces.py.preview
+++ /dev/null
@@ -1,228 +0,0 @@
-#!/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_lag_interfaces
-short_description: LAG/bonding interfaces resource module via REST API.
-description:
- - Manages Link Aggregation Group (LAG/bond) interfaces on VyOS via REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of LAG interface configurations.
- type: list
- elements: dict
- suboptions:
- name:
- description: Bond interface name (e.g. bond0).
- type: str
- required: true
- mode:
- description: Bonding mode.
- type: str
- choices: [802.3ad, active-backup, broadcast, round-robin,
- transmit-load-balance, adaptive-load-balance, xor-hash]
- members:
- description: Member interfaces.
- type: list
- elements: dict
- suboptions:
- member:
- description: Interface name.
- type: str
- primary:
- description: Primary interface name.
- type: str
- hash_policy:
- description: Transmit hash policy.
- type: str
- choices: [layer2, layer2+3, layer3+4]
- arp_monitor:
- description: ARP monitoring settings.
- type: dict
- suboptions:
- interval:
- description: Monitoring interval in ms.
- type: int
- target:
- description: Target IP addresses.
- type: list
- elements: str
- state:
- description: Desired state.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: list
-after:
- returned: when changed
- type: list
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_MODE_MAP = {
- "802.3ad": "802.3ad",
- "active-backup": "active-backup",
- "broadcast": "broadcast",
- "round-robin": "round-robin",
- "transmit-load-balance": "transmit-load-balance",
- "adaptive-load-balance": "adaptive-load-balance",
- "xor-hash": "xor-hash",
-}
-
-
-def _get(client):
- try:
- r = client.retrieve_show_config(["interfaces", "bonding"])
- data = r.get("data") or {}
- out = []
- for bname, bdata in data.items():
- entry = {"name": bname}
- if isinstance(bdata, dict):
- if "mode" in bdata:
- entry["mode"] = bdata["mode"]
- if "primary" in bdata:
- entry["primary"] = bdata["primary"]
- if "hash-policy" in bdata:
- entry["hash_policy"] = bdata["hash-policy"]
- members = []
- for m in (
- bdata.get("member", {}).keys() if isinstance(bdata.get("member"), dict) else []
- ):
- members.append({"member": m})
- if members:
- entry["members"] = members
- out.append(entry)
- return out
- except VyOSRestError:
- return []
-
-
-def _apply(client, cfg, commands):
- name = cfg["name"]
- base = ["interfaces", "bonding", name]
- client.configure_set(base)
- commands.append("set interfaces bonding {n}".format(n=name))
-
- if cfg.get("mode"):
- client.configure_set(base + ["mode"], cfg["mode"])
- commands.append("set interfaces bonding {n} mode {m}".format(n=name, m=cfg["mode"]))
- if cfg.get("primary"):
- client.configure_set(base + ["primary"], cfg["primary"])
- if cfg.get("hash_policy"):
- client.configure_set(base + ["hash-policy"], cfg["hash_policy"])
- for m in cfg.get("members") or []:
- client.configure_set(["interfaces", "ethernet", m["member"], "bond-group"], name)
- commands.append("set interfaces ethernet {m} bond-group {n}".format(m=m["member"], n=name))
- arp = cfg.get("arp_monitor") or {}
- if arp.get("interval"):
- client.configure_set(base + ["arp-monitor", "interval"], str(arp["interval"]))
- for t in arp.get("target") or []:
- client.configure_set(base + ["arp-monitor", "target"], t)
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- mode=dict(type="str", choices=list(_MODE_MAP.keys())),
- members=dict(
- type="list",
- elements="dict",
- options=dict(member=dict(type="str")),
- ),
- primary=dict(type="str"),
- hash_policy=dict(type="str", choices=["layer2", "layer2+3", "layer3+4"]),
- arp_monitor=dict(
- type="dict",
- options=dict(
- interval=dict(type="int"),
- target=dict(type="list", elements="str"),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- targets = {i["name"] for i in config} if config else {i["name"] for i in before}
- for b in before:
- if b["name"] in targets:
- client.configure_delete(["interfaces", "bonding", b["name"]])
- commands.append("delete interfaces bonding {n}".format(n=b["name"]))
- changed = True
- elif state in ("merged", "replaced", "overridden"):
- for cfg in config:
- _apply(client, cfg, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_lldp_interfaces.py.preview b/plugins/modules/vyos_lldp_interfaces.py.preview
deleted file mode 100644
index 4f012aa..0000000
--- a/plugins/modules/vyos_lldp_interfaces.py.preview
+++ /dev/null
@@ -1,227 +0,0 @@
-#!/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_lldp_interfaces
-short_description: LLDP interfaces resource module via REST API.
-description:
- - Manages per-interface LLDP settings (enable/disable, location) on VyOS
- via the HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of LLDP interface configurations.
- type: list
- elements: dict
- suboptions:
- name:
- description: Interface name.
- type: str
- required: true
- enable:
- description: Enable LLDP on this interface (default true).
- type: bool
- default: true
- location:
- description: LLDP-MED location data.
- type: dict
- suboptions:
- coordinate_based:
- type: dict
- suboptions:
- altitude:
- type: int
- datum:
- type: str
- choices: [WGS84, NAD83, MLLW]
- latitude:
- type: str
- required: true
- longitude:
- type: str
- required: true
- elin:
- description: Emergency ELIN number (10-25 digits).
- type: str
- state:
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: list
-after:
- returned: when changed
- type: list
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_IFACE_TYPES = {
- "eth": "ethernet",
- "bond": "bonding",
- "lo": "loopback",
- "dummy": "dummy",
- "br": "bridge",
-}
-
-
-def _itype(name):
- for p, t in _IFACE_TYPES.items():
- if name.startswith(p):
- return t
- return "ethernet"
-
-
-def _get(client):
- try:
- r = client.retrieve_show_config(["service", "lldp", "interface"])
- data = r.get("data") or {}
- out = []
- for iname, idata in data.items():
- entry = {"name": iname}
- if isinstance(idata, dict):
- entry["enable"] = "disable" not in idata
- out.append(entry)
- return out
- except VyOSRestError:
- return []
-
-
-def _apply(client, cfg, commands):
- name = cfg["name"]
- base = ["service", "lldp", "interface", name]
- client.configure_set(base)
- commands.append("set service lldp interface {n}".format(n=name))
-
- if "enable" in cfg and not cfg["enable"]:
- client.configure_set(base + ["disable"])
- commands.append("set service lldp interface {n} disable".format(n=name))
-
- loc = cfg.get("location") or {}
- coord = loc.get("coordinate_based") or {}
- if coord:
- lbase = base + ["location", "coordinate-based"]
- if coord.get("latitude"):
- client.configure_set(lbase + ["latitude"], coord["latitude"])
- if coord.get("longitude"):
- client.configure_set(lbase + ["longitude"], coord["longitude"])
- if coord.get("altitude"):
- client.configure_set(lbase + ["altitude"], str(coord["altitude"]))
- if coord.get("datum"):
- client.configure_set(lbase + ["datum"], coord["datum"])
- commands.append(
- "set service lldp interface {n} location coordinate-based ...".format(n=name),
- )
- if loc.get("elin"):
- client.configure_set(base + ["location", "elin"], loc["elin"])
- commands.append(
- "set service lldp interface {n} location elin {e}".format(n=name, e=loc["elin"]),
- )
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- enable=dict(type="bool", default=True),
- location=dict(
- type="dict",
- options=dict(
- coordinate_based=dict(
- type="dict",
- options=dict(
- altitude=dict(type="int"),
- datum=dict(type="str", choices=["WGS84", "NAD83", "MLLW"]),
- latitude=dict(type="str", required=True),
- longitude=dict(type="str", required=True),
- ),
- ),
- elin=dict(type="str"),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- for cfg in config if config else before:
- name = cfg["name"] if isinstance(cfg, dict) else cfg
- try:
- client.configure_delete(["service", "lldp", "interface", name])
- commands.append("delete service lldp interface {n}".format(n=name))
- changed = True
- except VyOSRestError:
- pass
- elif state in ("merged", "replaced", "overridden"):
- for cfg in config:
- _apply(client, cfg, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_ospf_interfaces.py.preview b/plugins/modules/vyos_ospf_interfaces.py.preview
deleted file mode 100644
index 37876d4..0000000
--- a/plugins/modules/vyos_ospf_interfaces.py.preview
+++ /dev/null
@@ -1,290 +0,0 @@
-#!/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_ospf_interfaces
-short_description: OSPF Interfaces Resource Module via REST API.
-description:
- - Manages per-interface OSPF parameters (cost, hello/dead timers, authentication,
- passive mode, etc.) for both OSPFv2 and OSPFv3 via the VyOS HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of OSPF interface configurations.
- type: list
- elements: dict
- suboptions:
- name:
- description: Interface name.
- type: str
- address_family:
- description: OSPF settings per address family.
- type: list
- elements: dict
- suboptions:
- afi:
- description: Address family (ipv4=OSPFv2, ipv6=OSPFv3).
- type: str
- choices: [ipv4, ipv6]
- required: true
- authentication:
- type: dict
- suboptions:
- plaintext_password:
- type: str
- md5_key:
- type: dict
- suboptions:
- key_id:
- type: int
- key:
- type: str
- bandwidth:
- type: int
- cost:
- type: int
- dead_interval:
- type: int
- hello_interval:
- type: int
- mtu_ignore:
- type: bool
- network:
- type: str
- priority:
- type: int
- retransmit_interval:
- type: int
- transmit_delay:
- type: int
- ifmtu:
- type: int
- instance:
- type: str
- passive:
- type: bool
- state:
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: list
-after:
- returned: when changed
- type: list
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_IFACE_TYPES = {
- "eth": "ethernet",
- "bond": "bonding",
- "lo": "loopback",
- "dummy": "dummy",
- "br": "bridge",
- "wg": "wireguard",
- "tun": "tunnel",
- "vxlan": "vxlan",
-}
-
-
-def _itype(name):
- for p, t in _IFACE_TYPES.items():
- if name.startswith(p):
- return t
- return "ethernet"
-
-
-def _ospf_iface_base(name, afi):
- itype = _itype(name)
- if afi == "ipv4":
- return ["interfaces", itype, name, "ip", "ospf"]
- return ["interfaces", itype, name, "ipv6", "ospfv3"]
-
-
-def _apply(client, cfg, commands):
- name = cfg["name"]
- for af in cfg.get("address_family") or []:
- afi = af["afi"]
- base = _ospf_iface_base(name, afi)
-
- int_map = {
- "cost": "cost",
- "bandwidth": "bandwidth",
- "dead_interval": "dead-interval",
- "hello_interval": "hello-interval",
- "priority": "priority",
- "retransmit_interval": "retransmit-interval",
- "transmit_delay": "transmit-delay",
- "ifmtu": "ifmtu",
- }
- for param, key in int_map.items():
- if af.get(param) is not None:
- client.configure_set(base + [key], str(af[param]))
- commands.append("set {b} {k} {v}".format(b=" ".join(base), k=key, v=af[param]))
-
- if af.get("mtu_ignore"):
- client.configure_set(base + ["mtu-ignore"])
- commands.append("set {b} mtu-ignore".format(b=" ".join(base)))
- if af.get("passive"):
- client.configure_set(base + ["passive"])
- commands.append("set {b} passive".format(b=" ".join(base)))
- if af.get("network"):
- client.configure_set(base + ["network"], af["network"])
- if af.get("instance"):
- client.configure_set(base + ["instance-id"], af["instance"])
-
- auth = af.get("authentication") or {}
- if auth.get("plaintext_password"):
- client.configure_set(
- base + ["authentication", "plaintext-password"],
- auth["plaintext_password"],
- )
- commands.append(
- "set {b} authentication plaintext-password ...".format(b=" ".join(base)),
- )
- md5 = auth.get("md5_key") or {}
- if md5.get("key_id") and md5.get("key"):
- client.configure_set(
- base + ["authentication", "md5", "key-id", str(md5["key_id"]), "md5-key"],
- md5["key"],
- )
-
-
-def _get(client):
- try:
- r = client.retrieve_show_config(["interfaces"])
- raw = r.get("data") or {}
- out = []
- for itype, itype_data in raw.items():
- if not isinstance(itype_data, dict):
- continue
- for iname, idata in itype_data.items():
- if not isinstance(idata, dict):
- continue
- afs = []
- ip_ospf = (idata.get("ip") or {}).get("ospf")
- if ip_ospf:
- afs.append({"afi": "ipv4", "ospf_data": ip_ospf})
- ip6_ospfv3 = (idata.get("ipv6") or {}).get("ospfv3")
- if ip6_ospfv3:
- afs.append({"afi": "ipv6", "ospfv3_data": ip6_ospfv3})
- if afs:
- out.append({"name": iname, "address_family": afs})
- return out
- except VyOSRestError:
- return []
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str"),
- address_family=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", required=True, choices=["ipv4", "ipv6"]),
- authentication=dict(
- type="dict",
- options=dict(
- plaintext_password=dict(type="str", no_log=True),
- md5_key=dict(
- type="dict",
- options=dict(
- key_id=dict(type="int"),
- key=dict(type="str", no_log=True),
- ),
- ),
- ),
- ),
- bandwidth=dict(type="int"),
- cost=dict(type="int"),
- dead_interval=dict(type="int"),
- hello_interval=dict(type="int"),
- mtu_ignore=dict(type="bool"),
- network=dict(type="str"),
- priority=dict(type="int"),
- retransmit_interval=dict(type="int"),
- transmit_delay=dict(type="int"),
- ifmtu=dict(type="int"),
- instance=dict(type="str"),
- passive=dict(type="bool"),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- for cfg in config:
- _apply(client, cfg, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_ospfv2.py.preview b/plugins/modules/vyos_ospfv2.py.preview
deleted file mode 100644
index 063d0dc..0000000
--- a/plugins/modules/vyos_ospfv2.py.preview
+++ /dev/null
@@ -1,487 +0,0 @@
-#!/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_ospfv2
-short_description: OSPFv2 resource module via REST API.
-description:
- - Manages OSPFv2 (OSPF for IPv4) configuration on VyOS via HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: OSPFv2 configuration.
- type: dict
- suboptions:
- areas:
- type: list
- elements: dict
- suboptions:
- area_id:
- type: str
- area_type:
- type: dict
- suboptions:
- normal:
- type: bool
- nssa:
- type: dict
- suboptions:
- set:
- type: bool
- default_cost:
- type: int
- no_summary:
- type: bool
- translate:
- type: str
- choices: [always, candidate, never]
- stub:
- type: dict
- suboptions:
- set:
- type: bool
- default_cost:
- type: int
- no_summary:
- type: bool
- authentication:
- type: str
- choices: [plaintext-password, md5]
- network:
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- range:
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- cost:
- type: int
- not_advertise:
- type: bool
- substitute:
- type: str
- shortcut:
- type: str
- choices: [default, disable, enable]
- auto_cost:
- type: dict
- suboptions:
- reference_bandwidth:
- type: int
- default_information:
- type: dict
- suboptions:
- originate:
- type: dict
- suboptions:
- always:
- type: bool
- metric:
- type: int
- metric_type:
- type: int
- route_map:
- type: str
- log_adjacency_changes:
- type: str
- choices: [detail]
- max_metric:
- type: dict
- suboptions:
- router_lsa:
- type: dict
- suboptions:
- administrative:
- type: bool
- on_shutdown:
- type: int
- on_startup:
- type: int
- mpls_te:
- type: dict
- suboptions:
- enabled:
- type: bool
- router_address:
- type: str
- neighbor:
- type: list
- elements: dict
- suboptions:
- neighbor_id:
- type: str
- poll_interval:
- type: int
- priority:
- type: int
- parameters:
- type: dict
- suboptions:
- router_id:
- type: str
- opaque_lsa:
- type: bool
- rfc1583_compatibility:
- type: bool
- abr_type:
- type: str
- choices: [cisco, ibm, shortcut, standard]
- passive_interface:
- type: list
- elements: str
- redistribute:
- type: list
- elements: dict
- suboptions:
- route_type:
- type: str
- choices: [bgp, connected, kernel, rip, static]
- metric:
- type: int
- metric_type:
- type: int
- route_map:
- type: str
- state:
- type: str
- choices: [merged, replaced, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: dict
-after:
- returned: when changed
- type: dict
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_BASE = ["protocols", "ospf"]
-
-
-def _get(client):
- try:
- r = client.retrieve_show_config(_BASE)
- return r.get("data") or {}
- except VyOSRestError:
- return {}
-
-
-def _apply(client, config, commands):
- params = config.get("parameters") or {}
- if params.get("router_id"):
- client.configure_set(_BASE + ["parameters", "router-id"], params["router_id"])
- commands.append("set protocols ospf parameters router-id {r}".format(r=params["router_id"]))
- if params.get("opaque_lsa"):
- client.configure_set(_BASE + ["parameters", "opaque-lsa"])
- if params.get("rfc1583_compatibility"):
- client.configure_set(_BASE + ["parameters", "rfc1583-compatibility"])
- if params.get("abr_type"):
- client.configure_set(_BASE + ["parameters", "abr-type"], params["abr_type"])
-
- ac = config.get("auto_cost") or {}
- if ac.get("reference_bandwidth"):
- client.configure_set(
- _BASE + ["auto-cost", "reference-bandwidth"],
- str(ac["reference_bandwidth"]),
- )
- commands.append(
- "set protocols ospf auto-cost reference-bandwidth {b}".format(
- b=ac["reference_bandwidth"],
- ),
- )
-
- if config.get("log_adjacency_changes"):
- client.configure_set(_BASE + ["log-adjacency-changes", config["log_adjacency_changes"]])
-
- for nbr in config.get("neighbor") or []:
- nb = _BASE + ["neighbor", nbr["neighbor_id"]]
- client.configure_set(nb)
- if nbr.get("poll_interval"):
- client.configure_set(nb + ["poll-interval"], str(nbr["poll_interval"]))
- if nbr.get("priority"):
- client.configure_set(nb + ["priority"], str(nbr["priority"]))
-
- for pi in config.get("passive_interface") or []:
- client.configure_set(_BASE + ["passive-interface"], pi)
- commands.append("set protocols ospf passive-interface {i}".format(i=pi))
-
- for redist in config.get("redistribute") or []:
- rb = _BASE + ["redistribute", redist["route_type"]]
- client.configure_set(rb)
- commands.append("set protocols ospf redistribute {r}".format(r=redist["route_type"]))
- if redist.get("metric"):
- client.configure_set(rb + ["metric"], str(redist["metric"]))
- if redist.get("metric_type"):
- client.configure_set(rb + ["metric-type"], str(redist["metric_type"]))
- if redist.get("route_map"):
- client.configure_set(rb + ["route-map"], redist["route_map"])
-
- di = (config.get("default_information") or {}).get("originate") or {}
- if di:
- dib = _BASE + ["default-information", "originate"]
- client.configure_set(dib)
- commands.append("set protocols ospf default-information originate")
- if di.get("always"):
- client.configure_set(dib + ["always"])
- if di.get("metric"):
- client.configure_set(dib + ["metric"], str(di["metric"]))
- if di.get("metric_type"):
- client.configure_set(dib + ["metric-type"], str(di["metric_type"]))
- if di.get("route_map"):
- client.configure_set(dib + ["route-map"], di["route_map"])
-
- for area in config.get("areas") or []:
- aid = area["area_id"]
- ab = _BASE + ["area", aid]
- client.configure_set(ab)
- commands.append("set protocols ospf area {a}".format(a=aid))
-
- at = area.get("area_type") or {}
- if at.get("normal"):
- pass # default
- nssa = at.get("nssa") or {}
- if nssa.get("set"):
- client.configure_set(ab + ["area-type", "nssa"])
- if nssa.get("default_cost"):
- client.configure_set(
- ab + ["area-type", "nssa", "default-cost"],
- str(nssa["default_cost"]),
- )
- if nssa.get("no_summary"):
- client.configure_set(ab + ["area-type", "nssa", "no-summary"])
- stub = at.get("stub") or {}
- if stub.get("set"):
- client.configure_set(ab + ["area-type", "stub"])
- if stub.get("default_cost"):
- client.configure_set(
- ab + ["area-type", "stub", "default-cost"],
- str(stub["default_cost"]),
- )
-
- if area.get("authentication"):
- client.configure_set(ab + ["authentication"], area["authentication"])
-
- for net in area.get("network") or []:
- client.configure_set(ab + ["network"], net["address"])
- commands.append(
- "set protocols ospf area {a} network {n}".format(
- a=aid,
- n=net["address"],
- ),
- )
-
- for rng in area.get("range") or []:
- rb2 = ab + ["range", rng["address"]]
- client.configure_set(rb2)
- if rng.get("cost"):
- client.configure_set(rb2 + ["cost"], str(rng["cost"]))
- if rng.get("not_advertise"):
- client.configure_set(rb2 + ["not-advertise"])
- if rng.get("substitute"):
- client.configure_set(rb2 + ["substitute"], rng["substitute"])
-
- if area.get("shortcut"):
- client.configure_set(ab + ["shortcut"], area["shortcut"])
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="dict",
- options=dict(
- areas=dict(
- type="list",
- elements="dict",
- options=dict(
- area_id=dict(type="str"),
- area_type=dict(
- type="dict",
- options=dict(
- normal=dict(type="bool"),
- nssa=dict(
- type="dict",
- options=dict(
- set=dict(type="bool"),
- default_cost=dict(type="int"),
- no_summary=dict(type="bool"),
- translate=dict(
- type="str",
- choices=["always", "candidate", "never"],
- ),
- ),
- ),
- stub=dict(
- type="dict",
- options=dict(
- set=dict(type="bool"),
- default_cost=dict(type="int"),
- no_summary=dict(type="bool"),
- ),
- ),
- ),
- ),
- authentication=dict(type="str", choices=["plaintext-password", "md5"]),
- network=dict(
- type="list",
- elements="dict",
- options=dict(address=dict(type="str")),
- ),
- range=dict(
- type="list",
- elements="dict",
- options=dict(
- address=dict(type="str"),
- cost=dict(type="int"),
- not_advertise=dict(type="bool"),
- substitute=dict(type="str"),
- ),
- ),
- shortcut=dict(type="str", choices=["default", "disable", "enable"]),
- ),
- ),
- auto_cost=dict(type="dict", options=dict(reference_bandwidth=dict(type="int"))),
- default_information=dict(
- type="dict",
- options=dict(
- originate=dict(
- type="dict",
- options=dict(
- always=dict(type="bool"),
- metric=dict(type="int"),
- metric_type=dict(type="int"),
- route_map=dict(type="str"),
- ),
- ),
- ),
- ),
- log_adjacency_changes=dict(type="str", choices=["detail"]),
- max_metric=dict(type="dict"),
- mpls_te=dict(
- type="dict",
- options=dict(
- enabled=dict(type="bool"),
- router_address=dict(type="str"),
- ),
- ),
- neighbor=dict(
- type="list",
- elements="dict",
- options=dict(
- neighbor_id=dict(type="str"),
- poll_interval=dict(type="int"),
- priority=dict(type="int"),
- ),
- ),
- parameters=dict(
- type="dict",
- options=dict(
- router_id=dict(type="str"),
- opaque_lsa=dict(type="bool"),
- rfc1583_compatibility=dict(type="bool"),
- abr_type=dict(type="str", choices=["cisco", "ibm", "shortcut", "standard"]),
- ),
- ),
- passive_interface=dict(type="list", elements="str"),
- redistribute=dict(
- type="list",
- elements="dict",
- options=dict(
- route_type=dict(
- type="str",
- choices=["bgp", "connected", "kernel", "rip", "static"],
- ),
- metric=dict(type="int"),
- metric_type=dict(type="int"),
- route_map=dict(type="str"),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[("state", "merged", ["config"]), ("state", "replaced", ["config"])],
- supports_check_mode=True,
- )
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config")
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- if before:
- client.configure_delete(_BASE)
- commands.append("delete protocols ospf")
- changed = True
- elif state in ("merged", "replaced"):
- if state == "replaced" and before:
- client.configure_delete(_BASE)
- commands.append("delete protocols ospf")
- _apply(client, config, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_ospfv3.py.preview b/plugins/modules/vyos_ospfv3.py.preview
deleted file mode 100644
index 0de49d7..0000000
--- a/plugins/modules/vyos_ospfv3.py.preview
+++ /dev/null
@@ -1,257 +0,0 @@
-#!/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_ospfv3
-short_description: OSPFv3 resource module via REST API.
-description:
- - Manages OSPFv3 (OSPF for IPv6) configuration on VyOS via HTTPS REST API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: OSPFv3 configuration.
- type: dict
- suboptions:
- areas:
- type: list
- elements: dict
- suboptions:
- area_id:
- type: str
- export_list:
- type: str
- import_list:
- type: str
- interface:
- description: Interfaces in this area.
- type: list
- elements: dict
- suboptions:
- name:
- type: str
- range:
- type: list
- elements: dict
- suboptions:
- address:
- type: str
- advertise:
- type: bool
- not_advertise:
- type: bool
- parameters:
- type: dict
- suboptions:
- router_id:
- type: str
- redistribute:
- type: list
- elements: dict
- suboptions:
- route_type:
- type: str
- choices: [bgp, connected, kernel, ripng, static]
- route_map:
- type: str
- state:
- type: str
- choices: [merged, replaced, deleted, gathered]
- default: merged
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-before:
- returned: always
- type: dict
-after:
- returned: when changed
- type: dict
-commands:
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_BASE = ["protocols", "ospfv3"]
-
-
-def _get(client):
- try:
- r = client.retrieve_show_config(_BASE)
- return r.get("data") or {}
- except VyOSRestError:
- return {}
-
-
-def _apply(client, config, commands):
- params = config.get("parameters") or {}
- if params.get("router_id"):
- client.configure_set(_BASE + ["parameters", "router-id"], params["router_id"])
- commands.append(
- "set protocols ospfv3 parameters router-id {r}".format(r=params["router_id"]),
- )
-
- for redist in config.get("redistribute") or []:
- rb = _BASE + ["redistribute", redist["route_type"]]
- client.configure_set(rb)
- commands.append("set protocols ospfv3 redistribute {r}".format(r=redist["route_type"]))
- if redist.get("route_map"):
- client.configure_set(rb + ["route-map"], redist["route_map"])
-
- for area in config.get("areas") or []:
- aid = area["area_id"]
- ab = _BASE + ["area", aid]
- client.configure_set(ab)
- commands.append("set protocols ospfv3 area '{a}'".format(a=aid))
- if area.get("export_list"):
- client.configure_set(ab + ["export-list"], area["export_list"])
- commands.append(
- "set protocols ospfv3 area {a} export-list {e}".format(
- a=aid,
- e=area["export_list"],
- ),
- )
- if area.get("import_list"):
- client.configure_set(ab + ["import-list"], area["import_list"])
- for iface in area.get("interface") or []:
- client.configure_set(ab + ["interface"], iface["name"])
- commands.append(
- "set protocols ospfv3 area {a} interface {i}".format(
- a=aid,
- i=iface["name"],
- ),
- )
- for rng in area.get("range") or []:
- rb2 = ab + ["range", rng["address"]]
- client.configure_set(rb2)
- commands.append(
- "set protocols ospfv3 area {a} range {r}".format(
- a=aid,
- r=rng["address"],
- ),
- )
- if rng.get("advertise"):
- client.configure_set(rb2 + ["advertise"])
- if rng.get("not_advertise"):
- client.configure_set(rb2 + ["not-advertise"])
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="dict",
- options=dict(
- areas=dict(
- type="list",
- elements="dict",
- options=dict(
- area_id=dict(type="str"),
- export_list=dict(type="str"),
- import_list=dict(type="str"),
- interface=dict(
- type="list",
- elements="dict",
- options=dict(name=dict(type="str")),
- ),
- range=dict(
- type="list",
- elements="dict",
- options=dict(
- address=dict(type="str"),
- advertise=dict(type="bool"),
- not_advertise=dict(type="bool"),
- ),
- ),
- ),
- ),
- parameters=dict(type="dict", options=dict(router_id=dict(type="str"))),
- redistribute=dict(
- type="list",
- elements="dict",
- options=dict(
- route_type=dict(
- type="str",
- choices=["bgp", "connected", "kernel", "ripng", "static"],
- ),
- route_map=dict(type="str"),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_if=[("state", "merged", ["config"]), ("state", "replaced", ["config"])],
- supports_check_mode=True,
- )
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config")
- commands = []
- changed = False
- before = _get(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state == "deleted":
- if before:
- client.configure_delete(_BASE)
- commands.append("delete protocols ospfv3")
- changed = True
- elif state in ("merged", "replaced"):
- if state == "replaced" and before:
- client.configure_delete(_BASE)
- commands.append("delete protocols ospfv3")
- _apply(client, config, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_ping.py.preview b/plugins/modules/vyos_ping.py.preview
deleted file mode 100644
index 45368d1..0000000
--- a/plugins/modules/vyos_ping.py.preview
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/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_ping
-short_description: Test reachability using ping via VyOS REST API.
-description:
- - Sends an ICMP ping via the VyOS HTTPS REST API (/show endpoint) and
- checks reachability. Mirrors C(vyos.vyos.vyos_ping).
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- dest:
- description: Destination IP address or hostname.
- type: str
- required: true
- count:
- description: Number of packets to send.
- type: int
- default: 5
- source:
- description: Source interface or IP address.
- type: str
- ttl:
- description: Time-to-live value.
- type: int
- size:
- description: Packet size in bytes.
- type: int
- interval:
- description: Interval between pings in seconds.
- type: int
- state:
- description: C(present) = expect success; C(absent) = expect failure.
- type: str
- choices: [present, absent]
- default: present
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-commands:
- description: Ping command tokens sent to the API.
- returned: always
- type: list
-packet_loss:
- description: Packet loss percentage string.
- returned: always
- type: str
-packets_rx:
- description: Packets received.
- returned: always
- type: int
-packets_tx:
- description: Packets transmitted.
- returned: always
- type: int
-rtt:
- description: RTT statistics dict (min/avg/max/mdev).
- returned: when available
- type: dict
-"""
-
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def _build_ping_path(params):
- path = ["ping", params["dest"]]
- if params.get("count"):
- path += ["count", str(params["count"])]
- if params.get("source"):
- path += ["interface", params["source"]]
- if params.get("ttl"):
- path += ["ttl", str(params["ttl"])]
- if params.get("size"):
- path += ["size", str(params["size"])]
- return path
-
-
-def _parse_ping_output(output):
- stats = {"packet_loss": "100%", "packets_rx": 0, "packets_tx": 0}
- tx_match = re.search(r"(\d+) packets transmitted", output)
- rx_match = re.search(r"(\d+) received", output)
- loss_match = re.search(r"(\d+(?:\.\d+)?%)\s+packet loss", output)
- if tx_match:
- stats["packets_tx"] = int(tx_match.group(1))
- if rx_match:
- stats["packets_rx"] = int(rx_match.group(1))
- if loss_match:
- stats["packet_loss"] = loss_match.group(1)
- rtt_match = re.search(
- r"rtt min/avg/max/mdev = ([\d.]+)/([\d.]+)/([\d.]+)/([\d.]+)",
- output,
- )
- if rtt_match:
- stats["rtt"] = {
- "min": rtt_match.group(1),
- "avg": rtt_match.group(2),
- "max": rtt_match.group(3),
- "mdev": rtt_match.group(4),
- }
- return stats
-
-
-def main():
- argument_spec = dict(
- dest=dict(type="str", required=True),
- count=dict(type="int", default=5),
- source=dict(type="str"),
- ttl=dict(type="int"),
- size=dict(type="int"),
- interval=dict(type="int"),
- state=dict(type="str", default="present", choices=["present", "absent"]),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- if module.check_mode:
- module.exit_json(changed=False, commands=[], packet_loss="0%", packets_rx=0, packets_tx=0)
-
- client = VyOSRestClient(module)
- path = _build_ping_path(module.params)
-
- try:
- result = client.show(path)
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- output = result.get("data", "")
- stats = _parse_ping_output(output)
- reachable = stats["packets_rx"] > 0
-
- if module.params["state"] == "present" and not reachable:
- module.fail_json(
- msg="Ping to {dest} failed — no packets received.".format(dest=module.params["dest"]),
- **stats,
- )
- elif module.params["state"] == "absent" and reachable:
- module.fail_json(
- msg="Expected {dest} to be unreachable but ping succeeded.".format(
- dest=module.params["dest"],
- ),
- **stats,
- )
-
- module.exit_json(changed=False, commands=path, **stats)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_prefix_lists.py.preview b/plugins/modules/vyos_prefix_lists.py.preview
deleted file mode 100644
index 5334e7a..0000000
--- a/plugins/modules/vyos_prefix_lists.py.preview
+++ /dev/null
@@ -1,412 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-from __future__ import absolute_import, division, print_function
-
-
-__metaclass__ = type
-
-DOCUMENTATION = r"""
----
-module: vyos_prefix_lists
-short_description: Manage prefix-list configuration on VyOS devices using REST API
-description:
- - Manages IPv4 and IPv6 prefix lists on VyOS via the REST API.
- - Uses REST API (C(connection=httpapi)) instead of CLI.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-
-options:
- config:
- description: List of prefix-list configurations grouped by address family.
- type: list
- elements: dict
- suboptions:
- afi:
- description: Address family identifier.
- type: str
- choices: [ipv4, ipv6]
- required: true
- prefix_lists:
- description: Named prefix lists.
- type: list
- elements: dict
- suboptions:
- name:
- description: Prefix list name.
- type: str
- required: true
- description:
- description: Prefix list description.
- type: str
- entries:
- description: Prefix list rules.
- type: list
- elements: dict
- suboptions:
- sequence:
- description: Rule sequence number.
- type: int
- required: true
- description:
- description: Rule description.
- type: str
- action:
- description: Permit or deny.
- type: str
- choices: [permit, deny]
- ge:
- description: Minimum prefix length.
- type: int
- le:
- description: Maximum prefix length.
- type: int
- prefix:
- description: Network prefix to match.
- type: str
-
- state:
- description:
- - Desired state of the prefix-list configuration.
- - C(merged) adds or updates entries without removing existing ones.
- - C(replaced) replaces each named prefix list mentioned in config.
- - C(overridden) replaces all prefix lists for the given AFIs.
- - C(deleted) removes prefix lists. Without config removes all.
- - C(gathered) returns current configuration as structured data.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
-
-notes:
- - Requires C(ansible_connection=httpapi) with the VyOS httpapi plugin.
- - C(ansible_network_os) must be set to C(vyos.rest.vyos).
-"""
-
-EXAMPLES = r"""
-- name: Merge prefix list configuration
- vyos.rest.vyos_prefix_lists:
- config:
- - afi: ipv4
- prefix_lists:
- - name: AnsibleIPv4PrefixList
- description: PL configured by ansible
- entries:
- - sequence: 2
- action: permit
- prefix: 92.168.10.0/26
- le: 32
- - sequence: 3
- action: deny
- prefix: 72.168.2.0/24
- ge: 26
- - afi: ipv6
- prefix_lists:
- - name: AllowIPv6Prefix
- entries:
- - sequence: 5
- action: permit
- prefix: 2001:db8:8000::/35
- le: 37
- state: merged
-
-- name: Delete all prefix lists
- vyos.rest.vyos_prefix_lists:
- state: deleted
-
-- name: Gather current prefix list configuration
- vyos.rest.vyos_prefix_lists:
- state: gathered
-"""
-
-RETURN = r"""
-before:
- description: Prefix list configuration before this module ran.
- returned: always
- type: list
-
-after:
- description: Prefix list configuration after this module ran.
- returned: when changed
- type: list
-
-commands:
- description: List of API command tuples sent to the device.
- returned: always
- type: list
-
-gathered:
- description: Current prefix list configuration as structured data.
- returned: when state is gathered
- type: list
-
-saved:
- description: Whether the config was saved after changes.
- returned: when changes are applied
- type: bool
-
-response:
- description: Raw API response.
- returned: when changes are applied
- type: dict
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos import VyOSModule
-
-
-# AFI → API key mapping
-_PL_KEY = {"ipv4": "prefix-list", "ipv6": "prefix-list6"}
-
-
-# ------------------------------------------------------------
-# Parsing: API response → argspec list
-# ------------------------------------------------------------
-
-
-def get_running_config(vyos):
- """
- Fetch current prefix list config and return in argspec list format:
- [{"afi": "ipv4", "prefix_lists": [...]}, {"afi": "ipv6", ...}]
- """
- raw = vyos.get_config(["policy"])
- if not raw or not isinstance(raw, dict):
- return []
-
- result = []
- for afi, api_key in [("ipv4", "prefix-list"), ("ipv6", "prefix-list6")]:
- pl_data = raw.get(api_key) or {}
- if not isinstance(pl_data, dict):
- continue
-
- pls = []
- for pl_name, pl_info in sorted(pl_data.items()):
- entry = {"name": pl_name}
- pl_info = pl_info or {}
-
- if pl_info.get("description"):
- entry["description"] = pl_info["description"]
-
- rules = []
- for seq, rdata in sorted(
- (pl_info.get("rule") or {}).items(),
- key=lambda x: int(x[0]),
- ):
- rdata = rdata or {}
- rule = {"sequence": int(seq)}
- if rdata.get("action"):
- rule["action"] = rdata["action"]
- if rdata.get("prefix"):
- rule["prefix"] = rdata["prefix"]
- if rdata.get("ge") is not None:
- rule["ge"] = int(rdata["ge"])
- if rdata.get("le") is not None:
- rule["le"] = int(rdata["le"])
- if rdata.get("description"):
- rule["description"] = rdata["description"]
- rules.append(rule)
-
- if rules:
- entry["entries"] = rules
- pls.append(entry)
-
- if pls:
- result.append({"afi": afi, "prefix_lists": pls})
-
- return result
-
-
-# ------------------------------------------------------------
-# Internal normalization: argspec list → nested dicts for diffing
-# ------------------------------------------------------------
-
-
-def _normalize(config):
- """
- Convert argspec list to nested dict keyed by afi → pl_name → rule_seq.
- {
- "ipv4": {
- "AnsibleIPv4PrefixList": {
- "description": "...",
- "rules": {2: {...}, 3: {...}}
- }
- },
- "ipv6": {...}
- }
- """
- result = {"ipv4": {}, "ipv6": {}}
- for entry in config or []:
- afi = entry.get("afi")
- if afi not in result:
- continue
- for pl in entry.get("prefix_lists") or []:
- name = pl["name"]
- rules = {}
- for r in pl.get("entries") or []:
- seq = r["sequence"]
- rules[seq] = {k: v for k, v in r.items() if k != "sequence" and v is not None}
- result[afi][name] = {
- "description": pl.get("description"),
- "rules": rules,
- }
- return result
-
-
-# ------------------------------------------------------------
-# Command builders
-# ------------------------------------------------------------
-
-
-def _rule_cmds(base, seq, want_rule, have_rule, state):
- """Build commands for a single rule entry."""
- cmds = []
- rbase = base + ["rule", str(seq)]
-
- if seq not in (have_rule or {}):
- # New rule
- for field, api_key in [
- ("action", "action"),
- ("prefix", "prefix"),
- ("description", "description"),
- ]:
- if want_rule.get(field):
- cmds.append(("set", rbase + [api_key, want_rule[field]]))
- if want_rule.get("ge") is not None:
- cmds.append(("set", rbase + ["ge", str(want_rule["ge"])]))
- if want_rule.get("le") is not None:
- cmds.append(("set", rbase + ["le", str(want_rule["le"])]))
- else:
- # Existing rule — update changed fields
- h = have_rule[seq]
- for field, api_key in [
- ("action", "action"),
- ("prefix", "prefix"),
- ("description", "description"),
- ]:
- if want_rule.get(field) and want_rule[field] != h.get(field):
- cmds.append(("set", rbase + [api_key, want_rule[field]]))
- for field in ("ge", "le"):
- if want_rule.get(field) is not None and want_rule[field] != h.get(field):
- cmds.append(("set", rbase + [field, str(want_rule[field])]))
-
- return cmds
-
-
-def build_commands(config, have_raw, state):
- """
- Build command tuples to move from have → want.
- """
- cmds = []
-
- if state == "deleted":
- if not config:
- # Delete all prefix lists for both AFIs
- for afi, api_key in _PL_KEY.items():
- # Only delete if something exists
- if any(e.get("afi") == afi for e in have_raw):
- cmds.append(("delete", ["policy", api_key]))
- else:
- # Delete only specified prefix lists
- for entry in config:
- afi = entry["afi"]
- api_key = _PL_KEY[afi]
- for pl in entry.get("prefix_lists") or []:
- cmds.append(("delete", ["policy", api_key, pl["name"]]))
- return cmds
-
- want = _normalize(config)
- have = _normalize(have_raw)
-
- for afi, api_key in _PL_KEY.items():
- want_afi = want.get(afi, {})
- have_afi = have.get(afi, {})
-
- if state == "overridden":
- # Delete PLs present on device but not in want
- for pl_name in set(have_afi) - set(want_afi):
- cmds.append(("delete", ["policy", api_key, pl_name]))
-
- for pl_name, want_pl in want_afi.items():
- have_pl = have_afi.get(pl_name, {})
- base = ["policy", api_key, pl_name]
-
- if state == "replaced" and pl_name in have_afi:
- # Full replacement — delete existing then re-set
- cmds.append(("delete", ["policy", api_key, pl_name]))
- have_pl = {}
-
- # Description
- if want_pl.get("description") and want_pl["description"] != have_pl.get("description"):
- cmds.append(("set", base + ["description", want_pl["description"]]))
-
- # Rules
- want_rules = want_pl.get("rules", {})
- have_rules = have_pl.get("rules", {})
-
- if state == "replaced":
- # have_rules is now empty after delete above
- have_rules = {}
-
- for seq, want_rule in want_rules.items():
- cmds += _rule_cmds(base, seq, want_rule, have_rules, state)
-
- # merged: leave extra have rules alone
- # replaced: they were deleted with the parent node above
-
- return cmds
-
-
-# ------------------------------------------------------------
-# Argument spec
-# ------------------------------------------------------------
-
-ARGUMENT_SPEC = dict(
- config=dict(type="list", elements="dict"),
- state=dict(
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
-)
-
-
-# ------------------------------------------------------------
-# Main
-# ------------------------------------------------------------
-
-
-def main():
-
- module = AnsibleModule(ARGUMENT_SPEC, supports_check_mode=True)
-
- vyos = VyOSModule(module)
-
- state = module.params["state"]
- config = module.params.get("config") or []
-
- have = get_running_config(vyos)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=have)
-
- commands = build_commands(config, have, state)
-
- if module.check_mode:
- module.exit_json(changed=bool(commands), commands=commands, before=have)
-
- if commands:
- response = vyos.apply_commands(commands)
- saved = vyos.save_config()
- module.exit_json(
- changed=True,
- before=have,
- after=get_running_config(vyos),
- commands=commands,
- saved=saved,
- response=response,
- )
-
- module.exit_json(changed=False, before=have, after=have, commands=[])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_reset.py.preview b/plugins/modules/vyos_reset.py.preview
deleted file mode 100644
index ca3e343..0000000
--- a/plugins/modules/vyos_reset.py.preview
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_reset
-short_description: Execute reset commands on a VyOS device via REST API.
-description:
- - Sends a C(reset) operational command to a VyOS device via the HTTPS REST
- API (C(/reset) endpoint).
- - Useful for resetting BGP sessions, VPN tunnels, ARP caches, etc.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- path:
- description:
- - Reset command path tokens.
- - E.g. C(["ip", "bgp", "192.0.2.1"]) to reset a BGP peer.
- type: list
- elements: str
- required: true
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-examples: |
- - name: Reset a BGP peer
- vyos.rest.vyos_reset:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["ip", "bgp", "192.0.2.11"]
-
- - name: Reset an IPsec VPN peer
- vyos.rest.vyos_reset:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["vpn", "ipsec-peer", "203.0.113.5"]
-
- - name: Clear ARP cache
- vyos.rest.vyos_reset:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["arp", "cache"]
-"""
-
-RETURN = r"""
-output:
- description: Text output from the reset command (usually empty on success).
- returned: success
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def main():
- argument_spec = dict(
- path=dict(type="list", elements="str", required=True),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=False,
- )
-
- client = VyOSRestClient(module)
- try:
- result = client.reset(module.params["path"])
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=True, output=result.get("data", ""))
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_show.py.preview b/plugins/modules/vyos_show.py.preview
deleted file mode 100644
index fbe6c1b..0000000
--- a/plugins/modules/vyos_show.py.preview
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_show
-short_description: Execute op-mode show commands on a VyOS device via REST API.
-description:
- - Sends a C(show) operational-mode command to a VyOS device via the
- HTTPS REST API (C(/show) endpoint) and returns the text output.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- path:
- description:
- - Operational-mode command tokens following C(show).
- - E.g. C(["interfaces"]) maps to C(show interfaces).
- type: list
- elements: str
- required: true
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-notes:
- - This module never modifies device state.
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.rest.vyos_configure
- - module: vyos.rest.vyos_retrieve
-examples: |
- - name: Show interfaces
- vyos.rest.vyos_show:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["interfaces"]
- register: iface_output
-
- - name: Show version
- vyos.rest.vyos_show:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["version"]
- register: ver_output
-
- - name: Show installed images
- vyos.rest.vyos_show:
- hostname: 192.168.1.1
- api_key: MY-KEY
- path: ["system", "image"]
- register: images
-"""
-
-RETURN = r"""
-output:
- description: Raw text output from the show command.
- returned: success
- type: str
- sample: |
- Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
- Interface IP Address S/L Description
- eth0 10.0.0.1/24 u/u WAN
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def main():
- argument_spec = dict(
- path=dict(type="list", elements="str", required=True),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- try:
- result = client.show(module.params["path"])
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=False, output=result.get("data", ""))
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_static_routes.py.preview b/plugins/modules/vyos_static_routes.py.preview
deleted file mode 100644
index f203603..0000000
--- a/plugins/modules/vyos_static_routes.py.preview
+++ /dev/null
@@ -1,397 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# 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
-
-DOCUMENTATION = r"""
----
-module: vyos_static_routes
-short_description: Manage static routes on VyOS via the REST API.
-description:
- - Manages IPv4 and IPv6 static routes on VyOS devices using the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_static_routes) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- config:
- description: List of static route address-family configurations.
- type: list
- elements: dict
- suboptions:
- address_families:
- description: List of address family route groups.
- type: list
- elements: dict
- suboptions:
- afi:
- description: Address family indicator.
- type: str
- choices: [ipv4, ipv6]
- required: true
- routes:
- description: List of static route entries.
- type: list
- elements: dict
- suboptions:
- dest:
- description: Destination prefix in CIDR notation.
- type: str
- required: true
- blackhole_config:
- description: Blackhole route configuration.
- type: dict
- suboptions:
- distance:
- description: Administrative distance (1-255).
- type: int
- type:
- description: Blackhole type.
- type: str
- next_hops:
- description: List of next-hop addresses.
- type: list
- elements: dict
- suboptions:
- forward_router_address:
- description: Next-hop IP address.
- type: str
- required: true
- admin_distance:
- description: Administrative distance for this next-hop.
- type: int
- enabled:
- description: Whether this next-hop is enabled.
- type: bool
- default: true
- interface:
- description: Outgoing interface name.
- type: str
- state:
- description:
- - C(merged): Add routes (preserve existing).
- - C(replaced): Replace routes for listed destinations.
- - C(overridden): Replace the entire static route table.
- - C(deleted): Remove listed (or all) static routes.
- - C(gathered): Read static routes from device.
- type: str
- choices: [merged, replaced, overridden, deleted, gathered]
- default: merged
- hostname:
- description: IP address or FQDN of the VyOS device.
- type: str
- required: true
- port:
- description: HTTPS port for the REST API.
- type: int
- default: 443
- api_key:
- description: API key configured on the device.
- type: str
- required: true
- no_log: true
- timeout:
- description: Request timeout in seconds.
- type: int
- default: 30
- verify_ssl:
- description: Validate the device's TLS certificate.
- type: bool
- default: false
-requirements:
- - VyOS 1.3+
-seealso:
- - module: vyos.vyos.vyos_static_routes
-examples: |
- - name: Add IPv4 static routes
- vyos.rest.vyos_static_routes:
- hostname: 192.168.1.1
- api_key: MY-KEY
- config:
- - address_families:
- - afi: ipv4
- routes:
- - dest: 192.0.2.0/24
- next_hops:
- - forward_router_address: 10.0.0.1
- - dest: 203.0.113.0/24
- blackhole_config:
- distance: 200
- state: merged
-
- - name: Delete all static routes
- vyos.rest.vyos_static_routes:
- hostname: 192.168.1.1
- api_key: MY-KEY
- state: deleted
-"""
-
-RETURN = r"""
-before:
- description: Static route config before the module ran.
- returned: always
- type: list
-after:
- description: Static route config after the module ran.
- returned: when changed
- type: list
-gathered:
- description: Static routes read from device (state=gathered).
- returned: when state is gathered
- type: list
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_ROUTE_BASE = {
- "ipv4": ["protocols", "static", "route"],
- "ipv6": ["protocols", "static", "route6"],
-}
-
-
-def _get_static_routes(client):
- try:
- result = client.retrieve_show_config(["protocols", "static"])
- data = result.get("data") or {}
- out = []
- for afi, route_key in [("ipv4", "route"), ("ipv6", "route6")]:
- routes_data = data.get(route_key, {})
- if not isinstance(routes_data, dict):
- continue
- routes = []
- for dest, rdata in routes_data.items():
- route_entry = {"dest": dest}
- if isinstance(rdata, dict):
- if "blackhole" in rdata:
- bh = rdata["blackhole"]
- bc = {}
- if isinstance(bh, dict) and "distance" in bh:
- bc["distance"] = int(bh["distance"])
- route_entry["blackhole_config"] = bc
- next_hops = []
- for nh_key in ("next-hop", "next_hop"):
- nh_data = rdata.get(nh_key, {})
- if isinstance(nh_data, dict):
- for nh_addr, nh_opts in nh_data.items():
- nh = {"forward_router_address": nh_addr}
- if isinstance(nh_opts, dict):
- if "distance" in nh_opts:
- nh["admin_distance"] = int(nh_opts["distance"])
- nh["enabled"] = "disable" not in nh_opts
- next_hops.append(nh)
- if next_hops:
- route_entry["next_hops"] = next_hops
- routes.append(route_entry)
- if routes:
- out.append({"address_families": [{"afi": afi, "routes": routes}]})
- return out
- except VyOSRestError:
- return []
-
-
-def _apply_route(client, afi, route, commands):
- base = _ROUTE_BASE[afi]
- dest = route["dest"]
-
- if route.get("blackhole_config") is not None:
- bh_path = base + [dest, "blackhole"]
- client.configure_set(bh_path)
- commands.append("set {p}".format(p=" ".join(bh_path)))
- dist = route["blackhole_config"].get("distance")
- if dist:
- client.configure_set(bh_path + ["distance"], str(dist))
- commands.append(
- "set {p} distance {d}".format(p=" ".join(bh_path), d=dist),
- )
-
- for nh in route.get("next_hops") or []:
- nh_addr = nh["forward_router_address"]
- nh_path = base + [dest, "next-hop", nh_addr]
- client.configure_set(nh_path)
- commands.append("set {p}".format(p=" ".join(nh_path)))
- if nh.get("admin_distance"):
- client.configure_set(nh_path + ["distance"], str(nh["admin_distance"]))
- commands.append(
- "set {p} distance {d}".format(
- p=" ".join(nh_path),
- d=nh["admin_distance"],
- ),
- )
- if "enabled" in nh and not nh["enabled"]:
- client.configure_set(nh_path + ["disable"])
- commands.append("set {p} disable".format(p=" ".join(nh_path)))
- if nh.get("interface"):
- client.configure_set(nh_path + ["interface"], nh["interface"])
- commands.append(
- "set {p} interface {i}".format(
- p=" ".join(nh_path),
- i=nh["interface"],
- ),
- )
-
-
-def main():
- argument_spec = dict(
- config=dict(
- type="list",
- elements="dict",
- options=dict(
- address_families=dict(
- type="list",
- elements="dict",
- options=dict(
- afi=dict(type="str", required=True, choices=["ipv4", "ipv6"]),
- routes=dict(
- type="list",
- elements="dict",
- options=dict(
- dest=dict(type="str", required=True),
- blackhole_config=dict(
- type="dict",
- options=dict(
- distance=dict(type="int"),
- type=dict(type="str"),
- ),
- ),
- next_hops=dict(
- type="list",
- elements="dict",
- options=dict(
- forward_router_address=dict(
- type="str",
- required=True,
- ),
- admin_distance=dict(type="int"),
- enabled=dict(type="bool", default=True),
- interface=dict(type="str"),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- state=dict(
- type="str",
- default="merged",
- choices=["merged", "replaced", "overridden", "deleted", "gathered"],
- ),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- config = module.params.get("config") or []
- commands = []
- changed = False
-
- before = _get_static_routes(client)
-
- if state == "gathered":
- module.exit_json(changed=False, gathered=before, before=before, commands=[])
-
- if module.check_mode:
- module.exit_json(changed=True, before=before, commands=["(check mode)"])
-
- try:
- if state in ("overridden", "deleted") and not config:
- # Delete all static routes
- for afi_key in ("route", "route6"):
- try:
- client.configure_delete(["protocols", "static", afi_key])
- commands.append(
- "delete protocols static {k}".format(k=afi_key),
- )
- except VyOSRestError:
- pass
- changed = True
-
- elif state == "deleted" and config:
- for entry in config:
- for af in entry.get("address_families") or []:
- afi = af["afi"]
- base = _ROUTE_BASE[afi]
- for route in af.get("routes") or []:
- try:
- client.configure_delete(base + [route["dest"]])
- commands.append(
- "delete {p} {d}".format(
- p=" ".join(base),
- d=route["dest"],
- ),
- )
- except VyOSRestError:
- pass
- changed = True
-
- elif state in ("merged", "replaced", "overridden"):
- if state in ("replaced", "overridden"):
- # Remove existing routes for affected destinations
- dests_by_afi = {}
- for entry in config:
- for af in entry.get("address_families") or []:
- afi = af["afi"]
- dests_by_afi.setdefault(afi, set())
- for route in af.get("routes") or []:
- dests_by_afi[afi].add(route["dest"])
- if state == "overridden":
- for afi_key in ("route", "route6"):
- try:
- client.configure_delete(
- ["protocols", "static", afi_key],
- )
- commands.append(
- "delete protocols static {k}".format(k=afi_key),
- )
- except VyOSRestError:
- pass
- else:
- for afi, dests in dests_by_afi.items():
- base = _ROUTE_BASE[afi]
- for dest in dests:
- try:
- client.configure_delete(base + [dest])
- commands.append(
- "delete {p} {d}".format(
- p=" ".join(base),
- d=dest,
- ),
- )
- except VyOSRestError:
- pass
-
- for entry in config:
- for af in entry.get("address_families") or []:
- afi = af["afi"]
- for route in af.get("routes") or []:
- _apply_route(client, afi, route, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- after = _get_static_routes(client) if changed else before
- module.exit_json(changed=changed, before=before, after=after, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_system.py.preview b/plugins/modules/vyos_system.py.preview
deleted file mode 100644
index d1d696e..0000000
--- a/plugins/modules/vyos_system.py.preview
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/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_system
-short_description: Manage system settings on VyOS via the REST API.
-description:
- - Manages system-level settings — hostname, domain name, name servers,
- domain search list — using the VyOS HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_system) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- host_name:
- description: System hostname.
- type: str
- domain_name:
- description: System domain name.
- type: str
- name_server:
- description: List of DNS name servers. Mutually exclusive with domain_search.
- type: list
- elements: str
- aliases: [name_servers]
- domain_search:
- description: List of domain search suffixes. Mutually exclusive with name_server.
- type: list
- elements: str
- state:
- description: C(present) to apply, C(absent) to remove.
- type: str
- choices: [present, absent]
- default: present
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def main():
- argument_spec = dict(
- host_name=dict(type="str"),
- domain_name=dict(type="str"),
- name_server=dict(type="list", elements="str", aliases=["name_servers"]),
- domain_search=dict(type="list", elements="str"),
- state=dict(type="str", default="present", choices=["present", "absent"]),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- mutually_exclusive=[["name_server", "domain_search"]],
- supports_check_mode=True,
- )
-
- if module.check_mode:
- module.exit_json(changed=True, commands=["(check mode)"])
-
- client = VyOSRestClient(module)
- state = module.params["state"]
- commands = []
- changed = False
-
- try:
- if state == "present":
- if module.params.get("host_name"):
- client.configure_set(["system", "host-name"], module.params["host_name"])
- commands.append("set system host-name '{h}'".format(h=module.params["host_name"]))
- changed = True
- if module.params.get("domain_name"):
- client.configure_set(["system", "domain-name"], module.params["domain_name"])
- commands.append(
- "set system domain-name '{d}'".format(d=module.params["domain_name"]),
- )
- changed = True
- for ns in module.params.get("name_server") or []:
- client.configure_set(["system", "name-server"], ns)
- commands.append("set system name-server {ns}".format(ns=ns))
- changed = True
- for ds in module.params.get("domain_search") or []:
- client.configure_set(["system", "domain-search", "domain"], ds)
- commands.append("set system domain-search domain {ds}".format(ds=ds))
- changed = True
- else:
- if module.params.get("host_name"):
- try:
- client.configure_delete(["system", "host-name"])
- commands.append("delete system host-name")
- changed = True
- except VyOSRestError:
- pass
- if module.params.get("domain_name"):
- try:
- client.configure_delete(["system", "domain-name"])
- commands.append("delete system domain-name")
- changed = True
- except VyOSRestError:
- pass
- if module.params.get("name_server"):
- try:
- client.configure_delete(["system", "name-server"])
- commands.append("delete system name-server")
- changed = True
- except VyOSRestError:
- pass
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=changed, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_user.py.preview b/plugins/modules/vyos_user.py.preview
deleted file mode 100644
index 41e014d..0000000
--- a/plugins/modules/vyos_user.py.preview
+++ /dev/null
@@ -1,282 +0,0 @@
-#!/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_user
-short_description: Manage local users on VyOS via the REST API.
-description:
- - Manages local user accounts on VyOS devices using the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_user) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- aggregate:
- description: List of user definitions. Mutually exclusive with I(name).
- type: list
- elements: dict
- aliases: [users, collection]
- suboptions:
- name:
- description: Username.
- type: str
- required: true
- full_name:
- description: Full name.
- type: str
- configured_password:
- description: Plaintext password (will be hashed on device).
- type: str
- no_log: true
- encrypted_password:
- description: Pre-hashed password string.
- type: str
- no_log: true
- update_password:
- description: When to update the password.
- type: str
- choices: [always, on_create]
- level:
- description: User privilege level.
- type: str
- choices: [admin, operator]
- public_keys:
- description: SSH public keys for authentication.
- type: list
- elements: dict
- suboptions:
- name:
- description: Key identifier (e.g. user@host).
- type: str
- required: true
- key:
- description: Base64-encoded public key.
- type: str
- required: true
- type:
- description: Key type.
- type: str
- required: true
- choices: [ssh-dss, ssh-rsa, ecdsa-sha2-nistp256,
- ecdsa-sha2-nistp384, ssh-ed25519, ecdsa-sha2-nistp521]
- state:
- description: Present or absent.
- type: str
- choices: [present, absent]
- name:
- description: Single username. Mutually exclusive with I(aggregate).
- type: str
- full_name:
- description: Full name for the single user.
- type: str
- configured_password:
- description: Plaintext password.
- type: str
- no_log: true
- encrypted_password:
- description: Pre-hashed password.
- type: str
- no_log: true
- update_password:
- type: str
- choices: [always, on_create]
- level:
- type: str
- choices: [admin, operator]
- public_keys:
- type: list
- elements: dict
- suboptions:
- name:
- type: str
- required: true
- key:
- type: str
- required: true
- type:
- type: str
- required: true
- state:
- description: Whether to create (present) or remove (absent) the user.
- type: str
- choices: [present, absent]
- default: present
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-_KEY_TYPES = [
- "ssh-dss",
- "ssh-rsa",
- "ecdsa-sha2-nistp256",
- "ecdsa-sha2-nistp384",
- "ssh-ed25519",
- "ecdsa-sha2-nistp521",
-]
-
-
-def _apply_user(client, user_def, commands, update_password="always"):
- name = user_def["name"]
- base = ["system", "login", "user", name]
- client.configure_set(base)
- commands.append("set system login user {n}".format(n=name))
-
- if user_def.get("full_name"):
- client.configure_set(base + ["full-name"], user_def["full_name"])
- if user_def.get("level"):
- client.configure_set(base + ["level"], user_def["level"])
- if user_def.get("configured_password") and update_password in ("always",):
- client.configure_set(
- base + ["authentication", "plaintext-password"],
- user_def["configured_password"],
- )
- commands.append(
- "set system login user {n} authentication plaintext-password".format(n=name),
- )
- if user_def.get("encrypted_password"):
- client.configure_set(
- base + ["authentication", "encrypted-password"],
- user_def["encrypted_password"],
- )
- for pk in user_def.get("public_keys") or []:
- kb = base + ["authentication", "public-keys", pk["name"]]
- client.configure_set(kb + ["key"], pk["key"])
- client.configure_set(kb + ["type"], pk["type"])
- commands.append(
- "set system login user {n} authentication public-keys {k}".format(
- n=name,
- k=pk["name"],
- ),
- )
-
-
-def _delete_user(client, name, commands):
- try:
- client.configure_delete(["system", "login", "user", name])
- commands.append("delete system login user {n}".format(n=name))
- except VyOSRestError:
- pass
-
-
-def main():
- pk_spec = dict(
- type="list",
- elements="dict",
- options=dict(
- name=dict(type="str", required=True),
- key=dict(type="str", required=True),
- type=dict(type="str", required=True, choices=_KEY_TYPES),
- ),
- )
- user_spec = dict(
- name=dict(type="str", required=True),
- full_name=dict(type="str"),
- configured_password=dict(type="str", no_log=True),
- encrypted_password=dict(type="str", no_log=True),
- update_password=dict(type="str", choices=["always", "on_create"]),
- level=dict(type="str", choices=["admin", "operator"]),
- public_keys=pk_spec,
- state=dict(type="str", choices=["present", "absent"]),
- )
- argument_spec = dict(
- aggregate=dict(
- type="list",
- elements="dict",
- aliases=["users", "collection"],
- options=user_spec,
- ),
- name=dict(type="str"),
- full_name=dict(type="str"),
- configured_password=dict(type="str", no_log=True),
- encrypted_password=dict(type="str", no_log=True),
- update_password=dict(type="str", choices=["always", "on_create"]),
- level=dict(type="str", choices=["admin", "operator"]),
- public_keys=pk_spec,
- state=dict(type="str", default="present", choices=["present", "absent"]),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- mutually_exclusive=[["aggregate", "name"]],
- supports_check_mode=True,
- )
- if module.check_mode:
- module.exit_json(changed=True, commands=["(check mode)"])
-
- client = VyOSRestClient(module)
- commands = []
- changed = False
-
- # Build unified user list
- users = module.params.get("aggregate") or []
- if module.params.get("name"):
- users = [
- {
- "name": module.params["name"],
- "full_name": module.params.get("full_name"),
- "configured_password": module.params.get("configured_password"),
- "encrypted_password": module.params.get("encrypted_password"),
- "update_password": module.params.get("update_password", "always"),
- "level": module.params.get("level"),
- "public_keys": module.params.get("public_keys"),
- "state": module.params.get("state", "present"),
- },
- ]
-
- try:
- for u in users:
- u_state = u.get("state") or module.params.get("state", "present")
- if u_state == "absent":
- _delete_user(client, u["name"], commands)
- else:
- _apply_user(
- client,
- u,
- commands,
- update_password=u.get("update_password") or "always",
- )
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=changed, commands=commands)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/vyos_vlan.py.preview b/plugins/modules/vyos_vlan.py.preview
deleted file mode 100644
index 18eca92..0000000
--- a/plugins/modules/vyos_vlan.py.preview
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/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_vlan
-short_description: Manage VLANs on VyOS network devices via REST API.
-description:
- - Manages 802.1Q VLAN sub-interfaces on VyOS Ethernet interfaces using
- the HTTPS REST API.
- - Mirrors C(vyos.vyos.vyos_vlan) but uses the HTTP API.
-version_added: "1.0.0"
-author:
- - VyOS Community (@vyos)
-options:
- vlan_id:
- description: VLAN ID (0-4094).
- type: int
- name:
- description: VLAN name (used as description on the VIF).
- type: str
- address:
- description: IP address for the VLAN interface.
- type: str
- interfaces:
- description: List of physical interfaces to configure the VLAN on.
- type: list
- elements: str
- aggregate:
- description: List of VLAN definitions.
- type: list
- elements: dict
- suboptions:
- vlan_id:
- type: int
- required: true
- name:
- type: str
- address:
- type: str
- interfaces:
- type: list
- elements: str
- required: true
- state:
- type: str
- choices: [present, absent]
- state:
- description: C(present) to configure, C(absent) to remove.
- type: str
- choices: [present, absent]
- default: present
- purge:
- description: Remove VLANs not defined in aggregate.
- type: bool
- default: false
- hostname:
- type: str
- required: true
- port:
- type: int
- default: 443
- api_key:
- type: str
- required: true
- no_log: true
- timeout:
- type: int
- default: 30
- verify_ssl:
- type: bool
- default: false
-"""
-
-RETURN = r"""
-commands:
- description: set/delete commands issued.
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
- VYOS_REST_CONNECTION_ARGSPEC,
- VyOSRestClient,
- VyOSRestError,
-)
-
-
-def _apply_vlan(client, vlan, commands):
- vid = str(vlan["vlan_id"])
- for iface in vlan.get("interfaces") or []:
- # Detect interface type
- if iface.startswith("bond"):
- itype = "bonding"
- else:
- itype = "ethernet"
- vif_base = ["interfaces", itype, iface, "vif", vid]
- client.configure_set(vif_base)
- commands.append("set interfaces {t} {i} vif {v}".format(t=itype, i=iface, v=vid))
- if vlan.get("name"):
- client.configure_set(vif_base + ["description"], vlan["name"])
- commands.append(
- "set interfaces {t} {i} vif {v} description '{n}'".format(
- t=itype,
- i=iface,
- v=vid,
- n=vlan["name"],
- ),
- )
- if vlan.get("address"):
- client.configure_set(vif_base + ["address"], vlan["address"])
- commands.append(
- "set interfaces {t} {i} vif {v} address {a}".format(
- t=itype,
- i=iface,
- v=vid,
- a=vlan["address"],
- ),
- )
-
-
-def _delete_vlan(client, vlan, commands):
- vid = str(vlan["vlan_id"])
- for iface in vlan.get("interfaces") or []:
- itype = "bonding" if iface.startswith("bond") else "ethernet"
- try:
- client.configure_delete(["interfaces", itype, iface, "vif", vid])
- commands.append("delete interfaces {t} {i} vif {v}".format(t=itype, i=iface, v=vid))
- except VyOSRestError:
- pass
-
-
-def main():
- vlan_spec = dict(
- vlan_id=dict(type="int", required=True),
- name=dict(type="str"),
- address=dict(type="str"),
- interfaces=dict(type="list", elements="str"),
- state=dict(type="str", choices=["present", "absent"]),
- )
- argument_spec = dict(
- vlan_id=dict(type="int"),
- name=dict(type="str"),
- address=dict(type="str"),
- interfaces=dict(type="list", elements="str"),
- aggregate=dict(type="list", elements="dict", options=vlan_spec),
- state=dict(type="str", default="present", choices=["present", "absent"]),
- purge=dict(type="bool", default=False),
- )
- argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
- module = AnsibleModule(
- argument_spec=argument_spec,
- mutually_exclusive=[["aggregate", "vlan_id"]],
- supports_check_mode=True,
- )
- if module.check_mode:
- module.exit_json(changed=True, commands=["(check mode)"])
-
- client = VyOSRestClient(module)
- commands = []
- changed = False
-
- vlans = module.params.get("aggregate") or []
- if module.params.get("vlan_id"):
- vlans = [
- {
- "vlan_id": module.params["vlan_id"],
- "name": module.params.get("name"),
- "address": module.params.get("address"),
- "interfaces": module.params.get("interfaces") or [],
- "state": module.params.get("state", "present"),
- },
- ]
-
- try:
- for vlan in vlans:
- v_state = vlan.get("state") or module.params.get("state", "present")
- if v_state == "absent":
- _delete_vlan(client, vlan, commands)
- else:
- _apply_vlan(client, vlan, commands)
- changed = True
- except VyOSRestError as exc:
- module.fail_json(msg=str(exc))
-
- module.exit_json(changed=changed, commands=commands)
-
-
-if __name__ == "__main__":
- main()