diff options
author | Rohit Thakur <rohitthakur2590@outlook.com> | 2020-04-29 23:59:44 +0530 |
---|---|---|
committer | Rohit Thakur <rohitthakur2590@outlook.com> | 2020-04-29 23:59:44 +0530 |
commit | d14344f56803e0564f273e9451a76ef84f8b1313 (patch) | |
tree | 675d749d2ac9d3570ad78f28a2c5377c38b8801e | |
parent | 77e8b041b2983415ac36eb6264f6e385ac87b074 (diff) | |
download | vyos-ansible-collection-d14344f56803e0564f273e9451a76ef84f8b1313.tar.gz vyos-ansible-collection-d14344f56803e0564f273e9451a76ef84f8b1313.zip |
new states added
Signed-off-by: Rohit Thakur <rohitthakur2590@outlook.com>
10 files changed, 446 insertions, 49 deletions
diff --git a/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py b/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py index 97c5d5a..6cfdabf 100644 --- a/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py +++ b/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py @@ -19,7 +19,6 @@ # builder template. # ############################################# - """ The arg spec for the vyos_lag_interfaces module """ @@ -72,8 +71,17 @@ class Lag_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/lag_interfaces/lag_interfaces.py b/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py index 2a9efd9..452670f 100644 --- a/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py +++ b/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py @@ -56,14 +56,14 @@ class Lag_interfaces(ConfigBase): def __init__(self, module): super(Lag_interfaces, self).__init__(module) - def get_lag_interfaces_facts(self): + def get_lag_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 ) lag_interfaces_facts = facts["ansible_network_resources"].get( "lag_interfaces" @@ -79,27 +79,47 @@ class Lag_interfaces(ConfigBase): :returns: The result from module execution """ result = {"changed": False} - commands = list() warnings = list() - existing_lag_interfaces_facts = self.get_lag_interfaces_facts() - commands.extend(self.set_config(existing_lag_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_lag_interfaces_facts = self.get_lag_interfaces_facts() + else: + existing_lag_interfaces_facts = [] - result["commands"] = commands + if self.state in self.ACTION_STATES or self.state == "rendered": + commands.extend(self.set_config(existing_lag_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_lag_interfaces_facts = self.get_lag_interfaces_facts() + if self.state in self.ACTION_STATES: + result["commands"] = commands + + if self.state in self.ACTION_STATES or self.state == "gathered": + changed_lag_interfaces_facts = self.get_lag_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_lag_interfaces_facts( + data=running_config + ) + else: + changed_lag_interfaces_facts = [] - result["before"] = existing_lag_interfaces_facts - if result["changed"]: - result["after"] = changed_lag_interfaces_facts + if self.state in self.ACTION_STATES: + result["before"] = existing_lag_interfaces_facts + if result["changed"]: + result["after"] = changed_lag_interfaces_facts + elif self.state == "gathered": + result["gathered"] = changed_lag_interfaces_facts result["warnings"] = warnings return result @@ -127,16 +147,18 @@ class Lag_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, have)) - elif state == "deleted": + elif self.state == "deleted": if want: for want_item in want: name = want_item["name"] @@ -149,9 +171,9 @@ class Lag_interfaces(ConfigBase): for want_item in want: name = want_item["name"] obj_in_have = search_obj_in_list(name, have) - if state == "merged": + if self.state in ("merged", "rendered"): commands.extend(self._state_merged(want_item, obj_in_have)) - elif state == "replaced": + elif self.state == "replaced": commands.extend( self._state_replaced(want_item, obj_in_have) ) diff --git a/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py b/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py index 9201e5c..9056294 100644 --- a/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py @@ -12,6 +12,7 @@ based on the configuration. from __future__ import absolute_import, division, print_function __metaclass__ = type + from re import findall, search, M from copy import deepcopy @@ -59,30 +60,21 @@ class Lag_interfacesFacts(object): lag_regex = r" %s .+$" % lag cfg = findall(lag_regex, data, M) obj = self.render_config(cfg) - - output = connection.run_commands( - ["show interfaces bonding " + lag + " slaves"] - ) - lines = output[0].splitlines() members = [] member = {} - if len(lines) > 1: - for line in lines[2:]: - splitted_line = line.split() - - if len(splitted_line) > 1: - member["member"] = splitted_line[0] - members.append(member) - else: - members = [] - member = {} + + group_regex = r".*eth.* '%s'" % lag + g_cfg = findall(group_regex, data, M) + for item in g_cfg: + output = search("^set interfaces ethernet (\\S+)", item, M) + if output: + member["member"] = output.group(1).strip("'") + members.append(member) obj["name"] = lag.strip("'") if members: obj["members"] = members - if obj: objs.append(obj) - facts = {} if objs: facts["lag_interfaces"] = [] diff --git a/plugins/modules/vyos_lag_interfaces.py b/plugins/modules/vyos_lag_interfaces.py index 84f3d01..a034d40 100644 --- a/plugins/modules/vyos_lag_interfaces.py +++ b/plugins/modules/vyos_lag_interfaces.py @@ -37,7 +37,7 @@ ANSIBLE_METADATA = { } DOCUMENTATION = """module: vyos_lag_interfaces -short_description: Manages attributes of link aggregation groups on VyOS network devices. +short_description: LAG interfaces resource module description: This module manages attributes of link aggregation groups on VyOS network devices. notes: @@ -100,6 +100,15 @@ options: description: - IP address to use for ARP monitoring. type: list + 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 bond). + - 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. @@ -109,6 +118,9 @@ options: - replaced - overridden - deleted + - parsed + - gathered + - rendered default: merged """ EXAMPLES = """ @@ -122,7 +134,7 @@ EXAMPLES = """ # set interfaces bonding bond3 # - name: Merge provided configuration with device configuration - vyos_lag_interfaces: + vyos.vyos.vyos_lag_interfaces: config: - name: bond2 mode: active-backup @@ -226,7 +238,7 @@ EXAMPLES = """ # set interfaces ethernet eth3 bond-group 'bond3' # - name: Replace device configurations of listed LAGs with provided configurations - vyos_lag_interfaces: + vyos.vyos.vyos_lag_interfaces: config: - name: bond3 mode: '802.3ad' @@ -331,7 +343,7 @@ EXAMPLES = """ # set interfaces ethernet eth3 bond-group 'bond3' # - name: Overrides all device configuration with provided configuration - vyos_lag_interfaces: + vyos.vyos.vyos_lag_interfaces: config: - name: bond3 mode: active-backup @@ -441,7 +453,7 @@ EXAMPLES = """ # set interfaces ethernet eth3 bond-group 'bond3' # - name: Delete LAG attributes of given interfaces (Note This won't delete the interface itself) - vyos_lag_interfaces: + vyos.vyos.vyos_lag_interfaces: config: - name: bond2 - name: bond3 @@ -507,6 +519,202 @@ EXAMPLES = """ # set interfaces bonding bond3 +# Using gathered +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep bond +# set interfaces bonding bond0 hash-policy 'layer2' +# set interfaces bonding bond0 mode 'active-backup' +# set interfaces bonding bond0 primary 'eth1' +# set interfaces bonding bond1 hash-policy 'layer2+3' +# set interfaces bonding bond1 mode 'active-backup' +# set interfaces bonding bond1 primary 'eth2' +# set interfaces ethernet eth1 bond-group 'bond0' +# set interfaces ethernet eth2 bond-group 'bond1' +# +- name: Gather listed lag interfaces with provided configurations + vyos.vyos.vyos_lag_interfaces: + config: + state: gathered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# "gathered": [ +# { +# "afi": "ipv6", +# "rule_sets": [ +# { +# "default_action": "accept", +# "description": "This is ipv6 specific rule-set", +# "name": "UPLINK", +# "rules": [ +# { +# "action": "accept", +# "description": "Fwipv6-Rule 1 is configured by Ansible", +# "ipsec": "match-ipsec", +# "number": 1 +# }, +# { +# "action": "accept", +# "description": "Fwipv6-Rule 2 is configured by Ansible", +# "ipsec": "match-ipsec", +# "number": 2 +# } +# ] +# } +# ] +# }, +# { +# "afi": "ipv4", +# "rule_sets": [ +# { +# "default_action": "accept", +# "description": "IPv4 INBOUND rule set", +# "name": "INBOUND", +# "rules": [ +# { +# "action": "accept", +# "description": "Rule 101 is configured by Ansible", +# "ipsec": "match-ipsec", +# "number": 101 +# }, +# { +# "action": "reject", +# "description": "Rule 102 is configured by Ansible", +# "ipsec": "match-ipsec", +# "number": 102 +# }, +# { +# "action": "accept", +# "description": "Rule 103 is configured by Ansible", +# "destination": { +# "group": { +# "address_group": "inbound" +# } +# }, +# "number": 103, +# "source": { +# "address": "192.0.2.0" +# }, +# "state": { +# "established": true, +# "invalid": false, +# "new": false, +# "related": true +# } +# } +# ] +# } +# ] +# } +# ] +# +# +# After state: +# ------------- +# +# vyos@192# run show configuration commands | grep bond +# set interfaces bonding bond0 hash-policy 'layer2' +# set interfaces bonding bond0 mode 'active-backup' +# set interfaces bonding bond0 primary 'eth1' +# set interfaces bonding bond1 hash-policy 'layer2+3' +# set interfaces bonding bond1 mode 'active-backup' +# set interfaces bonding bond1 primary 'eth2' +# set interfaces ethernet eth1 bond-group 'bond0' +# set interfaces ethernet eth2 bond-group 'bond1' + + +# Using rendered +# +# +- name: Render the commands for provided configuration + vyos.vyos.vyos_lag_interfaces: + config: + - name: bond0 + hash_policy: layer2 + members: + - member: eth1 + mode: active-backup + primary: eth1 + - name: bond1 + hash_policy: layer2+3 + members: + - member: eth2 + mode: active-backup + primary: eth2 + state: rendered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "rendered": [ +# "set interfaces bonding bond0 hash-policy 'layer2'", +# "set interfaces ethernet eth1 bond-group 'bond0'", +# "set interfaces bonding bond0 mode 'active-backup'", +# "set interfaces bonding bond0 primary 'eth1'", +# "set interfaces bonding bond1 hash-policy 'layer2+3'", +# "set interfaces ethernet eth2 bond-group 'bond1'", +# "set interfaces bonding bond1 mode 'active-backup'", +# "set interfaces bonding bond1 primary 'eth2'" +# ] + + +# Using parsed +# +# +- name: Parsed the commands for provided configuration + vyos.vyos.vyos_l3_interfaces: + running_config: + "set interfaces bonding bond0 hash-policy 'layer2' + set interfaces bonding bond0 mode 'active-backup' + set interfaces bonding bond0 primary 'eth1' + set interfaces bonding bond1 hash-policy 'layer2+3' + set interfaces bonding bond1 mode 'active-backup' + set interfaces bonding bond1 primary 'eth2' + set interfaces ethernet eth1 bond-group 'bond0' + set interfaces ethernet eth2 bond-group 'bond1'" + state: parsed +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "parsed": [ +# { +# "hash_policy": "layer2", +# "members": [ +# { +# "member": "eth1" +# } +# ], +# "mode": "active-backup", +# "name": "bond0", +# "primary": "eth1" +# }, +# { +# "hash_policy": "layer2+3", +# "members": [ +# { +# "member": "eth2" +# } +# ], +# "mode": "active-backup", +# "name": "bond1", +# "primary": "eth2" +# } +# ] + + """ RETURN = """ before: @@ -551,12 +759,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=Lag_interfacesArgs.argument_spec, required_if=required_if, supports_check_mode=True, + mutually_exclusive=mutually_exclusive, ) result = Lag_interfaces(module).execute_module() diff --git a/tests/integration/targets/vyos_lag_interfaces/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_lag_interfaces/tests/cli/_parsed_config.cfg new file mode 100644 index 0000000..ea3bfce --- /dev/null +++ b/tests/integration/targets/vyos_lag_interfaces/tests/cli/_parsed_config.cfg @@ -0,0 +1,8 @@ +set interfaces bonding bond0 hash-policy 'layer2' +set interfaces bonding bond0 mode 'active-backup' +set interfaces bonding bond0 primary 'eth1' +set interfaces bonding bond1 hash-policy 'layer2+3' +set interfaces bonding bond1 mode 'active-backup' +set interfaces bonding bond1 primary 'eth2' +set interfaces ethernet eth1 bond-group 'bond0' +set interfaces ethernet eth2 bond-group 'bond1'
\ No newline at end of file diff --git a/tests/integration/targets/vyos_lag_interfaces/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_lag_interfaces/tests/cli/empty_config.yaml index 3894fb5..6e89eae 100644 --- a/tests/integration/targets/vyos_lag_interfaces/tests/cli/empty_config.yaml +++ b/tests/integration/targets/vyos_lag_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_lag_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_lag_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_lag_interfaces/tests/cli/gathered.yaml b/tests/integration/targets/vyos_lag_interfaces/tests/cli/gathered.yaml new file mode 100644 index 0000000..c600ec1 --- /dev/null +++ b/tests/integration/targets/vyos_lag_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,34 @@ +--- +- debug: + msg: START vyos_lag_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_lag_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_lag_interfaces: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + always: + + - include_tasks: _remove_config.yaml
\ No newline at end of file diff --git a/tests/integration/targets/vyos_lag_interfaces/tests/cli/parsed.yaml b/tests/integration/targets/vyos_lag_interfaces/tests/cli/parsed.yaml new file mode 100644 index 0000000..64e7780 --- /dev/null +++ b/tests/integration/targets/vyos_lag_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,41 @@ +--- +- debug: + msg: START vyos_lag_interfaces parsed integration tests on connection={{ ansible_connection + }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + + - name: Gather lag_interfaces facts + register: lag_interfaces_facts + vyos.vyos.vyos_facts: + gather_subset: + - default + gather_network_resources: + - lag_interfaces + + - name: Provide the running configuration for parsing (config to be parsed) + register: result + vyos.vyos.vyos_lag_interfaces: &id001 + running_config: "{{ lookup('file', '_parsed_config.cfg') }}" + state: parsed + + - name: Assert that correct parsing done + assert: + that: "{{ ansible_facts['network_resources']['lag_interfaces'] | symmetric_difference(result['parsed'])\ + \ |length == 0 }}" + + - name: Gather the existing running configuration (IDEMPOTENT) + register: result + vyos.vyos.vyos_lag_interfaces: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + always: + + - include_tasks: _remove_config.yaml
\ No newline at end of file diff --git a/tests/integration/targets/vyos_lag_interfaces/tests/cli/rendered.yaml b/tests/integration/targets/vyos_lag_interfaces/tests/cli/rendered.yaml new file mode 100644 index 0000000..9892a3f --- /dev/null +++ b/tests/integration/targets/vyos_lag_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,46 @@ +--- +- debug: + msg: START vyos_lag_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_lag_interfaces: &id001 + config: + - name: bond0 + hash_policy: layer2 + members: + - member: eth1 + mode: active-backup + primary: eth1 + - name: bond1 + hash_policy: layer2+3 + members: + - member: eth2 + mode: active-backup + primary: eth2 + 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_lag_interfaces: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + always: + + - include_tasks: _remove_config.yaml
\ No newline at end of file diff --git a/tests/integration/targets/vyos_lag_interfaces/vars/main.yaml b/tests/integration/targets/vyos_lag_interfaces/vars/main.yaml index 5783693..9784fb9 100644 --- a/tests/integration/targets/vyos_lag_interfaces/vars/main.yaml +++ b/tests/integration/targets/vyos_lag_interfaces/vars/main.yaml @@ -83,6 +83,16 @@ deleted: after: - name: bond0 - name: bond1 +rendered: + commands: + - set interfaces bonding bond0 hash-policy 'layer2' + - set interfaces ethernet eth1 bond-group 'bond0' + - set interfaces bonding bond0 mode 'active-backup' + - set interfaces bonding bond0 primary 'eth1' + - set interfaces bonding bond1 hash-policy 'layer2+3' + - set interfaces ethernet eth2 bond-group 'bond1' + - set interfaces bonding bond1 mode 'active-backup' + - set interfaces bonding bond1 primary 'eth2' round_trip: after: - name: bond0 |