diff options
24 files changed, 1229 insertions, 148 deletions
diff --git a/plugins/module_utils/network/vyos/argspec/facts/facts.py b/plugins/module_utils/network/vyos/argspec/facts/facts.py index 624d2fd..31b1aa9 100644 --- a/plugins/module_utils/network/vyos/argspec/facts/facts.py +++ b/plugins/module_utils/network/vyos/argspec/facts/facts.py @@ -24,6 +24,8 @@ class FactsArgs(object): # pylint: disable=R0903 "!l3_interfaces", "lag_interfaces", "!lag_interfaces", + "lldp_global", + "!lldp_global", ] argument_spec = { diff --git a/plugins/module_utils/network/vyos/argspec/lldp_global/__init__.py b/plugins/module_utils/network/vyos/argspec/lldp_global/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/lldp_global/__init__.py diff --git a/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py b/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py new file mode 100644 index 0000000..84bbc00 --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py @@ -0,0 +1,56 @@ +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the resource +# module builder playbook. +# +# Do not edit this file manually. +# +# Changes to this file will be over written +# by the resource module builder. +# +# Changes should be made in the model used to +# generate this file or in the resource module +# builder template. +# +############################################# + +""" +The arg spec for the vyos_lldp_global module +""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +class Lldp_globalArgs(object): # pylint: disable=R0903 + """The arg spec for the vyos_lldp_global module + """ + + def __init__(self, **kwargs): + pass + + argument_spec = { + "config": { + "options": { + "address": {"type": "str"}, + "enable": {"type": "bool"}, + "legacy_protocols": { + "choices": ["cdp", "edp", "fdp", "sonmp"], + "type": "list", + }, + "snmp": {"type": "str"}, + }, + "type": "dict", + }, + "state": { + "choices": ["merged", "replaced", "deleted"], + "default": "merged", + "type": "str", + }, + } # pylint: disable=C0301 diff --git a/plugins/module_utils/network/vyos/config/lldp_global/__init__.py b/plugins/module_utils/network/vyos/config/lldp_global/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/module_utils/network/vyos/config/lldp_global/__init__.py diff --git a/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py b/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py new file mode 100644 index 0000000..54606fa --- /dev/null +++ b/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py @@ -0,0 +1,248 @@ +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The vyos_lldp_global class +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 it's desired end-state is +created +""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type +from ansible.module_utils.network.common.cfg.base import ConfigBase +from ansible.module_utils.network.common.utils import to_list, dict_diff +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( + Facts, +) +from ansible.module_utils.six import iteritems +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( + get_lst_diff_for_dicts, + list_diff_have_only, +) + + +class Lldp_global(ConfigBase): + """ + The vyos_lldp_global class + """ + + gather_subset = ["!all", "!min"] + + gather_network_resources = ["lldp_global"] + + params = ["enable", "address", "snmp", "legacy_protocols"] + + def __init__(self, module): + super(Lldp_global, self).__init__(module) + + def get_lldp_global_facts(self): + """ Get the 'facts' (the current configuration) + + :rtype: A dictionary + :returns: The current configuration as a dictionary + """ + facts, _warnings = Facts(self._module).get_facts( + self.gather_subset, self.gather_network_resources + ) + lldp_global_facts = facts["ansible_network_resources"].get( + "lldp_global" + ) + if not lldp_global_facts: + return {} + return lldp_global_facts + + def execute_module(self): + """ Execute the module + + :rtype: A dictionary + :returns: The result from module execution + """ + result = {"changed": False} + commands = list() + warnings = list() + + existing_lldp_global_facts = self.get_lldp_global_facts() + commands.extend(self.set_config(existing_lldp_global_facts)) + if commands: + if not self._module.check_mode: + self._connection.edit_config(commands) + result["changed"] = True + result["commands"] = commands + + changed_lldp_global_facts = self.get_lldp_global_facts() + + result["before"] = existing_lldp_global_facts + if result["changed"]: + result["after"] = changed_lldp_global_facts + + result["warnings"] = warnings + return result + + def set_config(self, existing_lldp_global_facts): + """ Collect the configuration from the args passed to the module, + collect the current configuration (as a dict from facts) + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + want = self._module.params["config"] + have = existing_lldp_global_facts + resp = self.set_state(want, have) + return to_list(resp) + + def set_state(self, want, have): + """ Select the appropriate function based on the state provided + + :param want: the desired configuration as a dictionary + :param have: the current configuration as a dictionary + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + state = self._module.params["state"] + if state == "deleted": + commands.extend(self._state_deleted(want=None, have=have)) + elif state == "merged": + commands.extend(self._state_merged(want=want, have=have)) + elif state == "replaced": + commands.extend(self._state_replaced(want=want, have=have)) + return commands + + def _state_replaced(self, want, have): + """ The command generator when state is replaced + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + if have: + commands.extend(self._state_deleted(want, have)) + commands.extend(self._state_merged(want, have)) + return commands + + def _state_merged(self, want, have): + """ The command generator when state is merged + + :rtype: A list + :returns: the commands necessary to merge the provided into + the current configuration + """ + commands = [] + commands.extend(self._render_updates(want, have)) + return commands + + def _state_deleted(self, want, have): + """ The command generator when state is deleted + + :rtype: A list + :returns: the commands necessary to remove the current configuration + of the provided objects + """ + commands = [] + if want: + for item in Lldp_global.params: + if item == "legacy_protocols": + commands.extend(self._update_lldp_protocols(want, have)) + elif ( + have.get(item) and not want.get(item) and item != "enable" + ): + commands.append(Lldp_global.del_cmd + item) + elif have: + for item in Lldp_global.params: + if have.get(item): + if item == "legacy_protocols": + commands.append( + self._compute_command( + "legacy-protocols", remove=True + ) + ) + elif item == "address": + commands.append( + self._compute_command( + "management-address", remove=True + ) + ) + elif item == "snmp": + commands.append( + self._compute_command(item, remove=True) + ) + + return commands + + def _render_updates(self, want, have): + commands = [] + if have: + temp_have_legacy_protos = have.pop("legacy_protocols", None) + else: + have = {} + temp_want_legacy_protos = want.pop("legacy_protocols", None) + + updates = dict_diff(have, want) + + if have and temp_have_legacy_protos: + have["legacy_protocols"] = temp_have_legacy_protos + if not have and temp_want_legacy_protos: + want["legacy_protocols"] = temp_want_legacy_protos + + commands.extend(self._add_lldp_protocols(want, have)) + + if updates: + for key, value in iteritems(updates): + if value: + if key == "enable": + commands.append(self._compute_command()) + elif key == "address": + commands.append( + self._compute_command( + "management-address", str(value) + ) + ) + elif key == "snmp": + if value == "disable": + commands.append( + self._compute_command(key, remove=True) + ) + else: + commands.append( + self._compute_command(key, str(value)) + ) + return commands + + def _add_lldp_protocols(self, want, have): + commands = [] + diff_members = get_lst_diff_for_dicts(want, have, "legacy_protocols") + for key in diff_members: + commands.append(self._compute_command("legacy-protocols", key)) + return commands + + def _update_lldp_protocols(self, want_item, have_item): + commands = [] + want_protocols = want_item.get("legacy_protocols") or [] + have_protocols = have_item.get("legacy_protocols") or [] + + members_diff = list_diff_have_only(want_protocols, have_protocols) + if members_diff: + for member in members_diff: + commands.append( + self._compute_command( + "legacy-protocols", member, remove=True + ) + ) + return commands + + def _compute_command(self, key=None, value=None, remove=False): + if remove: + cmd = "delete service lldp" + else: + cmd = "set service lldp" + if key: + cmd += " " + key + + if value: + cmd += " '" + value + "'" + return cmd diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py index 9c389c9..fb05f2a 100644 --- a/plugins/module_utils/network/vyos/facts/facts.py +++ b/plugins/module_utils/network/vyos/facts/facts.py @@ -6,12 +6,9 @@ The facts class for vyos this file validates each subset of facts and selectively calls the appropriate facts gathering function """ - from __future__ import absolute_import, division, print_function __metaclass__ = type - - from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.facts.facts import ( FactsArgs, ) @@ -25,6 +22,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.l3_in from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lag_interfaces.lag_interfaces import ( Lag_interfacesFacts, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_global.lldp_global import ( + Lldp_globalFacts, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import ( Default, Neighbors, @@ -37,6 +37,7 @@ FACT_RESOURCE_SUBSETS = dict( interfaces=InterfacesFacts, l3_interfaces=L3_interfacesFacts, lag_interfaces=Lag_interfacesFacts, + lldp_global=Lldp_globalFacts, ) @@ -71,7 +72,6 @@ class Facts(FactsBase): resource_facts_type, data, ) - if self.VALID_LEGACY_GATHER_SUBSETS: self.get_network_legacy_facts( FACT_LEGACY_SUBSETS, legacy_facts_type diff --git a/plugins/module_utils/network/vyos/facts/legacy/base.py b/plugins/module_utils/network/vyos/facts/legacy/base.py index 34992b1..dce93aa 100644 --- a/plugins/module_utils/network/vyos/facts/legacy/base.py +++ b/plugins/module_utils/network/vyos/facts/legacy/base.py @@ -12,8 +12,6 @@ based on the configuration. from __future__ import absolute_import, division, print_function __metaclass__ = type - - import platform import re from ansible.module_utils.network.vyos.vyos import ( diff --git a/plugins/module_utils/network/vyos/facts/lldp_global/__init__.py b/plugins/module_utils/network/vyos/facts/lldp_global/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/lldp_global/__init__.py diff --git a/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py b/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py new file mode 100644 index 0000000..8954393 --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py @@ -0,0 +1,114 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The vyos lldp_global fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from re import findall, M +from copy import deepcopy + +from ansible.module_utils.network.common import utils +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_global.lldp_global import ( + Lldp_globalArgs, +) + + +class Lldp_globalFacts(object): + """ The vyos lldp_global fact class + """ + + def __init__(self, module, subspec="config", options="options"): + self._module = module + self.argument_spec = Lldp_globalArgs.argument_spec + spec = deepcopy(self.argument_spec) + if subspec: + if options: + facts_argument_spec = spec[subspec][options] + else: + facts_argument_spec = spec[subspec] + else: + facts_argument_spec = spec + + self.generated_spec = utils.generate_dict(facts_argument_spec) + + def populate_facts(self, connection, ansible_facts, data=None): + """ Populate the facts for lldp_global + :param connection: the device connection + :param ansible_facts: Facts dictionary + :param data: previously collected conf + :rtype: dictionary + :returns: facts + """ + if not data: + data = connection.get_config() + + objs = {} + lldp_output = findall(r"^set service lldp (\S+)", data, M) + if lldp_output: + for item in set(lldp_output): + lldp_regex = r" %s .+$" % item + cfg = findall(lldp_regex, data, M) + obj = self.render_config(cfg) + if obj: + objs.update(obj) + lldp_service = findall(r"^set service (lldp)?('lldp')", data, M) + if lldp_service or lldp_output: + lldp_obj = {} + lldp_obj["enable"] = True + objs.update(lldp_obj) + + facts = {} + params = utils.validate_config(self.argument_spec, {"config": objs}) + facts["lldp_global"] = utils.remove_empties(params["config"]) + + ansible_facts["ansible_network_resources"].update(facts) + + return ansible_facts + + def render_config(self, conf): + """ + Render config as dictionary structure and delete keys + from spec for null values + :param spec: The facts tree, generated from the argspec + :param conf: The configuration + :rtype: dictionary + :returns: The generated config + """ + protocol_conf = "\n".join( + filter(lambda x: ("legacy-protocols" in x), conf) + ) + att_conf = "\n".join( + filter(lambda x: ("legacy-protocols" not in x), conf) + ) + config = self.parse_attribs(["snmp", "address"], att_conf) + config["legacy_protocols"] = self.parse_protocols(protocol_conf) + return utils.remove_empties(config) + + def parse_protocols(self, conf): + protocol_support = None + if conf: + protocols = findall(r"^.*legacy-protocols (.+)", conf, M) + if protocols: + protocol_support = [] + for protocol in protocols: + protocol_support.append(protocol.strip("'")) + return protocol_support + + def parse_attribs(self, attribs, conf): + config = {} + for item in attribs: + value = utils.parse_conf_arg(conf, item) + if value: + config[item] = value.strip("'") + else: + config[item] = None + return utils.remove_empties(config) diff --git a/plugins/module_utils/network/vyos/utils/utils.py b/plugins/module_utils/network/vyos/utils/utils.py index d6c11bd..1968ccc 100644 --- a/plugins/module_utils/network/vyos/utils/utils.py +++ b/plugins/module_utils/network/vyos/utils/utils.py @@ -67,7 +67,33 @@ def diff_list_of_dicts(want, have): return diff +def get_lst_diff_for_dicts(want, have, lst): + """ + This function generates a list containing values + that are only in want and not in list in have dict + :param want: dict object to want + :param have: dict object to have + :param lst: list the diff on + :return: new list object with values which are only in want. + """ + if not have: + diff = want.get(lst) or [] + + else: + want_elements = want.get(lst) or {} + have_elements = have.get(lst) or {} + diff = list_diff_want_only(want_elements, have_elements) + return diff + + def list_diff_have_only(want_list, have_list): + """ + This function generated the list containing values + that are only in have list. + :param want_list: + :param have_list: + :return: new list with values which are only in have list + """ if have_list and not want_list: diff = have_list elif not have_list: @@ -82,6 +108,13 @@ def list_diff_have_only(want_list, have_list): def list_diff_want_only(want_list, have_list): + """ + This function generated the list containing values + that are only in want list. + :param want_list: + :param have_list: + :return: new list with values which are only in want list + """ if have_list and not want_list: diff = None elif not have_list: @@ -93,14 +126,3 @@ def list_diff_want_only(want_list, have_list): if i in want_list and i not in have_list ] return diff - - -def get_lst_diff_for_dicts(want, have, lst): - if not have: - diff = want.get(lst) or [] - - else: - want_elements = want.get(lst) or {} - have_elements = have.get(lst) or {} - diff = list_diff_want_only(want_elements, have_elements) - return diff diff --git a/plugins/modules/_vyos_lldp.py b/plugins/modules/_vyos_lldp.py new file mode 100644 index 0000000..6978754 --- /dev/null +++ b/plugins/modules/_vyos_lldp.py @@ -0,0 +1,144 @@ +#!/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 <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} + + +DOCUMENTATION = """ +--- +module: vyos_lldp +version_added: "2.4" +author: "Ricardo Carrillo Cruz (@rcarrillocruz)" +short_description: Manage LLDP configuration on VyOS network devices +description: + - This module provides declarative management of LLDP service + on VyOS network devices. +deprecated: + removed_in: '2.13' + alternative: vyos_lldp_global + why: Updated modules released with more functionality. +notes: + - Tested against VYOS 1.1.7 +options: + interfaces: + description: + - Name of the interfaces. + type: list + state: + description: + - State of the link aggregation group. + default: present + choices: ['present', 'absent', 'enabled', 'disabled'] + type: str +extends_documentation_fragment: vyos +""" + +EXAMPLES = """ +- name: Enable LLDP service + vyos_lldp: + state: present + +- name: Disable LLDP service + vyos_lldp: + 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 service lldp +""" +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) + + +def has_lldp(module): + config = get_config(module).splitlines() + + if "set service 'lldp'" in config or "set service lldp" in config: + return True + else: + return False + + +def main(): + """ main entry point for module execution + """ + argument_spec = dict( + interfaces=dict(type="list"), + state=dict( + default="present", + choices=["present", "absent", "enabled", "disabled"], + ), + ) + + argument_spec.update(vyos_argument_spec) + + module = AnsibleModule( + argument_spec=argument_spec, supports_check_mode=True + ) + + warnings = list() + + result = {"changed": False} + + if warnings: + result["warnings"] = warnings + + HAS_LLDP = has_lldp(module) + + commands = [] + + if module.params["state"] == "absent" and HAS_LLDP: + commands.append("delete service lldp") + elif module.params["state"] == "present" and not HAS_LLDP: + commands.append("set service lldp") + + 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/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index 6ceb234..561b149 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -54,7 +54,7 @@ options: specific subset should not be collected. required: false version_added: "2.9" - choices: ['all', 'interfaces', '!interfaces', 'l3_interfaces', '!l3_interfaces', 'lag_interfaces', '!lag_interfaces'] + choices: ['all', 'interfaces', '!interfaces', 'l3_interfaces', '!l3_interfaces', 'lag_interfaces', '!lag_interfaces', 'lldp_global', '!lldp_global'] """ EXAMPLES = """ diff --git a/plugins/modules/vyos_lldp.py b/plugins/modules/vyos_lldp.py index fdec814..259de8c 100644..120000 --- a/plugins/modules/vyos_lldp.py +++ b/plugins/modules/vyos_lldp.py @@ -1,130 +1 @@ -#!/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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "network", -} - - -DOCUMENTATION = """ ---- -module: vyos_lldp -version_added: "2.4" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage LLDP configuration on VyOS network devices -description: - - This module provides declarative management of LLDP service - on VyOS network devices. -notes: - - Tested against VYOS 1.1.7 -options: - state: - description: - - State of the LLDP configuration. - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos -""" - -EXAMPLES = """ -- name: Enable LLDP service - vyos_lldp: - state: present - -- name: Disable LLDP service - vyos_lldp: - 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 service lldp -""" -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - get_config, - load_config, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - vyos_argument_spec, -) - - -def has_lldp(module): - config = get_config(module).splitlines() - - if "set service 'lldp'" in config or "set service lldp" in config: - return True - else: - return False - - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - interfaces=dict(type="list"), - state=dict( - default="present", - choices=["present", "absent", "enabled", "disabled"], - ), - ) - - argument_spec.update(vyos_argument_spec) - - module = AnsibleModule( - argument_spec=argument_spec, supports_check_mode=True - ) - - warnings = list() - - result = {"changed": False} - - if warnings: - result["warnings"] = warnings - - HAS_LLDP = has_lldp(module) - - commands = [] - - if module.params["state"] == "absent" and HAS_LLDP: - commands.append("delete service lldp") - elif module.params["state"] == "present" and not HAS_LLDP: - commands.append("set service lldp") - - 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() +_vyos_lldp.py
\ No newline at end of file diff --git a/plugins/modules/vyos_lldp_global.py b/plugins/modules/vyos_lldp_global.py new file mode 100644 index 0000000..3783dcb --- /dev/null +++ b/plugins/modules/vyos_lldp_global.py @@ -0,0 +1,333 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the resource +# module builder playbook. +# +# Do not edit this file manually. +# +# Changes to this file will be over written +# by the resource module builder. +# +# Changes should be made in the model used to +# generate this file or in the resource module +# builder template. +# +############################################# + +""" +The module file for vyos_lldp_global +""" + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} + +DOCUMENTATION = """ +--- +module: vyos_lldp_global +version_added: 2.9 +short_description: Manage link layer discovery protocol (LLDP) attributes on VyOS devices.. +description: This module manages link layer discovery protocol (LLDP) attributes on VyOS devices. +notes: + - Tested against VyOS 1.1.8 (helium). + - This module works with connection C(network_cli). +author: + - Rohit Thakur (@rohitthakur2590) +options: + config: + description: The provided link layer discovery protocol (LLDP) configuration. + type: dict + suboptions: + enable: + description: + - This argument is a boolean value to enable or disable LLDP. + type: bool + address: + description: + - This argument defines management-address. + type: str + snmp: + description: + - This argument enable the SNMP queries to LLDP database. + type: str + legacy_protocols: + description: + - List of the supported legacy protocols. + type: list + choices: + - cdp + - edp + - fdp + - sonmp + state: + description: + - The state the configuration should be left in. + type: str + choices: + - merged + - replaced + - deleted + default: merged +""" +EXAMPLES = """ +# Using merged +# +# Before state: +# ------------- +# +# vyos@vyos:~$ show configuration commands|grep lldp +# vyos@vyos:~$ +# +- name: Merge provided configuration with device configuration + vyos_lldp_global: + config: + legacy_protocols: + - 'fdp' + - 'cdp' + snmp: 'enable' + address: 192.0.2.11 + state: merged +# +# +# ------------------------ +# Module Execution Results +# ------------------------ +# +# "before": [] +# +# "commands": [ +# "set service lldp legacy-protocols fdp", +# "set service lldp legacy-protocols cdp", +# "set service lldp snmp enable", +# "set service lldp management-address '192.0.2.11'" +# ] +# +# "after": [ +# { +# "snmp": "enable" +# }, +# { +# "address": "192.0.2.11" +# }, +# { +# "legacy_protocols": [ +# "cdp", +# "fdp" +# ] +# } +# { +# "enable": true +# } +# ] +# +# After state: +# ------------- +# +# set service lldp legacy-protocols cdp +# set service lldp legacy-protocols fdp +# set service lldp management-address '192.0.2.11' +# set service lldp snmp enable + + +# Using replaced +# +# Before state: +# ------------- +# +# vyos@vyos:~$ show configuration commands | grep lldp +# set service lldp legacy-protocols cdp +# set service lldp legacy-protocols fdp +# set service lldp management-address '192.0.2.11' +# set service lldp snmp enable +# +- name: Replace device configurations with provided configurations + vyos_lldp_global: + config: + legacy_protocols: + - 'edp' + - 'sonmp' + - 'cdp' + address: 192.0.2.14 + state: replaced +# +# +# ------------------------ +# Module Execution Results +# ------------------------ +# +# +# "before": [ +# { +# "snmp": "enable" +# }, +# { +# "address": "192.0.2.11" +# }, +# { +# "legacy_protocols": [ +# "cdp", +# "fdp" +# ] +# } +# { +# "enable": true +# } +# ] +# "commands": [ +# "delete service lldp snmp", +# "delete service lldp legacy-protocols fdp", +# "set service lldp management-address '192.0.2.14'", +# "set service lldp legacy-protocols edp", +# "set service lldp legacy-protocols sonmp" +# ] +# +# "after": [ +# { +# "address": "192.0.2.14" +# }, +# { +# "legacy_protocols": [ +# "cdp", +# "edp", +# "sonmp" +# ] +# } +# { +# "enable": true +# } +# ] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands|grep lldp +# set service lldp legacy-protocols cdp +# set service lldp legacy-protocols edp +# set service lldp legacy-protocols sonmp +# set service lldp management-address '192.0.2.14' + + +# Using deleted +# +# Before state +# ------------- +# vyos@vyos:~$ show configuration commands|grep lldp +# set service lldp legacy-protocols cdp +# set service lldp legacy-protocols edp +# set service lldp legacy-protocols sonmp +# set service lldp management-address '192.0.2.14' +# +- name: Delete attributes of given lldp service (This won't delete the LLDP service itself) + vyos_lldp_global: + config: + state: deleted +# +# +# ------------------------ +# Module Execution Results +# ------------------------ +# +# "before": [ +# { +# "address": "192.0.2.14" +# }, +# { +# "legacy_protocols": [ +# "cdp", +# "edp", +# "sonmp" +# ] +# } +# { +# "enable": true +# } +# ] +# +# "commands": [ +# "delete service lldp management-address", +# "delete service lldp legacy-protocols" +# ] +# +# "after": [ +# { +# "enable": true +# } +# ] +# +# After state +# ------------ +# vyos@vyos:~$ show configuration commands | grep lldp +# set service lldp + + +""" +RETURN = """ +before: + description: The configuration prior to the model invocation. + returned: always + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +after: + description: The resulting configuration model invocation. + returned: when changed + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +commands: + description: The set of commands pushed to the remote device. + returned: always + type: list + sample: + - set service lldp legacy-protocols sonmp + - set service lldp management-address '192.0.2.14' +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_global.lldp_global import ( + Lldp_globalArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.lldp_global.lldp_global import ( + Lldp_global, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + required_if = [ + ("state", "merged", ("config",)), + ("state", "replaced", ("config",)), + ] + module = AnsibleModule( + argument_spec=Lldp_globalArgs.argument_spec, + required_if=required_if, + supports_check_mode=True, + ) + + result = Lldp_global(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/test/integration/targets/vyos_lldp_global/defaults/main.yaml b/test/integration/targets/vyos_lldp_global/defaults/main.yaml new file mode 100644 index 0000000..164afea --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/test/integration/targets/vyos_lldp_global/tasks/cli.yaml b/test/integration/targets/vyos_lldp_global/tasks/cli.yaml new file mode 100644 index 0000000..655e51e --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tasks/cli.yaml @@ -0,0 +1,19 @@ +--- +- name: Collect all cli test cases + find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=network_cli) + include: "{{ test_case_to_run }}" + vars: + ansible_connection: network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/vyos_lldp_global/tasks/main.yaml b/test/integration/targets/vyos_lldp_global/tasks/main.yaml new file mode 100644 index 0000000..415c99d --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tasks/main.yaml @@ -0,0 +1,2 @@ +--- +- { include: cli.yaml, tags: ['cli'] } diff --git a/test/integration/targets/vyos_lldp_global/tests/cli/_populate.yaml b/test/integration/targets/vyos_lldp_global/tests/cli/_populate.yaml new file mode 100644 index 0000000..088aa7b --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tests/cli/_populate.yaml @@ -0,0 +1,9 @@ +--- +- name: Setup + network.cli.cli_config: + config: "{{ lines }}" + vars: + lines: | + set service lldp + set service lldp legacy-protocols 'cdp' + set service lldp management-address '192.0.2.17' diff --git a/test/integration/targets/vyos_lldp_global/tests/cli/_remove_config.yaml b/test/integration/targets/vyos_lldp_global/tests/cli/_remove_config.yaml new file mode 100644 index 0000000..b000a94 --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tests/cli/_remove_config.yaml @@ -0,0 +1,9 @@ +--- +- name: Remove Config + network.cli.cli_config: + config: "{{ lines }}" + vars: + lines: | + delete service lldp legacy-protocols + delete service lldp management-address + delete service lldp diff --git a/test/integration/targets/vyos_lldp_global/tests/cli/deleted.yaml b/test/integration/targets/vyos_lldp_global/tests/cli/deleted.yaml new file mode 100644 index 0000000..79660af --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tests/cli/deleted.yaml @@ -0,0 +1,44 @@ +--- +- debug: + msg: "Start vyos_lldp_global deleted integration tests ansible_connection={{ ansible_connection }}" + +- include_tasks: _populate.yaml + +- block: + - name: Delete attributes of LLDP service. + vyos.vyos.vyos_lldp_global: &deleted + config: + state: deleted + register: result + + - name: Assert that the before dicts were correctly generated + assert: + that: + - "{{ populate == result['before']}}" + + - name: Assert that the correct set of commands were generated + assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + assert: + that: + - "{{ deleted['after'] == result['after']}}" + + - name: Delete attributes of given interfaces (IDEMPOTENT) + vyos.vyos.vyos_lldp_global: *deleted + register: result + + - name: Assert that the previous task was idempotent + assert: + that: + - "result.changed == false" + + - name: Assert that the before dicts were correctly generated + assert: + that: + - "{{ deleted['after'] == result['before'] }}" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/vyos_lldp_global/tests/cli/merged.yaml b/test/integration/targets/vyos_lldp_global/tests/cli/merged.yaml new file mode 100644 index 0000000..b1687da --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tests/cli/merged.yaml @@ -0,0 +1,49 @@ +--- +- debug: + msg: "START vyos_lldp_global merged integration tests on connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + - name: Merge the provided configuration with the exisiting running configuration + vyos.vyos.vyos_lldp_global: &merged + config: + legacy_protocols: + - 'fdp' + - 'cdp' + address: 192.0.2.11 + state: merged + register: result + + - name: Assert that before dicts were correctly generated + assert: + that: "{{ merged['before'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + assert: + that: + - "{{ merged['after'] == result['after'] }}" + + - name: Merge the provided configuration with the existing running configuration (IDEMPOTENT) + vyos.vyos.vyos_lldp_global: *merged + register: result + + - name: Assert that the previous task was idempotent + assert: + that: + - "result['changed'] == false" + + - name: Assert that before dicts were correctly generated + assert: + that: + - "{{ merged['after'] == result['before'] }}" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/vyos_lldp_global/tests/cli/replaced.yaml b/test/integration/targets/vyos_lldp_global/tests/cli/replaced.yaml new file mode 100644 index 0000000..22bd8e5 --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tests/cli/replaced.yaml @@ -0,0 +1,51 @@ +--- +- debug: + msg: "START vyos_lldp_global replaced integration tests on connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + - name: Replace device configurations of LLDP service with provided configurations + vyos.vyos.vyos_lldp_global: &replaced + config: + legacy_protocols: + - 'edp' + - 'sonmp' + - 'cdp' + address: 192.0.2.14 + state: replaced + register: result + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + assert: + that: + - "{{ populate == result['before'] }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ replaced['after'] == result['after'] }}" + + - name: Replace device configurations of LLDP service with provided configurarions (IDEMPOTENT) + vyos.vyos.vyos_lldp_global: *replaced + register: result + + - name: Assert that task was idempotent + assert: + that: + - "result['changed'] == false" + + - name: Assert that before dict is correctly generated + assert: + that: + - "{{ replaced['after'] == result['before'] }}" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/vyos_lldp_global/tests/cli/rtt.yaml b/test/integration/targets/vyos_lldp_global/tests/cli/rtt.yaml new file mode 100644 index 0000000..4f8ca9c --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/tests/cli/rtt.yaml @@ -0,0 +1,51 @@ +--- +- debug: + msg: "START vyos_lldp_global round trip integration tests on connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- block: + - name: Apply the provided configuration (base config) + vyos.vyos.vyos_lldp_global: + config: + legacy_protocols: + - 'fdp' + - 'cdp' + address: 192.0.2.11 + state: merged + register: base_config + + - name: Gather vyos_lldp_global facts + vyos.vyos.vyos_facts: + gather_subset: + - default + gather_network_resources: + - lldp_global + + - name: Apply the provided configuration (config to be reverted) + vyos.vyos.vyos_lldp_global: + config: + legacy_protocols: + - 'edp' + - 'sonmp' + - 'cdp' + address: 192.0.2.14 + state: merged + register: result + + - name: Assert that changes were applied + assert: + that: "{{ round_trip['after'] == result['after'] }}" + + - name: Revert back to base config using facts round trip + vyos.vyos.vyos_lldp_global: + config: "{{ ansible_facts['network_resources']['lldp_global'] }}" + state: replaced + register: revert + + - name: Assert that config was reverted + assert: + that: "{{ base_config['after'] == revert['after'] }}" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/vyos_lldp_global/vars/main.yaml b/test/integration/targets/vyos_lldp_global/vars/main.yaml new file mode 100644 index 0000000..f091f2c --- /dev/null +++ b/test/integration/targets/vyos_lldp_global/vars/main.yaml @@ -0,0 +1,56 @@ +--- +merged: + before: + address: '192.0.2.17' + enable: true + legacy_protocols: + - 'cdp' + + commands: + - "set service lldp management-address '192.0.2.11'" + - "set service lldp legacy-protocols 'fdp'" + + after: + address: '192.0.2.11' + enable: true + legacy_protocols: + - 'cdp' + - 'fdp' + +populate: + address: '192.0.2.17' + enable: true + legacy_protocols: + - 'cdp' + +replaced: + commands: + - "set service lldp legacy-protocols 'edp'" + - "set service lldp legacy-protocols 'sonmp'" + - "set service lldp management-address '192.0.2.14'" + + after: + address: '192.0.2.14' + enable: true + legacy_protocols: + - 'cdp' + - 'edp' + - 'sonmp' + +deleted: + commands: + - "delete service lldp management-address" + - "delete service lldp legacy-protocols" + + after: + "enable": true + +round_trip: + after: + address: '192.0.2.14' + enable: true + legacy_protocols: + - 'cdp' + - 'edp' + - 'fdp' + - 'sonmp' |