diff options
| author | omnom62 <75066712+omnom62@users.noreply.github.com> | 2025-11-27 06:00:30 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-26 20:00:30 +0000 |
| commit | 85e132415cd7917c677d27b9085d17f50bc3da2e (patch) | |
| tree | 0982a65bff1a6e74d5c8929349a92414b6008f1b | |
| parent | cba33a3b88f58881d7989a22292b25901cb3242c (diff) | |
| download | vyos.vyos-85e132415cd7917c677d27b9085d17f50bc3da2e.tar.gz vyos.vyos-85e132415cd7917c677d27b9085d17f50bc3da2e.zip | |
T6823: correctly set the IPv6 autoconf option (#433)
* T6823 init fix
* slaac and integration tests
* reaplced integration test
* WIP integration tests
* changelog and tweaks
* rendered, gathered, parsed, integration tests for SLAAC
* l3_interfaces gathered, emty, deleted
* deleted integration test
* vif processing
* vif tests
* vir related integration test cases
* ignore ansible-bad-import-from
* ansible-bad-import-from ingore
* ignore ansible-bad-import-from for all
* test ansible-bad-import-from skip
* ingore file
* Fix bugs with configuration remove
* Delete testcase fixed
* SLAAC integration tests
* Sanity check fixes
* remove_config formatted
* l3 slaac eth0 removed from SIT
* Remove ignore 2.20
* ignore2.20 recovered
* Remove residue
12 files changed, 298 insertions, 56 deletions
diff --git a/changelogs/fragments/t6823_ipv6_autoconf.yml b/changelogs/fragments/t6823_ipv6_autoconf.yml new file mode 100644 index 00000000..8dfa04ee --- /dev/null +++ b/changelogs/fragments/t6823_ipv6_autoconf.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - vyos_l3_interfaces - ipv6 auto-config option incorrectly set diff --git a/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py b/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py index ee709e2a..a23494cd 100644 --- a/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py +++ b/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py @@ -79,7 +79,7 @@ class L3_interfaces(ConfigBase): commands = list() if self.state in self.ACTION_STATES: - existing_l3_interfaces_facts = self.get_l3_interfaces_facts() + existing_l3_interfaces_facts = self.mutate_autoconfig(self.get_l3_interfaces_facts()) else: existing_l3_interfaces_facts = [] @@ -95,16 +95,19 @@ class L3_interfaces(ConfigBase): result["commands"] = commands if self.state in self.ACTION_STATES or self.state == "gathered": - changed_l3_interfaces_facts = self.get_l3_interfaces_facts() + changed_l3_interfaces_facts = self.mutate_autoconfig(self.get_l3_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_l3_interfaces_facts(data=running_config) + result["parsed"] = self.mutate_autoconfig( + self.get_l3_interfaces_facts(data=running_config), + ) else: changed_l3_interfaces_facts = [] @@ -128,6 +131,7 @@ class L3_interfaces(ConfigBase): """ want = self._module.params["config"] have = existing_l3_interfaces_facts + resp = self.set_state(want, have) return to_list(resp) @@ -173,6 +177,7 @@ class L3_interfaces(ConfigBase): elif state == "replaced": commands.extend(self._state_replaced(item, obj_in_have)) + commands = [command.replace("auto-config", "autoconf") for command in commands] return commands def _state_replaced(self, want, have): @@ -246,7 +251,6 @@ class L3_interfaces(ConfigBase): vif=want_vif["vlan_id"], ), ) - return commands def _state_deleted(self, want, have): @@ -260,51 +264,73 @@ class L3_interfaces(ConfigBase): want_copy = deepcopy(remove_empties(want)) have_copy = deepcopy(have) - want_vifs = want_copy.pop("vifs", []) - have_vifs = have_copy.pop("vifs", []) - - for update in self._get_updates(have_copy, want_copy): - for key, value in update.items(): + if have_copy is not None: + if all(v in (None, {}, []) for k, v in want_copy.items() if k != "name"): commands.append( self._compute_commands( - key=key, - value=value, + key=None, + value=None, interface=want_copy["name"], remove=True, ), ) - - if have_vifs: - for have_vif in have_vifs: - want_vif = search_obj_in_list(have_vif["vlan_id"], want_vifs, key="vlan_id") - if not want_vif: - want_vif = {"vlan_id": have_vif["vlan_id"]} - - for update in self._get_updates(have_vif, want_vif): - for key, value in update.items(): - commands.append( - self._compute_commands( - key=key, - interface=want_copy["name"], - value=value, - vif=want_vif["vlan_id"], - remove=True, - ), - ) + return commands + + want_vifs = want_copy.pop("vifs", []) + have_vifs = have_copy.pop("vifs", []) + + if have_vifs: + for have_vif in have_vifs: + want_vif = search_obj_in_list(have_vif["vlan_id"], want_vifs, key="vlan_id") + if not want_vif: + want_vif = {"vlan_id": have_vif["vlan_id"]} + + for update in self._get_updates(have_vif, want_vif): + for key, value in update.items(): + commands.append( + self._compute_commands( + key=key, + interface=want_copy["name"], + value=value, + vif=want_vif["vlan_id"], + remove=True, + ), + ) + + for update in self._get_updates(have_copy, want_copy): + for key, value in update.items(): + commands.append( + self._compute_commands( + key=key, + value=value, + interface=want_copy["name"], + remove=True, + ), + ) return commands def _compute_commands(self, interface, key, vif=None, value=None, remove=False): - intf_context = "interfaces {0} {1}".format(get_interface_type(interface), interface) + if value == "auto-config" and vif is None: + intf_context = "interfaces {0} {1} ipv6".format( + get_interface_type(interface), + interface, + ) + else: + intf_context = "interfaces {0} {1}".format(get_interface_type(interface), interface) + set_cmd = "set {0}".format(intf_context) del_cmd = "delete {0}".format(intf_context) if vif: - set_cmd = set_cmd + (" vif {0}".format(vif)) - del_cmd = del_cmd + (" vif {0}".format(vif)) + suffix = " ipv6" if value == "auto-config" else "" + set_cmd += f" vif {vif}{suffix}" + del_cmd += f" vif {vif}{suffix}" - if remove: + if remove and key and value: command = "{0} {1} '{2}'".format(del_cmd, key, value) + elif remove and not (key and value): + command = "{0}".format(del_cmd) else: command = "{0} {1} '{2}'".format(set_cmd, key, value) @@ -317,3 +343,12 @@ class L3_interfaces(ConfigBase): updates.extend(diff_list_of_dicts(want.get("ipv6", []), have.get("ipv6", []))) return updates + + def mutate_autoconfig(self, obj): + if isinstance(obj, dict): + return dict(map(lambda kv: (kv[0], self.mutate_autoconfig(kv[1])), obj.items())) + if isinstance(obj, list): + return list(map(self.mutate_autoconfig, obj)) + if isinstance(obj, str): + return obj.replace("autoconf", "auto-config") + return obj diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_l3_interfaces/tests/cli/_parsed_config.cfg index 9232a0a4..a34ac606 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/_parsed_config.cfg +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/_parsed_config.cfg @@ -1,4 +1,5 @@ set interfaces ethernet eth1 address '192.0.2.10/24' +set interfaces ethernet eth1 vif 102 ipv6 address 'autoconf' set interfaces ethernet eth1 address '2001:db8::10/32' set interfaces ethernet eth1 hw-id '08:00:27:da:67:43' set interfaces ethernet eth2 address '198.51.100.10/24' diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/_populate.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/_populate.yaml index 6f6c5066..d6ccd116 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/_populate.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/_populate.yaml @@ -7,7 +7,7 @@ set interfaces ethernet eth1 address '192.0.2.14/24' set interfaces ethernet eth2 address '192.0.2.10/24' set interfaces ethernet eth2 address '192.0.2.11/24' - set interfaces ethernet eth2 address '2001:db8::10/32' + set interfaces ethernet eth2 address '2001:db8::10/32' set interfaces ethernet eth2 address '2001:db8::12/32' ansible.netcommon.cli_config: config: "{{ lines }}" diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/_remove_config.yaml index aa5a628f..13774cd5 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/_remove_config.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/_remove_config.yaml @@ -1,7 +1,10 @@ --- - name: Remove Config vars: - lines: "delete interfaces ethernet \"{{ intf }}\" address\ndelete interfaces ethernet \"{{ intf }}\" vif\n" + lines: | + delete interfaces ethernet "{{ intf }}" address + delete interfaces ethernet "{{ intf }}" vif + delete interfaces ethernet "{{ intf }}" ipv6 loop: - eth1 - eth2 diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/deleted.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/deleted.yaml index df21b431..000d55e0 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/deleted.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/deleted.yaml @@ -10,7 +10,6 @@ vyos.vyos.vyos_l3_interfaces: &id001 config: - name: eth1 - - name: eth2 state: deleted @@ -42,5 +41,42 @@ assert: that: - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Prepare delete test for SLAAC auto-config + vyos.vyos.vyos_l3_interfaces: + config: + - name: eth1 + ipv6: + - address: auto-config + - name: eth2 + vifs: + - vlan_id: 101 + ipv6: + - address: auto-config + state: replaced + + - name: Delete SLACC auto-config of given interfaces + register: result + vyos.vyos.vyos_l3_interfaces: + config: + - name: eth1 + - name: eth2 + state: deleted + + - name: Assert that the before dicts were correctly generated (SLAAC) + assert: + that: + - "{{ deleted['before_slaac'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated (SLAAC) + assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated (SLAAC) + assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + always: - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/gathered.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/gathered.yaml index 41a53d87..0a3db05b 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/gathered.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/gathered.yaml @@ -24,5 +24,37 @@ assert: that: - result['changed'] == false + + - name: Merge the provided configuration for SLAAC tesitng + register: result + vyos.vyos.vyos_l3_interfaces: + config: + - name: eth1 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config + state: merged + + - name: Gather the provided configuration with the existing running configuration + register: result + vyos.vyos.vyos_l3_interfaces: &id002 + config: + state: gathered + + - name: Assert that gathered dicts was correctly generated for SLAAC + assert: + that: + - "{{ populate_slaac | symmetric_difference(result['gathered']) |length == 0 }}" + + - name: Gather the existing running configuration for SLAAC (IDEMPOTENT) + register: result + vyos.vyos.vyos_l3_interfaces: *id002 + + - 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_l3_interfaces/tests/cli/merged.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/merged.yaml index 4ec4d0f2..fcb5e896 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/merged.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/merged.yaml @@ -14,6 +14,10 @@ - address: 192.0.2.10/24 ipv6: - address: 2001:db8::10/32 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config - name: eth2 ipv4: diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/overridden.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/overridden.yaml index 8334a610..240d01ac 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/overridden.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/overridden.yaml @@ -16,6 +16,14 @@ - name: eth1 ipv4: - address: 192.0.2.15/24 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config + + - name: eth2 + ipv6: + - address: auto-config state: overridden - name: Assert that before dicts were correctly generated diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/rendered.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/rendered.yaml index 199879f4..9f5de20a 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/rendered.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/rendered.yaml @@ -12,6 +12,10 @@ - name: eth1 ipv4: - address: 192.0.2.14/24 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config - name: eth2 ipv4: - address: 192.0.2.10/24 @@ -19,6 +23,12 @@ ipv6: - address: 2001:db8::10/32 - address: 2001:db8::12/32 + vifs: + - vlan_id: 101 + ipv4: + - address: 198.51.100.130/25 + ipv6: + - address: 2001:db8::20/32 state: rendered - name: Assert that correct set of commands were generated diff --git a/tests/integration/targets/vyos_l3_interfaces/tests/cli/replaced.yaml b/tests/integration/targets/vyos_l3_interfaces/tests/cli/replaced.yaml index 502175fc..0715172d 100644 --- a/tests/integration/targets/vyos_l3_interfaces/tests/cli/replaced.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/tests/cli/replaced.yaml @@ -46,5 +46,49 @@ assert: that: - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Replace device configurations (autoconf) + register: result + vyos.vyos.vyos_l3_interfaces: &id002 + config: + - name: eth2 + ipv6: + - address: auto-config + - name: eth1 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config + state: replaced + + - name: Assert that correct set of commands were generated (autoconf) + assert: + that: + - "{{ replaced['af_commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dict is correctly generated (autoconf) + assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ replaced['af_after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device autoconf configurations (IDEMPOTENT) + register: result + vyos.vyos.vyos_l3_interfaces: *id002 + + - name: Assert that task was idempotent (autoconf) + assert: + that: + - result['changed'] == false + + - name: Assert that before dict is correctly generated (autoconf) + assert: + that: + - "{{ replaced['af_after'] | symmetric_difference(result['before']) |length == 0 }}" + always: - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_l3_interfaces/vars/main.yaml b/tests/integration/targets/vyos_l3_interfaces/vars/main.yaml index e9781e6a..84f1c637 100644 --- a/tests/integration/targets/vyos_l3_interfaces/vars/main.yaml +++ b/tests/integration/targets/vyos_l3_interfaces/vars/main.yaml @@ -9,27 +9,32 @@ merged: commands: - set interfaces ethernet eth1 address '192.0.2.10/24' - set interfaces ethernet eth1 address '2001:db8::10/32' + - set interfaces ethernet eth1 vif 102 ipv6 address 'autoconf' - set interfaces ethernet eth2 address '198.51.100.10/24' - set interfaces ethernet eth2 vif 101 address '198.51.100.130/25' - set interfaces ethernet eth2 vif 101 address '2001:db8::20/32' after: - - name: eth0 - ipv4: - - address: dhcp - - name: eth1 - ipv4: - - address: 192.0.2.10/24 - ipv6: - - address: 2001:db8::10/32 - - name: eth2 - ipv4: + - ipv4: - address: 198.51.100.10/24 + name: eth2 vifs: - - vlan_id: 101 - ipv4: + - ipv4: - address: 198.51.100.130/25 ipv6: - address: 2001:db8::20/32 + vlan_id: 101 + - ipv4: + - address: dhcp + name: eth0 + - ipv4: + - address: 192.0.2.10/24 + ipv6: + - address: 2001:db8::10/32 + name: eth1 + vifs: + - ipv6: + - address: auto-config + vlan_id: 102 populate: - name: eth1 ipv4: @@ -44,6 +49,25 @@ populate: - name: eth0 ipv4: - address: dhcp + +populate_slaac: + - name: eth1 + ipv4: + - address: 192.0.2.14/24 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config + - name: eth2 + ipv4: + - address: 192.0.2.10/24 + - address: 192.0.2.11/24 + ipv6: + - address: 2001:db8::10/32 + - address: 2001:db8::12/32 + - name: eth0 + ipv4: + - address: dhcp replaced: commands: - delete interfaces ethernet eth2 address '192.0.2.10/24' @@ -53,6 +77,11 @@ replaced: - set interfaces ethernet eth2 address '2001:db8::11/32' - delete interfaces ethernet eth1 address '192.0.2.14/24' - set interfaces ethernet eth1 address '192.0.2.19/24' + af_commands: + - delete interfaces ethernet eth2 address '2001:db8::11/32' + - set interfaces ethernet eth2 ipv6 address 'autoconf' + - delete interfaces ethernet eth1 address '192.0.2.19/24' + - set interfaces ethernet eth1 vif 102 ipv6 address 'autoconf' after: - name: eth2 ipv6: @@ -63,14 +92,28 @@ replaced: - name: eth0 ipv4: - address: dhcp + af_after: + - name: eth2 + ipv6: + - address: auto-config + - name: eth1 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config + - name: eth0 + ipv4: + - address: dhcp overridden: commands: - delete interfaces ethernet eth1 address '192.0.2.14/24' - set interfaces ethernet eth1 address '192.0.2.15/24' - - delete interfaces ethernet eth2 address '192.0.2.10/24' + - set interfaces ethernet eth1 vif 102 ipv6 address 'autoconf' - delete interfaces ethernet eth2 address '192.0.2.11/24' - - delete interfaces ethernet eth2 address '2001:db8::10/32' + - delete interfaces ethernet eth2 address '192.0.2.10/24' - delete interfaces ethernet eth2 address '2001:db8::12/32' + - delete interfaces ethernet eth2 address '2001:db8::10/32' + - set interfaces ethernet eth2 ipv6 address 'autoconf' after: - name: eth0 ipv4: @@ -78,7 +121,13 @@ overridden: - name: eth1 ipv4: - address: 192.0.2.15/24 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config - name: eth2 + ipv6: + - address: auto-config parsed: after: - name: eth1 @@ -86,6 +135,10 @@ parsed: - address: 192.0.2.10/24 ipv6: - address: 2001:db8::10/32 + vifs: + - vlan_id: 102 + ipv6: + - address: auto-config - name: eth2 ipv4: - address: 198.51.100.10/24 @@ -98,21 +151,34 @@ parsed: rendered: commands: - set interfaces ethernet eth1 address '192.0.2.14/24' + - set interfaces ethernet eth1 vif 102 ipv6 address 'autoconf' - set interfaces ethernet eth2 address '192.0.2.11/24' - set interfaces ethernet eth2 address '192.0.2.10/24' - - set interfaces ethernet eth2 address '2001:db8::10/32' - set interfaces ethernet eth2 address '2001:db8::12/32' + - set interfaces ethernet eth2 address '2001:db8::10/32' + - set interfaces ethernet eth2 vif 101 address '198.51.100.130/25' + - set interfaces ethernet eth2 vif 101 address '2001:db8::20/32' deleted: commands: - - delete interfaces ethernet eth1 address '192.0.2.14/24' - - delete interfaces ethernet eth2 address '192.0.2.10/24' - - delete interfaces ethernet eth2 address '192.0.2.11/24' - - delete interfaces ethernet eth2 address '2001:db8::10/32' - - delete interfaces ethernet eth2 address '2001:db8::12/32' + - delete interfaces ethernet eth1 + - delete interfaces ethernet eth2 + commands_slaac: + - delete interfaces ethernet eth1 ipv6 address 'autoconf' + - delete interfaces ethernet eth2 vif 101 ipv6 address 'autoconf' after: - name: eth0 ipv4: - address: dhcp + before_slaac: + - name: eth0 + ipv4: + - address: dhcp - name: eth1 + ipv6: + - address: auto-config - name: eth2 + vifs: + - vlan_id: 101 + ipv6: + - address: auto-config |
