diff options
author | ansible-zuul[bot] <48994755+ansible-zuul[bot]@users.noreply.github.com> | 2020-05-07 19:53:53 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-07 19:53:53 +0000 |
commit | 07a53b4407c46dc19cdbde092fbf96970bb61306 (patch) | |
tree | 46ba4ea2a996e06ae195b7e2d209791759456364 | |
parent | 62d621f64c082d889950d48ccf4d1177aa24000a (diff) | |
parent | 622294ebf8acee14f4f8f9041cea14f66c13b643 (diff) | |
download | vyos-ansible-old-07a53b4407c46dc19cdbde092fbf96970bb61306.tar.gz vyos-ansible-old-07a53b4407c46dc19cdbde092fbf96970bb61306.zip |
Merge pull request #25 from rohitthakur2590/interfaces_states_addded
[VyOS] interfaces resource module updated with new states
Reviewed-by: https://github.com/apps/ansible-zuul
9 files changed, 469 insertions, 41 deletions
diff --git a/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py b/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py index 3542cb1..fd8b612 100644 --- a/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py +++ b/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py @@ -61,8 +61,17 @@ class InterfacesArgs(object): # pylint: disable=R0903 }, "type": "list", }, + "running_config": {"type": "str"}, "state": { - "choices": ["merged", "replaced", "overridden", "deleted"], + "choices": [ + "merged", + "replaced", + "overridden", + "deleted", + "rendered", + "parsed", + "gathered", + ], "default": "merged", "type": "str", }, diff --git a/plugins/module_utils/network/vyos/config/interfaces/interfaces.py b/plugins/module_utils/network/vyos/config/interfaces/interfaces.py index deb504c..51bf98e 100644 --- a/plugins/module_utils/network/vyos/config/interfaces/interfaces.py +++ b/plugins/module_utils/network/vyos/config/interfaces/interfaces.py @@ -13,7 +13,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type - from copy import deepcopy from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, @@ -49,14 +48,14 @@ class Interfaces(ConfigBase): def __init__(self, module): super(Interfaces, self).__init__(module) - def get_interfaces_facts(self): + def get_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 ) interfaces_facts = facts["ansible_network_resources"].get("interfaces") if not interfaces_facts: @@ -72,25 +71,42 @@ class Interfaces(ConfigBase): commands = list() warnings = list() - existing_interfaces_facts = self.get_interfaces_facts() - commands.extend(self.set_config(existing_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 + if self.state in self.ACTION_STATES: + existing_interfaces_facts = self.get_interfaces_facts() + else: + existing_interfaces_facts = [] - result["commands"] = commands + if self.state in self.ACTION_STATES or self.state == "rendered": + commands.extend(self.set_config(existing_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_interfaces_facts = self.get_interfaces_facts() + if self.state in self.ACTION_STATES: + result["commands"] = commands + + if self.state in self.ACTION_STATES or self.state == "gathered": + changed_interfaces_facts = self.get_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_interfaces_facts(data=running_config) + else: + changed_interfaces_facts = [] - result["before"] = existing_interfaces_facts - if result["changed"]: - result["after"] = changed_interfaces_facts + if self.state in self.ACTION_STATES: + result["before"] = existing_interfaces_facts + if result["changed"]: + result["after"] = changed_interfaces_facts + elif self.state == "gathered": + result["gathered"] = changed_interfaces_facts result["warnings"] = warnings return result @@ -118,19 +134,21 @@ class 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 not want: for intf in have: commands.extend( @@ -146,12 +164,12 @@ class Interfaces(ConfigBase): obj_in_have = search_obj_in_list(name, have) if not obj_in_have: - obj_in_have = {"name": item["name"]} + obj_in_have = {"name": name} - elif state == "merged": + if self.state in ("merged", "rendered"): commands.extend(self._state_merged(item, obj_in_have)) - elif state == "replaced": + elif self.state == "replaced": commands.extend(self._state_replaced(item, obj_in_have)) return commands diff --git a/plugins/modules/vyos_interfaces.py b/plugins/modules/vyos_interfaces.py index 93df4e4..6730e30 100644 --- a/plugins/modules/vyos_interfaces.py +++ b/plugins/modules/vyos_interfaces.py @@ -30,14 +30,10 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "network", -} +ANSIBLE_METADATA = {"metadata_version": "1.1", "supported_by": "Ansible"} DOCUMENTATION = """module: vyos_interfaces -short_description: Manages interface attributes of VyOS network devices. +short_description: Interfaces resource module description: - This module manages the interface attributes on VyOS network devices. - This module supports managing base attributes of Ethernet, Bonding, VXLAN, Loopback @@ -45,7 +41,10 @@ description: notes: - Tested against VyOS 1.1.8 (helium). - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). -author: Nilashish Chakraborty (@nilashishc) +version_added: "1.0.0" +author: +- Nilashish Chakraborty (@nilashishc) +- Rohit Thakur (@rohitthakur2590) options: config: description: The provided interfaces configuration. @@ -119,6 +118,15 @@ options: - MTU for the virtual sub-interface. - Refer to vendor documentation for valid values. type: int + 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 interfaces). + - 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. @@ -128,6 +136,9 @@ options: - replaced - overridden - deleted + - rendered + - gathered + - parsed default: merged """ EXAMPLES = """ @@ -152,7 +163,7 @@ EXAMPLES = """ # set interfaces loopback lo - name: Merge provided configuration with device configuration - vyos_interfaces: + vyos.vyos.vyos_interfaces: config: - name: eth2 description: 'Configured by Ansible' @@ -330,7 +341,7 @@ EXAMPLES = """ # # - name: Replace device configurations of listed interfaces with provided configurations - vyos_interfaces: + vyos.vyos.vyos_interfaces: config: - name: eth2 description: "Replaced by Ansible" @@ -515,7 +526,7 @@ EXAMPLES = """ # # - name: Overrides all device configuration with provided configuration - vyos_interfaces: + vyos.vyos.vyos_interfaces: config: - name: eth0 description: Outbound Interface For The Appliance @@ -700,7 +711,7 @@ EXAMPLES = """ # # - name: Delete attributes of given interfaces (Note - This won't delete the interfaces themselves) - vyos_interfaces: + vyos.vyos.vyos_interfaces: config: - name: bond1 @@ -838,6 +849,224 @@ EXAMPLES = """ # set interfaces loopback lo # # + + +# Using gathered +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep interfaces +# set interfaces ethernet eth0 address 'dhcp' +# set interfaces ethernet eth0 duplex 'auto' +# set interfaces ethernet eth0 hw-id '08:00:27:50:5e:19' +# set interfaces ethernet eth0 smp_affinity 'auto' +# set interfaces ethernet eth0 speed 'auto' +# set interfaces ethernet eth1 description 'Configured by Ansible' +# set interfaces ethernet eth1 duplex 'auto' +# set interfaces ethernet eth1 mtu '1500' +# set interfaces ethernet eth1 speed 'auto' +# set interfaces ethernet eth1 vif 200 description 'VIF - 200' +# set interfaces ethernet eth2 description 'Configured by Ansible' +# set interfaces ethernet eth2 duplex 'auto' +# set interfaces ethernet eth2 mtu '1500' +# set interfaces ethernet eth2 speed 'auto' +# set interfaces ethernet eth2 vif 200 description 'VIF - 200' +# +- name: Gather listed interfaces with provided configurations + vyos.vyos.vyos_interfaces: + config: + state: gathered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# "gathered": [ +# { +# "description": "Configured by Ansible", +# "duplex": "auto", +# "enabled": true, +# "mtu": 1500, +# "name": "eth2", +# "speed": "auto", +# "vifs": [ +# { +# "description": "VIF - 200", +# "enabled": true, +# "vlan_id": 200 +# } +# ] +# }, +# { +# "description": "Configured by Ansible", +# "duplex": "auto", +# "enabled": true, +# "mtu": 1500, +# "name": "eth1", +# "speed": "auto", +# "vifs": [ +# { +# "description": "VIF - 200", +# "enabled": true, +# "vlan_id": 200 +# } +# ] +# }, +# { +# "duplex": "auto", +# "enabled": true, +# "name": "eth0", +# "speed": "auto" +# } +# ] +# +# +# After state: +# ------------- +# +# vyos@192# run show configuration commands | grep interfaces +# set interfaces ethernet eth0 address 'dhcp' +# set interfaces ethernet eth0 duplex 'auto' +# set interfaces ethernet eth0 hw-id '08:00:27:50:5e:19' +# set interfaces ethernet eth0 smp_affinity 'auto' +# set interfaces ethernet eth0 speed 'auto' +# set interfaces ethernet eth1 description 'Configured by Ansible' +# set interfaces ethernet eth1 duplex 'auto' +# set interfaces ethernet eth1 mtu '1500' +# set interfaces ethernet eth1 speed 'auto' +# set interfaces ethernet eth1 vif 200 description 'VIF - 200' +# set interfaces ethernet eth2 description 'Configured by Ansible' +# set interfaces ethernet eth2 duplex 'auto' +# set interfaces ethernet eth2 mtu '1500' +# set interfaces ethernet eth2 speed 'auto' +# set interfaces ethernet eth2 vif 200 description 'VIF - 200' + + +# Using rendered +# +# +- name: Render the commands for provided configuration + vyos.vyos.vyos_interfaces: + config: + - name: eth0 + enabled: true + duplex: auto + speed: auto + - name: eth1 + description: Configured by Ansible - Interface 1 + mtu: 1500 + speed: auto + duplex: auto + enabled: true + vifs: + - vlan_id: 100 + description: Eth1 - VIF 100 + mtu: 400 + enabled: true + - vlan_id: 101 + description: Eth1 - VIF 101 + enabled: true + - name: eth2 + description: Configured by Ansible - Interface 2 (ADMIN DOWN) + mtu: 600 + enabled: false + state: rendered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "rendered": [ +# "set interfaces ethernet eth0 duplex 'auto'", +# "set interfaces ethernet eth0 speed 'auto'", +# "delete interfaces ethernet eth0 disable", +# "set interfaces ethernet eth1 duplex 'auto'", +# "delete interfaces ethernet eth1 disable", +# "set interfaces ethernet eth1 speed 'auto'", +# "set interfaces ethernet eth1 description 'Configured by Ansible - Interface 1'", +# "set interfaces ethernet eth1 mtu '1500'", +# "set interfaces ethernet eth1 vif 100 description 'Eth1 - VIF 100'", +# "set interfaces ethernet eth1 vif 100 mtu '400'", +# "set interfaces ethernet eth1 vif 101 description 'Eth1 - VIF 101'", +# "set interfaces ethernet eth2 disable", +# "set interfaces ethernet eth2 description 'Configured by Ansible - Interface 2 (ADMIN DOWN)'", +# "set interfaces ethernet eth2 mtu '600'" +# ] + + +# Using parsed +# +# +- name: Parse the configuration. + vyos.vyos.vyos_interfaces: + running_config: + "set interfaces ethernet eth0 address 'dhcp' + set interfaces ethernet eth0 duplex 'auto' + set interfaces ethernet eth0 hw-id '08:00:27:50:5e:19' + set interfaces ethernet eth0 smp_affinity 'auto' + set interfaces ethernet eth0 speed 'auto' + set interfaces ethernet eth1 description 'Configured by Ansible' + set interfaces ethernet eth1 duplex 'auto' + set interfaces ethernet eth1 mtu '1500' + set interfaces ethernet eth1 speed 'auto' + set interfaces ethernet eth1 vif 200 description 'VIF - 200' + set interfaces ethernet eth2 description 'Configured by Ansible' + set interfaces ethernet eth2 duplex 'auto' + set interfaces ethernet eth2 mtu '1500' + set interfaces ethernet eth2 speed 'auto' + set interfaces ethernet eth2 vif 200 description 'VIF - 200'" + state: parsed +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "parsed": [ +# { +# "description": "Configured by Ansible", +# "duplex": "auto", +# "enabled": true, +# "mtu": 1500, +# "name": "eth2", +# "speed": "auto", +# "vifs": [ +# { +# "description": "VIF - 200", +# "enabled": true, +# "vlan_id": 200 +# } +# ] +# }, +# { +# "description": "Configured by Ansible", +# "duplex": "auto", +# "enabled": true, +# "mtu": 1500, +# "name": "eth1", +# "speed": "auto", +# "vifs": [ +# { +# "description": "VIF - 200", +# "enabled": true, +# "vlan_id": 200 +# } +# ] +# }, +# { +# "duplex": "auto", +# "enabled": true, +# "name": "eth0", +# "speed": "auto" +# } +# ] + + """ RETURN = """ before: @@ -879,8 +1108,19 @@ def main(): :returns: the result form module invocation """ + 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=InterfacesArgs.argument_spec, supports_check_mode=True + argument_spec=InterfacesArgs.argument_spec, + required_if=required_if, + supports_check_mode=True, + mutually_exclusive=mutually_exclusive, ) result = Interfaces(module).execute_module() diff --git a/tests/integration/targets/vyos_interfaces/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_interfaces/tests/cli/_parsed_config.cfg new file mode 100644 index 0000000..e5c3fc7 --- /dev/null +++ b/tests/integration/targets/vyos_interfaces/tests/cli/_parsed_config.cfg @@ -0,0 +1,12 @@ +set interfaces ethernet eth1 description 'Configured by Ansible - Interface 1' +set interfaces ethernet eth1 duplex 'auto' +set interfaces ethernet eth1 hw-id '08:00:27:da:67:43' +set interfaces ethernet eth1 mtu '1500' +set interfaces ethernet eth1 speed 'auto' +set interfaces ethernet eth1 vif 100 description 'Eth1 - VIF 100' +set interfaces ethernet eth1 vif 100 mtu '400' +set interfaces ethernet eth1 vif 101 description 'Eth1 - VIF 101' +set interfaces ethernet eth2 description 'Configured by Ansible - Interface 2 (ADMIN DOWN)' +set interfaces ethernet eth2 'disable' +set interfaces ethernet eth2 hw-id '08:00:27:d8:70:b0' +set interfaces ethernet eth2 mtu '600' diff --git a/tests/integration/targets/vyos_interfaces/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_interfaces/tests/cli/empty_config.yaml index e1e154d..652f158 100644 --- a/tests/integration/targets/vyos_interfaces/tests/cli/empty_config.yaml +++ b/tests/integration/targets/vyos_interfaces/tests/cli/empty_config.yaml @@ -1,7 +1,7 @@ --- - debug: - msg: START vyos_interfaces empty_config integration tests on connection={{ ansible_connection - }} + msg: START vyos_interfaces empty_config integration tests on connection={{ + ansible_connection }} - name: Merged with empty config should give appropriate error message register: result @@ -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_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_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_interfaces/tests/cli/gathered.yaml b/tests/integration/targets/vyos_interfaces/tests/cli/gathered.yaml new file mode 100644 index 0000000..ac9892c --- /dev/null +++ b/tests/integration/targets/vyos_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,26 @@ +--- +- debug: + msg: START vyos_interfaces gathered integration tests on connection={{ ansible_connection + }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + + - name: Gather the provided configuration with the exisiting running configuration + register: result + vyos.vyos.vyos_interfaces: + config: + state: gathered + + - name: Assert that gathered dicts was correctly generated + assert: + that: + - "{{ populate | symmetric_difference(result['gathered']) |length == 0\ + \ }}" + + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_interfaces/tests/cli/parsed.yaml b/tests/integration/targets/vyos_interfaces/tests/cli/parsed.yaml new file mode 100644 index 0000000..a44fc2f --- /dev/null +++ b/tests/integration/targets/vyos_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,16 @@ +--- +- debug: + msg: START vyos_interfaces parsed integration tests on connection={{ ansible_connection + }} + +- name: Parse externally provided interfaces config to agnostic model + register: result + vyos.vyos.vyos_interfaces: + running_config: "{{ lookup('file', '_parsed_config.cfg') }}" + state: parsed + +- name: Assert that config was correctly parsed + assert: + that: + - "{{ parsed['after'] | symmetric_difference(result['parsed']) |length ==\ + \ 0 }}" diff --git a/tests/integration/targets/vyos_interfaces/tests/cli/rendered.yaml b/tests/integration/targets/vyos_interfaces/tests/cli/rendered.yaml new file mode 100644 index 0000000..5030d71 --- /dev/null +++ b/tests/integration/targets/vyos_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,47 @@ +--- +- debug: + msg: START vyos_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_interfaces: + config: + - name: eth0 + enabled: true + duplex: auto + speed: auto + - name: eth1 + description: Configured by Ansible - Interface 1 + mtu: 1500 + speed: auto + duplex: auto + enabled: true + vifs: + - vlan_id: 100 + description: Eth1 - VIF 100 + mtu: 400 + enabled: true + - vlan_id: 101 + description: Eth1 - VIF 101 + enabled: true + - name: eth2 + description: Configured by Ansible - Interface 2 (ADMIN DOWN) + mtu: 600 + enabled: false + state: rendered + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered'])\ + \ |length == 0 }}" + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_interfaces/vars/main.yaml b/tests/integration/targets/vyos_interfaces/vars/main.yaml index b730080..84a8bf0 100644 --- a/tests/integration/targets/vyos_interfaces/vars/main.yaml +++ b/tests/integration/targets/vyos_interfaces/vars/main.yaml @@ -104,6 +104,26 @@ replaced: enabled: true duplex: auto speed: auto +parsed: + after: + - name: eth1 + description: Configured by Ansible - Interface 1 + mtu: 1500 + speed: auto + duplex: auto + enabled: true + vifs: + - vlan_id: 100 + description: Eth1 - VIF 100 + mtu: 400 + enabled: true + - vlan_id: 101 + description: Eth1 - VIF 101 + enabled: true + - name: eth2 + description: Configured by Ansible - Interface 2 (ADMIN DOWN) + mtu: 600 + enabled: false overridden: commands: - delete interfaces ethernet eth1 description @@ -133,6 +153,23 @@ overridden: vifs: - vlan_id: 200 enabled: true +rendered: + commands: + - set interfaces ethernet eth0 duplex 'auto' + - set interfaces ethernet eth0 speed 'auto' + - delete interfaces ethernet eth0 disable + - set interfaces ethernet eth1 duplex 'auto' + - delete interfaces ethernet eth1 disable + - set interfaces ethernet eth1 speed 'auto' + - set interfaces ethernet eth1 description 'Configured by Ansible - Interface 1' + - set interfaces ethernet eth1 mtu '1500' + - set interfaces ethernet eth1 vif 100 description 'Eth1 - VIF 100' + - set interfaces ethernet eth1 vif 100 mtu '400' + - set interfaces ethernet eth1 vif 101 description 'Eth1 - VIF 101' + - set interfaces ethernet eth2 disable + - set interfaces ethernet eth2 description 'Configured by Ansible - Interface 2 (ADMIN DOWN)' + - set interfaces ethernet eth2 mtu '600' + deleted: commands: - delete interfaces ethernet eth1 description |