diff --git a/README.md b/README.md index d771dd70..2a63d7d1 100644 --- a/README.md +++ b/README.md @@ -1,173 +1,173 @@ # VyOS Collection [![CI](https://zuul-ci.org/gated.svg)](https://dashboard.zuul.ansible.com/t/ansible/project/github.com/ansible-collections/vyos) The Ansible VyOS collection includes a variety of Ansible content to help automate the management of VyOS network appliances. This collection has been tested against VyOS 1.1.8 (helium). ## Ansible version compatibility -This collection has been tested against following Ansible versions: **>=2.9.10,<2.11**. +This collection has been tested against following Ansible versions: **>=2.9.10**. Plugins and modules within a collection may be tested with only specific Ansible versions. A collection may contain metadata that identifies these versions. PEP440 is the schema used to describe the versions of Ansible. ### Supported connections The VyOS collection supports ``network_cli`` connections. ## Included content ### Cliconf plugins Name | Description --- | --- [vyos.vyos.vyos](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_cliconf.rst)|Use vyos cliconf to run command on VyOS platform ### Filter plugins Name | Description --- | --- ### Modules Name | Description --- | --- [vyos.vyos.vyos_banner](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_banner_module.rst)|Manage multiline banners on VyOS devices [vyos.vyos.vyos_command](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_command_module.rst)|Run one or more commands on VyOS devices [vyos.vyos.vyos_config](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_config_module.rst)|Manage VyOS configuration on remote device [vyos.vyos.vyos_facts](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_facts_module.rst)|Get facts about vyos devices. [vyos.vyos.vyos_firewall_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_global_module.rst)|FIREWALL global resource module [vyos.vyos.vyos_firewall_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_interfaces_module.rst)|FIREWALL interfaces resource module [vyos.vyos.vyos_firewall_rules](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_rules_module.rst)|FIREWALL rules resource module [vyos.vyos.vyos_interface](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_interface_module.rst)|(deprecated, removed after 2022-06-01) Manage Interface on VyOS network devices [vyos.vyos.vyos_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_interfaces_module.rst)|Interfaces resource module [vyos.vyos.vyos_l3_interface](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_l3_interface_module.rst)|(deprecated, removed after 2022-06-01) Manage L3 interfaces on VyOS network devices [vyos.vyos.vyos_l3_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_l3_interfaces_module.rst)|L3 interfaces resource module [vyos.vyos.vyos_lag_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lag_interfaces_module.rst)|LAG interfaces resource module [vyos.vyos.vyos_linkagg](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_linkagg_module.rst)|(deprecated, removed after 2022-06-01) Manage link aggregation groups on VyOS network devices [vyos.vyos.vyos_lldp](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lldp_module.rst)|(deprecated, removed after 2022-06-01) Manage LLDP configuration on VyOS network devices [vyos.vyos.vyos_lldp_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lldp_global_module.rst)|LLDP global resource module [vyos.vyos.vyos_lldp_interface](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lldp_interface_module.rst)|(deprecated, removed after 2022-06-01) Manage LLDP interfaces configuration on VyOS network devices [vyos.vyos.vyos_lldp_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lldp_interfaces_module.rst)|LLDP interfaces resource module [vyos.vyos.vyos_logging](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_logging_module.rst)|Manage logging on network devices [vyos.vyos.vyos_ospf_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ospf_interfaces_module.rst)|OSPF Interfaces Resource Module. [vyos.vyos.vyos_ospfv2](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ospfv2_module.rst)|OSPFv2 resource module [vyos.vyos.vyos_ospfv3](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ospfv3_module.rst)|OSPFV3 resource module [vyos.vyos.vyos_ping](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ping_module.rst)|Tests reachability using ping from VyOS network devices [vyos.vyos.vyos_static_route](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_static_route_module.rst)|(deprecated, removed after 2022-06-01) Manage static IP routes on Vyatta VyOS network devices [vyos.vyos.vyos_static_routes](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_static_routes_module.rst)|Static routes resource module [vyos.vyos.vyos_system](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_system_module.rst)|Run `set system` commands on VyOS devices [vyos.vyos.vyos_user](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_user_module.rst)|Manage the collection of local users on VyOS device [vyos.vyos.vyos_vlan](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_vlan_module.rst)|Manage VLANs on VyOS network devices ### Inventory plugins Name | Description --- | --- Click the ``Content`` button to see the list of content included in this collection. ## Installing this collection You can install the VyOS collection with the Ansible Galaxy CLI: ansible-galaxy collection install vyos.vyos You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format: ```yaml --- collections: - name: vyos.vyos ``` ## Using this collection This collection includes [network resource modules](https://docs.ansible.com/ansible/latest/network/user_guide/network_resource_modules.html). ### Using modules from the VyOS collection in your playbooks You can call modules by their Fully Qualified Collection Namespace (FQCN), such as `vyos.vyos.vyos_static_routes`. The following example task replaces configuration changes in the existing configuration on a VyOS network device, using the FQCN: ```yaml --- - name: Replace device configurations of listed static routes with provided configurations register: result vyos.vyos.vyos_static_routes: &id001 config: - address_families: - afi: ipv4 routes: - dest: 192.0.2.32/28 blackhole_config: distance: 2 next_hops: - forward_router_address: 192.0.2.7 - forward_router_address: 192.0.2.8 - forward_router_address: 192.0.2.9 state: replaced ``` **NOTE**: For Ansible 2.9, you may not see deprecation warnings when you run your playbooks with this collection. Use this documentation to track when a module is deprecated. ### See Also: * [VyOS Platform Options](https://docs.ansible.com/ansible/latest/network/user_guide/platform_vyos.html) * [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. ## Contributing to this collection We welcome community contributions to this collection. If you find problems, please open an issue or create a PR against the [VyOS collection repository](https://github.com/ansible-collections/vyos). See [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details. You can also join us on: - Freenode IRC - ``#ansible-network`` Freenode channel - Slack - https://ansiblenetwork.slack.com See the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for details on contributing to Ansible. ### Code of Conduct This collection follows the Ansible project's [Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html). Please read and familiarize yourself with this document. ## Changelogs ## Release notes Release notes are available [here](https://github.com/ansible-collections/vyos.vyos/blob/main/changelogs/CHANGELOG.rst). ## Roadmap ## More information - [Ansible network resources](https://docs.ansible.com/ansible/latest/network/getting_started/network_resources.html) - [Ansible Collection overview](https://github.com/ansible-collections/overview) - [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html) - [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html) - [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) ## Licensing GNU General Public License v3.0 or later. See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. diff --git a/changelogs/fragments/fix_docker_sanity_test_failures.yaml b/changelogs/fragments/fix_docker_sanity_test_failures.yaml new file mode 100644 index 00000000..3f02049a --- /dev/null +++ b/changelogs/fragments/fix_docker_sanity_test_failures.yaml @@ -0,0 +1,3 @@ +--- +trivial: + - Fix failures in test-sanity-docker (https://github.com/ansible-collections/arista.eos/pull/172). diff --git a/meta/runtime.yml b/meta/runtime.yml index 00bbaca7..e68ed605 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,209 +1,209 @@ --- -requires_ansible: '>=2.9.10,<2.11' +requires_ansible: '>=2.9.10' plugin_routing: action: vyos_banner: redirect: vyos.vyos.vyos banner: redirect: vyos.vyos.vyos vyos_command: redirect: vyos.vyos.vyos command: redirect: vyos.vyos.vyos vyos_config: redirect: vyos.vyos.vyos config: redirect: vyos.vyos.vyos vyos_facts: redirect: vyos.vyos.vyos facts: redirect: vyos.vyos.vyos vyos_firewall_global: redirect: vyos.vyos.vyos firewall_global: redirect: vyos.vyos.vyos vyos_firewall_interfaces: redirect: vyos.vyos.vyos firewall_interfaces: redirect: vyos.vyos.vyos vyos_firewall_rules: redirect: vyos.vyos.vyos firewall_rules: redirect: vyos.vyos.vyos vyos_interface: redirect: vyos.vyos.vyos interface: redirect: vyos.vyos.vyos vyos_interfaces: redirect: vyos.vyos.vyos interfaces: redirect: vyos.vyos.vyos vyos_l3_interface: redirect: vyos.vyos.vyos l3_interface: redirect: vyos.vyos.vyos vyos_l3_interfaces: redirect: vyos.vyos.vyos l3_interfaces: redirect: vyos.vyos.vyos vyos_lag_interfaces: redirect: vyos.vyos.vyos lag_interfaces: redirect: vyos.vyos.vyos vyos_linkagg: redirect: vyos.vyos.vyos linkagg: redirect: vyos.vyos.vyos vyos_lldp: redirect: vyos.vyos.vyos lldp: redirect: vyos.vyos.vyos vyos_lldp_global: redirect: vyos.vyos.vyos lldp_global: redirect: vyos.vyos.vyos vyos_lldp_interface: redirect: vyos.vyos.vyos lldp_interface: redirect: vyos.vyos.vyos vyos_lldp_interfaces: redirect: vyos.vyos.vyos lldp_interfaces: redirect: vyos.vyos.vyos vyos_logging: redirect: vyos.vyos.vyos logging: redirect: vyos.vyos.vyos vyos_ospfv2: redirect: vyos.vyos.vyos ospfv2: redirect: vyos.vyos.vyos vyos_ospfv3: redirect: vyos.vyos.vyos ospfv3: redirect: vyos.vyos.vyos vyos_ospf_interfaces: redirect: vyos.vyos.vyos ospf_interfaces: redirect: vyos.vyos.vyos vyos_ping: redirect: vyos.vyos.vyos ping: redirect: vyos.vyos.vyos vyos_static_route: redirect: vyos.vyos.vyos static_route: redirect: vyos.vyos.vyos vyos_static_routes: redirect: vyos.vyos.vyos static_routes: redirect: vyos.vyos.vyos vyos_system: redirect: vyos.vyos.vyos system: redirect: vyos.vyos.vyos vyos_user: redirect: vyos.vyos.vyos user: redirect: vyos.vyos.vyos vyos_vlan: redirect: vyos.vyos.vyos vlan: redirect: vyos.vyos.vyos modules: banner: redirect: vyos.vyos.vyos_banner command: redirect: vyos.vyos.vyos_command config: redirect: vyos.vyos.vyos_config facts: redirect: vyos.vyos.vyos_facts firewall_global: redirect: vyos.vyos.vyos_firewall_global firewall_interfaces: redirect: vyos.vyos.vyos_firewall_interfaces firewall_rules: redirect: vyos.vyos.vyos_firewall_rules interface: redirect: vyos.vyos.vyos_interface deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details vyos_interface: deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details interfaces: redirect: vyos.vyos.vyos_interfaces l3_interface: redirect: vyos.vyos.vyos_l3_interface deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details vyos_l3_interface: deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details l3_interfaces: redirect: vyos.vyos.vyos_l3_interfaces lag_interfaces: redirect: vyos.vyos.vyos_lag_interfaces linkagg: redirect: vyos.vyos.vyos_linkagg deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details vyos_linkagg: deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details lldp: redirect: vyos.vyos.vyos_lldp deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details vyos_lldp: deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details lldp_global: redirect: vyos.vyos.vyos_lldp_global lldp_interface: redirect: vyos.vyos.vyos_lldp_interface deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details vyos_lldp_interface: deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details lldp_interfaces: redirect: vyos.vyos.vyos_lldp_interfaces logging: redirect: vyos.vyos.vyos_logging ospfv2: redirect: vyos.vyos.vyos_ospfv2 ospfv3: redirect: vyos.vyos.vyos_ospfv3 ospf_interfaces: redirect: vyos.vyos.vyos_ospf_interfaces ping: redirect: vyos.vyos.vyos_ping static_route: redirect: vyos.vyos.vyos_static_route deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details vyos_static_route: deprecation: removal_date: '2022-06-01' warning_text: See the plugin documentation for more details static_routes: redirect: vyos.vyos.vyos_static_routes system: redirect: vyos.vyos.vyos_system user: redirect: vyos.vyos.vyos_user vlan: redirect: vyos.vyos.vyos_vlan diff --git a/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py b/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py index d01b1e02..c7590ee7 100644 --- a/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py +++ b/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py @@ -1,164 +1,170 @@ # # -*- coding: utf-8 -*- # Copyright 2020 Red Hat # 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 """ The vyos_ospf_interfaces config file. It is in this file where the current configuration (as dict) is compared to the provided configuration (as dict) and the command set necessary to bring the current configuration to its desired end-state is created. """ from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( dict_merge, ) from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.resource_module import ( ResourceModule, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( Facts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.ospf_interfaces import ( Ospf_interfacesTemplate, ) class Ospf_interfaces(ResourceModule): """ The vyos_ospf_interfaces config class """ def __init__(self, module): super(Ospf_interfaces, self).__init__( empty_fact_val={}, facts_module=Facts(module), module=module, resource="ospf_interfaces", tmplt=Ospf_interfacesTemplate(), ) self.parsers = [ "authentication_password", "authentication_md5", "bandwidth", "cost", "hello_interval", "dead_interval", "mtu_ignore", "network", "priority", "retransmit_interval", "transmit_delay", "ifmtu", "instance", "passive", ] def execute_module(self): """Execute the module :rtype: A dictionary :returns: The result from module execution """ if self.state not in ["parsed", "gathered"]: self.generate_commands() self.run_commands() return self.result def generate_commands(self): """Generate configuration commands to send based on want, have and desired state. """ - wantd = {entry["name"]: entry for entry in self.want} - haved = {entry["name"]: entry for entry in self.have} + wantd = {} + haved = {} + for entry in self.want: + wantd.update({entry["name"]: entry}) + for entry in self.have: + haved.update({entry["name"]: entry}) # turn all lists of dicts into dicts prior to merge for entry in wantd, haved: self._ospf_int_list_to_dict(entry) # if state is merged, merge want onto have and then compare if self.state == "merged": wantd = dict_merge(haved, wantd) # if state is deleted, empty out wantd and set haved to wantd if self.state == "deleted": - haved = { - k: v for k, v in iteritems(haved) if k in wantd or not wantd - } + h_del = {} + for k, v in iteritems(haved): + if k in wantd or not wantd: + h_del.update({k: v}) + haved = h_del have_int = [] for k, have in iteritems(haved): if k in wantd: have_int.append(k) self._remove_ospf_int(have) wantd = {} if self.state == "overridden": have_int = [] for k, have in iteritems(haved): if k not in wantd: have_int.append(k) self._remove_ospf_int(have) # remove superfluous config for overridden and deleted if self.state in ["overridden", "deleted"]: # removing the interfaces from haved that are already negated for interface in have_int: haved.pop(interface) for k, have in iteritems(haved): if k not in wantd: self._compare(want={}, have=have) for k, want in iteritems(wantd): self._compare(want=want, have=haved.pop(k, {})) def _remove_ospf_int(self, entry): int_name = entry.get("name", {}) int_addr = entry.get("address_family", {}) for k, addr in iteritems(int_addr): rem_entry = {"name": int_name, "address_family": {"afi": k}} self.addcmd(rem_entry, "ip_ospf", True) def _compare(self, want, have): """Leverages the base class `compare()` method and populates the list of commands to be run by comparing the `want` and `have` data with the `parsers` defined for the Ospf_interfaces network resource. """ self._compare_addr_family(want=want, have=have) def _compare_addr_family(self, want, have): wdict = want.get("address_family", {}) hdict = have.get("address_family", {}) wname = want.get("name") hname = have.get("name") for name, entry in iteritems(wdict): for key, param in iteritems(entry): w_addr = {"afi": name, key: param} h_addr = {} if hdict.get(name): h_addr = {"afi": name, key: hdict[name].pop(key, {})} w = {"name": wname, "address_family": w_addr} h = {"name": hname, "address_family": h_addr} self.compare(parsers=self.parsers, want=w, have=h) for name, entry in iteritems(hdict): for key, param in iteritems(entry): h_addr = {"afi": name, key: param} w_addr = {} w = {"name": wname, "address_family": w_addr} h = {"name": hname, "address_family": h_addr} self.compare(parsers=self.parsers, want=w, have=h) def _ospf_int_list_to_dict(self, entry): for name, family in iteritems(entry): if "address_family" in family: - family["address_family"] = { - entry["afi"]: entry - for entry in family.get("address_family", []) - } + addr_dict = {} + for entry in family.get("address_family", []): + addr_dict.update({entry["afi"]: entry}) + family["address_family"] = addr_dict self._ospf_int_list_to_dict(family["address_family"]) diff --git a/plugins/modules/vyos_l3_interface.py b/plugins/modules/vyos_l3_interface.py index 88b5a911..214022a3 100644 --- a/plugins/modules/vyos_l3_interface.py +++ b/plugins/modules/vyos_l3_interface.py @@ -1,357 +1,357 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # (c) 2017, Ansible by Red Hat, inc # # This file is part of Ansible by Red Hat # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . # from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = """ module: vyos_l3_interface author: Ricardo Carrillo Cruz (@rcarrillocruz) short_description: (deprecated, removed after 2022-06-01) Manage L3 interfaces on VyOS network devices description: - This module provides declarative management of L3 interfaces on VyOS network devices. version_added: 1.0.0 deprecated: alternative: vyos_l3_interfaces why: Updated modules released with more functionality. removed_at_date: '2022-06-01' notes: - Tested against VYOS 1.1.7 options: name: description: - Name of the L3 interface. type: str ipv4: description: - IPv4 of the L3 interface. type: str ipv6: description: - IPv6 of the L3 interface. type: str aggregate: description: List of L3 interfaces definitions type: list elements: dict suboptions: name: description: - Name of the L3 interface. type: str required: True ipv4: description: - IPv4 of the L3 interface. type: str ipv6: description: - IPv6 of the L3 interface. type: str state: description: - State of the L3 interface configuration. type: str choices: - present - absent state: description: - State of the L3 interface configuration. default: present type: str choices: - present - absent extends_documentation_fragment: - vyos.vyos.vyos """ EXAMPLES = """ - name: Set eth0 IPv4 address vyos.vyos.vyos_l3_interface: name: eth0 ipv4: 192.168.0.1/24 - name: Remove eth0 IPv4 address vyos.vyos.vyos_l3_interface: name: eth0 state: absent - name: Set IP addresses on aggregate vyos.vyos.vyos_l3_interface: aggregate: - {name: eth1, ipv4: 192.168.2.10/24} - - {name: eth2, ipv4: 192.168.3.10/24, ipv6: fd5d:12c9:2201:1::1/64} + - {name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64"} - name: Remove IP addresses on aggregate vyos.vyos.vyos_l3_interface: aggregate: - {name: eth1, ipv4: 192.168.2.10/24} - - {name: eth2, ipv4: 192.168.3.10/24, ipv6: fd5d:12c9:2201:1::1/64} + - {name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64"} state: absent """ RETURN = """ commands: description: The list of configuration mode commands to send to the device returned: always, except for the platforms that use Netconf transport to manage the device. type: list sample: - set interfaces ethernet eth0 address '192.168.0.1/24' """ import socket import re from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( is_masklen, validate_ip_address, ) from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( remove_default_spec, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( load_config, run_commands, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( vyos_argument_spec, ) def is_ipv4(value): if value: address = value.split("/") if is_masklen(address[1]) and validate_ip_address(address[0]): return True return False def is_ipv6(value): if value: address = value.split("/") if 0 <= int(address[1]) <= 128: try: socket.inet_pton(socket.AF_INET6, address[0]) except socket.error: return False return True return False def search_obj_in_list(name, lst): for o in lst: if o["name"] == name: return o return None def map_obj_to_commands(updates, module): commands = list() want, have = updates for w in want: name = w["name"] ipv4 = w["ipv4"] ipv6 = w["ipv6"] state = w["state"] obj_in_have = search_obj_in_list(name, have) if state == "absent" and obj_in_have: if ( not ipv4 and not ipv6 and (obj_in_have["ipv4"] or obj_in_have["ipv6"]) ): if name == "lo": commands.append("delete interfaces loopback lo address") else: commands.append( "delete interfaces ethernet " + name + " address" ) else: if ipv4 and ipv4 in obj_in_have["ipv4"]: if name == "lo": commands.append( "delete interfaces loopback lo address " + ipv4 ) else: commands.append( "delete interfaces ethernet " + name + " address " + ipv4 ) if ipv6 and ipv6 in obj_in_have["ipv6"]: if name == "lo": commands.append( "delete interfaces loopback lo address " + ipv6 ) else: commands.append( "delete interfaces ethernet " + name + " address " + ipv6 ) elif state == "present" and obj_in_have: if ipv4 and ipv4 not in obj_in_have["ipv4"]: if name == "lo": commands.append( "set interfaces loopback lo address " + ipv4 ) else: commands.append( "set interfaces ethernet " + name + " address " + ipv4 ) if ipv6 and ipv6 not in obj_in_have["ipv6"]: if name == "lo": commands.append( "set interfaces loopback lo address " + ipv6 ) else: commands.append( "set interfaces ethernet " + name + " address " + ipv6 ) return commands def map_config_to_obj(module): obj = [] output = run_commands(module, ["show interfaces"]) lines = re.split(r"\n[e|l]", output[0])[1:] if len(lines) > 0: for line in lines: splitted_line = line.split() if len(splitted_line) > 0: ipv4 = [] ipv6 = [] if splitted_line[0].lower().startswith("th"): name = "e" + splitted_line[0].lower() elif splitted_line[0].lower().startswith("o"): name = "l" + splitted_line[0].lower() for i in splitted_line[1:]: if ("." in i or ":" in i) and "/" in i: value = i.split(r"\n")[0] if is_ipv4(value): ipv4.append(value) elif is_ipv6(value): ipv6.append(value) obj.append({"name": name, "ipv4": ipv4, "ipv6": ipv6}) return obj def map_params_to_obj(module): obj = [] aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: if item.get(key) is None: item[key] = module.params[key] obj.append(item.copy()) else: obj.append( { "name": module.params["name"], "ipv4": module.params["ipv4"], "ipv6": module.params["ipv6"], "state": module.params["state"], } ) return obj def main(): """main entry point for module execution""" element_spec = dict( name=dict(), ipv4=dict(), ipv6=dict(), state=dict(default="present", choices=["present", "absent"]), ) aggregate_spec = deepcopy(element_spec) aggregate_spec["name"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( aggregate=dict(type="list", elements="dict", options=aggregate_spec), ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) required_one_of = [["name", "aggregate"]] mutually_exclusive = [["name", "aggregate"]] module = AnsibleModule( argument_spec=argument_spec, required_one_of=required_one_of, mutually_exclusive=mutually_exclusive, supports_check_mode=True, ) warnings = list() result = {"changed": False} if warnings: result["warnings"] = warnings want = map_params_to_obj(module) have = map_config_to_obj(module) commands = map_obj_to_commands((want, have), module) result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) result["changed"] = True module.exit_json(**result) if __name__ == "__main__": main() diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt index c835eef8..a44822bd 100644 --- a/tests/sanity/ignore-2.10.txt +++ b/tests/sanity/ignore-2.10.txt @@ -1 +1,3 @@ plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local` +plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt new file mode 100644 index 00000000..a44822bd --- /dev/null +++ b/tests/sanity/ignore-2.11.txt @@ -0,0 +1,3 @@ +plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local` +plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt index 8f3fd9cf..68064bb3 100644 --- a/tests/sanity/ignore-2.9.txt +++ b/tests/sanity/ignore-2.9.txt @@ -1,13 +1,15 @@ plugins/modules/vyos_interface.py validate-modules:deprecation-mismatch # 2.9 expects METADATA plugins/modules/vyos_interface.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict plugins/modules/vyos_l3_interface.py validate-modules:deprecation-mismatch # 2.9 expects METADATA plugins/modules/vyos_l3_interface.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict plugins/modules/vyos_linkagg.py validate-modules:deprecation-mismatch # 2.9 expects METADATA plugins/modules/vyos_linkagg.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict plugins/modules/vyos_static_route.py validate-modules:deprecation-mismatch # 2.9 expects METADATA plugins/modules/vyos_static_route.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict plugins/modules/vyos_lldp.py validate-modules:deprecation-mismatch # 2.9 expects METADATA plugins/modules/vyos_lldp.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict plugins/modules/vyos_lldp_interface.py validate-modules:deprecation-mismatch # 2.9 expects METADATA plugins/modules/vyos_lldp_interface.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local` +plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip