diff options
9 files changed, 395 insertions, 37 deletions
| diff --git a/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py index 2976fc09..109ea430 100644 --- a/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py +++ b/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py @@ -81,8 +81,17 @@ class Lldp_interfacesArgs(object):  # pylint: disable=R0903              },              "type": "list",          }, +        "running_config": {"type": "str"},          "state": { -            "choices": ["merged", "replaced", "overridden", "deleted"], +            "choices": [ +                "merged", +                "replaced", +                "overridden", +                "deleted", +                "rendered", +                "gathered", +                "parsed", +            ],              "default": "merged",              "type": "str",          }, diff --git a/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py index 377fec9a..94e39c35 100644 --- a/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py +++ b/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py @@ -15,7 +15,6 @@ from __future__ import absolute_import, division, print_function  __metaclass__ = type -  from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (      ConfigBase,  ) @@ -54,14 +53,14 @@ class Lldp_interfaces(ConfigBase):      def __init__(self, module):          super(Lldp_interfaces, self).__init__(module) -    def get_lldp_interfaces_facts(self): +    def get_lldp_interfaces_facts(self, data=None):          """ 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 +            self.gather_subset, self.gather_network_resources, data=data          )          lldp_interfaces_facts = facts["ansible_network_resources"].get(              "lldp_interfaces" @@ -77,26 +76,47 @@ class Lldp_interfaces(ConfigBase):          :returns: The result from module execution          """          result = {"changed": False} -        commands = list()          warnings = list() -        existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts() -        commands.extend(self.set_config(existing_lldp_interfaces_facts)) -        if commands: -            if self._module.check_mode: -                resp = self._connection.edit_config(commands, commit=False) -            else: -                resp = self._connection.edit_config(commands) -            result["changed"] = True +        commands = list() + +        if self.state in self.ACTION_STATES: +            existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts() +        else: +            existing_lldp_interfaces_facts = [] -        result["commands"] = commands +        if self.state in self.ACTION_STATES or self.state == "rendered": +            commands.extend(self.set_config(existing_lldp_interfaces_facts)) -        if self._module._diff: -            result["diff"] = resp["diff"] if result["changed"] else None +        if commands and self.state in self.ACTION_STATES: +            if not self._module.check_mode: +                self._connection.edit_config(commands) +            result["changed"] = True -        changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts() -        result["before"] = existing_lldp_interfaces_facts -        if result["changed"]: -            result["after"] = changed_lldp_interfaces_facts +        if self.state in self.ACTION_STATES: +            result["commands"] = commands + +        if self.state in self.ACTION_STATES or self.state == "gathered": +            changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts() +        elif self.state == "rendered": +            result["rendered"] = commands +        elif self.state == "parsed": +            running_config = self._module.params["running_config"] +            if not running_config: +                self._module.fail_json( +                    msg="value of running_config parameter must not be empty for state parsed" +                ) +            result["parsed"] = self.get_lldp_interfaces_facts( +                data=running_config +            ) +        else: +            changed_lldp_interfaces_facts = [] + +        if self.state in self.ACTION_STATES: +            result["before"] = existing_lldp_interfaces_facts +            if result["changed"]: +                result["after"] = changed_lldp_interfaces_facts +        elif self.state == "gathered": +            result["gathered"] = changed_lldp_interfaces_facts          result["warnings"] = warnings          return result @@ -124,16 +144,18 @@ class Lldp_interfaces(ConfigBase):                    to the desired configuration          """          commands = [] -        state = self._module.params["state"] -        if state in ("merged", "replaced", "overridden") and not want: +        if ( +            self.state in ("merged", "replaced", "overridden", "rendered") +            and not want +        ):              self._module.fail_json(                  msg="value of config parameter must not be empty for state {0}".format( -                    state +                    self.state                  )              ) -        if state == "overridden": +        if self.state == "overridden":              commands.extend(self._state_overridden(want=want, have=have)) -        elif state == "deleted": +        elif self.state == "deleted":              if want:                  for item in want:                      name = item["name"] @@ -150,11 +172,11 @@ class Lldp_interfaces(ConfigBase):              for want_item in want:                  name = want_item["name"]                  have_item = search_obj_in_list(name, have) -                if state == "merged": +                if self.state in ("merged", "rendered"):                      commands.extend(                          self._state_merged(want=want_item, have=have_item)                      ) -                else: +                if self.state == "replaced":                      commands.extend(                          self._state_replaced(want=want_item, have=have_item)                      ) @@ -243,7 +265,6 @@ class Lldp_interfaces(ConfigBase):          lldp_name = want["name"]          params = Lldp_interfaces.params -        commands.extend(self._add_location(lldp_name, want, have))          for attrib in params:              value = want[attrib]              if value: diff --git a/plugins/modules/vyos_lldp_interfaces.py b/plugins/modules/vyos_lldp_interfaces.py index 8fe572b0..34ceb66b 100644 --- a/plugins/modules/vyos_lldp_interfaces.py +++ b/plugins/modules/vyos_lldp_interfaces.py @@ -37,7 +37,7 @@ ANSIBLE_METADATA = {  }  DOCUMENTATION = """module: vyos_lldp_interfaces -short_description: Manages attributes of lldp interfaces on VyOS devices. +short_description: LLDP interfaces resource module  description: This module manages attributes of lldp interfaces on VyOS network devices.  notes:  - Tested against VyOS 1.1.8 (helium). @@ -111,6 +111,15 @@ options:            elin:              description: Emergency Call Service ELIN number (between 10-25 numbers).              type: str +  running_config: +    description: +      - This option is used only with state I(parsed). +      - The value of this option should be the output received from the VyOS device by executing +        the command B(show configuration commands | grep lldp). +      - The state I(parsed) reads the configuration from C(running_config) option and transforms +        it into Ansible structured data as per the resource module's argspec and the value is then +        returned in the I(parsed) key within the result. +    type: str    state:      description:      - The state of the configuration after module completion. @@ -120,6 +129,9 @@ options:      - replaced      - overridden      - deleted +    - rendered +    - parsed +    - gathered      default: merged  """  EXAMPLES = """ @@ -131,7 +143,7 @@ EXAMPLES = """  # vyos@vyos:~$ show configuration  commands | grep lldp  #  - name: Merge provided configuration with device configuration -  vyos_lldp_interfaces: +  vyos.vyos.vyos_lldp_interfaces:      config:        - name: 'eth1'          location: @@ -225,7 +237,7 @@ EXAMPLES = """  # set service lldp interface eth2 location coordinate-based longitude '222.267255W'  #  - name: Replace device configurations of listed LLDP interfaces with provided configurations -  vyos_lldp_interfaces: +  vyos.vyos.vyos_lldp_interfaces:      config:        - name: 'eth2'          location: @@ -348,7 +360,7 @@ EXAMPLES = """  # set service lldp interface eth2 location civic-based country-code 'US'  #  - name: Overrides all device configuration with provided configuration -  vyos_lag_interfaces: +  vyos.vyos.vyos_lldp_interfaces:      config:       - name: 'eth2'         location: @@ -423,7 +435,7 @@ EXAMPLES = """  # set service lldp interface eth2 location elin '0000000911'  #  - name: Delete lldp  interface attributes of given interfaces. -  vyos_lag_interfaces: +  vyos.vyos.vyos_lldp_interfaces:      config:       - name: 'eth2'      state: deleted @@ -453,6 +465,159 @@ EXAMPLES = """  # set service 'lldp' +# Using gathered +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep lldp +# set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH' +# set service lldp interface eth1 location civic-based country-code 'US' +# set service lldp interface eth2 location coordinate-based altitude '2200' +# set service lldp interface eth2 location coordinate-based datum 'WGS84' +# set service lldp interface eth2 location coordinate-based latitude '33.524449N' +# set service lldp interface eth2 location coordinate-based longitude '222.267255W' +# +- name: Gather listed lldp interfaces from running configuration +  vyos.vyos.vyos_lldp_interfaces: +    config: +    state: gathered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +#    "gathered": [ +#         { +#             "location": { +#                 "coordinate_based": { +#                     "altitude": 2200, +#                     "datum": "WGS84", +#                     "latitude": "33.524449N", +#                     "longitude": "222.267255W" +#                 } +#             }, +#             "name": "eth2" +#         }, +#         { +#             "location": { +#                 "civic_based": { +#                     "ca_info": [ +#                         { +#                             "ca_type": 0, +#                             "ca_value": "ENGLISH" +#                         } +#                     ], +#                     "country_code": "US" +#                 } +#             }, +#             "name": "eth1" +#         } +#     ] +# +# +# After state: +# ------------- +# +# vyos@192# run show configuration commands | grep lldp +# set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH' +# set service lldp interface eth1 location civic-based country-code 'US' +# set service lldp interface eth2 location coordinate-based altitude '2200' +# set service lldp interface eth2 location coordinate-based datum 'WGS84' +# set service lldp interface eth2 location coordinate-based latitude '33.524449N' +# set service lldp interface eth2 location coordinate-based longitude '222.267255W' + + +# Using rendered +# +# +- name: Render the commands for provided  configuration +  vyos.vyos.vyos_lldp_interfaces: +    config: +          - name: eth1 +            location: +              civic_based: +                country_code: US +                ca_info: +                  - ca_type: 0 +                    ca_value: ENGLISH +          - name: eth2 +            location: +              coordinate_based: +                altitude: 2200 +                datum: WGS84 +                longitude: 222.267255W +                latitude: 33.524449N +    state: rendered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "rendered": [ +#         "set service lldp interface eth1 location civic-based country-code 'US'", +#         "set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH'", +#         "set service lldp interface eth1", +#         "set service lldp interface eth2 location coordinate-based latitude '33.524449N'", +#         "set service lldp interface eth2 location coordinate-based altitude '2200'", +#         "set service lldp interface eth2 location coordinate-based datum 'WGS84'", +#         "set service lldp interface eth2 location coordinate-based longitude '222.267255W'", +#         "set service lldp interface eth2" +#     ] + + +# Using parsed +# +# +- name: Parsed the commands to provide structured configuration. +  vyos.vyos.vyos_lldp_interfaces: +    running_config: +      "set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH' + set service lldp interface eth1 location civic-based country-code 'US' + set service lldp interface eth2 location coordinate-based altitude '2200' + set service lldp interface eth2 location coordinate-based datum 'WGS84' + set service lldp interface eth2 location coordinate-based latitude '33.524449N' + set service lldp interface eth2 location coordinate-based longitude '222.267255W'" +    state: parsed +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "parsed": [ +#         { +#             "location": { +#                 "coordinate_based": { +#                     "altitude": 2200, +#                     "datum": "WGS84", +#                     "latitude": "33.524449N", +#                     "longitude": "222.267255W" +#                 } +#             }, +#             "name": "eth2" +#         }, +#         { +#             "location": { +#                 "civic_based": { +#                     "ca_info": [ +#                         { +#                             "ca_type": 0, +#                             "ca_value": "ENGLISH" +#                         } +#                     ], +#                     "country_code": "US" +#                 } +#             }, +#             "name": "eth1" +#         } +#     ] + +  """  RETURN = """  before: @@ -497,12 +662,17 @@ def main():      required_if = [          ("state", "merged", ("config",)),          ("state", "replaced", ("config",)), +        ("state", "rendered", ("config",)),          ("state", "overridden", ("config",)), +        ("state", "parsed", ("running_config",)),      ] +    mutually_exclusive = [("config", "running_config")] +      module = AnsibleModule(          argument_spec=Lldp_interfacesArgs.argument_spec,          required_if=required_if,          supports_check_mode=True, +        mutually_exclusive=mutually_exclusive,      )      result = Lldp_interfaces(module).execute_module() diff --git a/tests/integration/targets/vyos_lldp_interfaces/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/_parsed_config.cfg new file mode 100644 index 00000000..40c96c40 --- /dev/null +++ b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/_parsed_config.cfg @@ -0,0 +1,6 @@ +set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH' +set service lldp interface eth1 location civic-based country-code 'US' +set service lldp interface eth2 location coordinate-based altitude '2200' +set service lldp interface eth2 location coordinate-based datum 'WGS84' +set service lldp interface eth2 location coordinate-based latitude '33.524449N' +set service lldp interface eth2 location coordinate-based longitude '222.267255W'
\ No newline at end of file diff --git a/tests/integration/targets/vyos_lldp_interfaces/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/empty_config.yaml index a5ff0a8e..4ef40c9e 100644 --- a/tests/integration/targets/vyos_lldp_interfaces/tests/cli/empty_config.yaml +++ b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/empty_config.yaml @@ -35,3 +35,26 @@  - assert:      that:        - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Parsed with empty running_config should give appropriate error message +  register: result +  ignore_errors: true +  vyos.vyos.vyos_lldp_interfaces: +    running_config: +    state: parsed + +- assert: +    that: +      - result.msg == 'value of running_config parameter must not be empty for state +        parsed' + +- name: Rendered with empty config should give appropriate error message +  register: result +  ignore_errors: true +  vyos.vyos.vyos_lldp_interfaces: +    config: +    state: rendered + +- assert: +    that: +      - result.msg == 'value of config parameter must not be empty for state rendered' diff --git a/tests/integration/targets/vyos_lldp_interfaces/tests/cli/gathered.yaml b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..d440b534 --- /dev/null +++ b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,34 @@ +--- +- debug: +    msg: START vyos_lldp_interfaces gathered 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 +      register: result +      vyos.vyos.vyos_lldp_interfaces: &id001 +        config: +        state: gathered + +    - name: Assert that gathered dicts was correctly generated +      assert: +        that: +          - "{{ populate | symmetric_difference(result['gathered']) |length == 0\ +            \ }}" + +    - name: Gather the existing running configuration (IDEMPOTENT) +      register: result +      vyos.vyos.vyos_lldp_interfaces: *id001 + +    - name: Assert that the previous task was idempotent +      assert: +        that: +          - result['changed'] == false +  always: + +    - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_lldp_interfaces/tests/cli/parsed.yaml b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..7842152f --- /dev/null +++ b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,41 @@ +--- +- debug: +    msg: START vyos_lldp_interfaces parsed integration tests on connection={{ ansible_connection +      }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + +    - name: Gather lldp_interfaces facts +      register: lldp_interfaces_facts +      vyos.vyos.vyos_facts: +        gather_subset: +          - default +        gather_network_resources: +          - lldp_interfaces + +    - name: Provide the running configuration for parsing (config to be parsed) +      register: result +      vyos.vyos.vyos_lldp_interfaces: &id001 +        running_config: "{{ lookup('file', '_parsed_config.cfg') }}" +        state: parsed + +    - name: Assert that correct parsing done +      assert: +        that: "{{ ansible_facts['network_resources']['lldp_interfaces'] | symmetric_difference(result['parsed'])\ +          \ |length == 0 }}" + +    - name: Gather the existing running configuration (IDEMPOTENT) +      register: result +      vyos.vyos.vyos_lldp_interfaces: *id001 + +    - name: Assert that the previous task was idempotent +      assert: +        that: +          - result['changed'] == false +  always: + +    - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_lldp_interfaces/tests/cli/rendered.yaml b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..6bb9f5a0 --- /dev/null +++ b/tests/integration/targets/vyos_lldp_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,48 @@ +--- +- debug: +    msg: START vyos_lldp_interfaces rendered integration tests on connection={{ ansible_connection +      }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + +    - name: Structure provided configuration into device specific commands +      register: result +      vyos.vyos.vyos_lldp_interfaces: &id001 +        config: +          - name: eth1 +            location: +              civic_based: +                country_code: US +                ca_info: +                  - ca_type: 0 +                    ca_value: ENGLISH +          - name: eth2 +            location: +              coordinate_based: +                altitude: 2200 +                datum: WGS84 +                longitude: 222.267255W +                latitude: 33.524449N +        state: rendered + +    - name: Assert that correct set of commands were generated +      assert: +        that: +          - "{{ rendered['commands'] | symmetric_difference(result['rendered'])\ +            \ |length == 0 }}" + +    - name: Structure provided configuration into device specific commands (IDEMPOTENT) +      register: result +      vyos.vyos.vyos_lldp_interfaces: *id001 + +    - name: Assert that the previous task was idempotent +      assert: +        that: +          - result['changed'] == false +  always: + +    - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_lldp_interfaces/vars/main.yaml b/tests/integration/targets/vyos_lldp_interfaces/vars/main.yaml index 3cb684ea..506bdf70 100644 --- a/tests/integration/targets/vyos_lldp_interfaces/vars/main.yaml +++ b/tests/integration/targets/vyos_lldp_interfaces/vars/main.yaml @@ -9,10 +9,6 @@ merged:      - set service lldp interface eth2 location coordinate-based altitude '2200'      - set service lldp interface eth2 location coordinate-based datum 'WGS84'      - set service lldp interface eth2 location coordinate-based longitude '222.267255W' -    - set service lldp interface eth2 location coordinate-based latitude '33.524449N' -    - set service lldp interface eth2 location coordinate-based altitude '2200' -    - set service lldp interface eth2 location coordinate-based datum 'WGS84' -    - set service lldp interface eth2 location coordinate-based longitude '222.267255W'      - set service lldp interface eth2    after:      - name: eth1 @@ -44,6 +40,16 @@ populate:          datum: WGS84          longitude: 222.267255W          latitude: 33.524449N +rendered: +  commands: +    - set service lldp interface eth1 location civic-based country-code 'US' +    - set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH' +    - set service lldp interface eth1 +    - set service lldp interface eth2 location coordinate-based latitude '33.524449N' +    - set service lldp interface eth2 location coordinate-based altitude '2200' +    - set service lldp interface eth2 location coordinate-based datum 'WGS84' +    - set service lldp interface eth2 location coordinate-based longitude '222.267255W' +    - set service lldp interface eth2  replaced:    commands:      - delete service lldp interface eth2 location | 
