From 961f2e3513e439cf97fb3dd2c6811ff834d89c04 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 20 Nov 2023 17:17:35 +0530 Subject: [PATCH 01/14] off-box-diff enhancement Signed-off-by: rohitthakur2590 --- changelogs/fragments/off_box_diff_enhancement.yaml | 3 +++ plugins/cliconf/eos.py | 4 +++- plugins/modules/eos_config.py | 8 +++++++- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/off_box_diff_enhancement.yaml diff --git a/changelogs/fragments/off_box_diff_enhancement.yaml b/changelogs/fragments/off_box_diff_enhancement.yaml new file mode 100644 index 000000000..9a5c74391 --- /dev/null +++ b/changelogs/fragments/off_box_diff_enhancement.yaml @@ -0,0 +1,3 @@ +--- +minor_changes: + - Implement off-box-diff optional feature. diff --git a/plugins/cliconf/eos.py b/plugins/cliconf/eos.py index 9c6fb753c..e86d30f7c 100644 --- a/plugins/cliconf/eos.py +++ b/plugins/cliconf/eos.py @@ -210,6 +210,8 @@ def edit_config( resp = {} session = None + diff_onbox = self.get_option("diff_onbox") + if self.supports_sessions(): session = session_name() resp.update({"session": session}) @@ -378,7 +380,6 @@ def get_diff( else: configdiffobjs = candidate_obj.items - diff["config_diff"] = dumps(configdiffobjs, "commands") if configdiffobjs else "" return diff @@ -450,6 +451,7 @@ def get_option_values(self): "format": ["text", "json"], "diff_match": ["line", "strict", "exact", "none"], "diff_replace": ["line", "block", "config"], + "diff_onbox": [True, False], "output": ["text", "json"], } diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 5aa8e7ceb..5c809386b 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -140,6 +140,10 @@ false, the command is issued without the all keyword type: bool default: false + diff_onbox: + description: Specify the status for on-box-diff + type: bool + default: true save_when: description: - When changes are made to the device running-configuration, the changes are not @@ -375,6 +379,7 @@ def main(): parents=dict(type="list", elements="str"), before=dict(type="list", elements="str"), after=dict(type="list", elements="str"), + diff_onbox=dict(type="bool", default=True), match=dict( default="line", choices=["line", "strict", "exact", "none"], @@ -453,12 +458,12 @@ def main(): candidate = get_candidate(module) running = get_running_config(module, contents, flags=flags) - try: response = connection.get_diff( candidate=candidate, running=running, diff_match=match, + diff_onbox=module.params["diff_onbox"], diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=replace, @@ -466,6 +471,7 @@ def main(): except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors="surrogate_then_replace")) + config_diff = response["config_diff"] if config_diff: commands = config_diff.split("\n") From d0881ae90999a90e7cb392c8683f7970223554a6 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 18 Dec 2023 17:15:50 +0530 Subject: [PATCH 02/14] implement unifieddiff Signed-off-by: rohitthakur2590 --- plugins/cliconf/eos.py | 2 +- .../module_utils/network/eos/utils/utils.py | 5 ++++ plugins/modules/eos_config.py | 28 ++++++++++++------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/plugins/cliconf/eos.py b/plugins/cliconf/eos.py index e86d30f7c..20badd1ba 100644 --- a/plugins/cliconf/eos.py +++ b/plugins/cliconf/eos.py @@ -210,7 +210,7 @@ def edit_config( resp = {} session = None - diff_onbox = self.get_option("diff_onbox") + # diff_onbox = self.get_option("diff_onbox") if self.supports_sessions(): session = session_name() diff --git a/plugins/module_utils/network/eos/utils/utils.py b/plugins/module_utils/network/eos/utils/utils.py index 260aa1996..f19a87736 100644 --- a/plugins/module_utils/network/eos/utils/utils.py +++ b/plugins/module_utils/network/eos/utils/utils.py @@ -10,6 +10,7 @@ __metaclass__ = type +import difflib def get_interface_number(name): digits = "" @@ -82,3 +83,7 @@ def numerical_sort(string_int_list): as_int_list.append(int(vlan)) as_int_list.sort() return list(set(as_int_list)) + +def unified_diff(content1, content2): + unified_diff = difflib.unified_diff(content1, content2, n=70, lineterm='\n') + return "\n".join(unified_diff) diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 5c809386b..04316e6da 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -140,10 +140,16 @@ false, the command is issued without the all keyword type: bool default: false - diff_onbox: - description: Specify the status for on-box-diff - type: bool - default: true + off_box_diff: + description: Specify the off-box diff parameters + type: dict + suboptions: + enable: + description: Enable off box diff + type: bool + context_lines: + description: Specify The number of context lines, by default it includes all lines. + type: int save_when: description: - When changes are made to the device running-configuration, the changes are not @@ -322,6 +328,7 @@ NetworkConfig, dumps, ) +from ansible_collections.arista.eos.plugins.module_utils.network.eos.utils.utils import unified_diff from ansible_collections.arista.eos.plugins.module_utils.network.eos.eos import ( get_config, @@ -379,7 +386,9 @@ def main(): parents=dict(type="list", elements="str"), before=dict(type="list", elements="str"), after=dict(type="list", elements="str"), - diff_onbox=dict(type="bool", default=True), + off_box_diff=dict(type="dict", options=dict( + enable=dict(type=bool), context_lines=dict(type=int) + )), match=dict( default="line", choices=["line", "strict", "exact", "none"], @@ -463,7 +472,6 @@ def main(): candidate=candidate, running=running, diff_match=match, - diff_onbox=module.params["diff_onbox"], diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=replace, @@ -471,7 +479,6 @@ def main(): except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors="surrogate_then_replace")) - config_diff = response["config_diff"] if config_diff: commands = config_diff.split("\n") @@ -493,12 +500,14 @@ def main(): replace=replace, commit=commit, ) - result["changed"] = True if module.params["diff_against"] == "session": if "diff" in response: - result["diff"] = {"prepared": response["diff"]} + if module.params.get("off_box_diff"): + result["off_box_diff"] = unified_diff(candidate.split("\n"), running.split("\n")) + else: + result["diff"] = {"prepared": response["diff"]} else: result["changed"] = False @@ -624,7 +633,6 @@ def main(): result["warnings"].append(msg) else: result["warnings"] = msg - module.exit_json(**result) From fd4240dac0638658e1fa14978b96fe9e9259e54b Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 18 Dec 2023 17:37:52 +0530 Subject: [PATCH 03/14] implement unifieddiff Signed-off-by: rohitthakur2590 --- plugins/modules/eos_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 04316e6da..34b27df42 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -387,7 +387,7 @@ def main(): before=dict(type="list", elements="str"), after=dict(type="list", elements="str"), off_box_diff=dict(type="dict", options=dict( - enable=dict(type=bool), context_lines=dict(type=int) + enable=dict(type="bool"), context_lines=dict(type="int") )), match=dict( default="line", From 1420644acf4531da3ee3fcfbb7765b1099160762 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 18 Dec 2023 17:47:10 +0530 Subject: [PATCH 04/14] implement unifieddiff Signed-off-by: rohitthakur2590 --- plugins/cliconf/eos.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/cliconf/eos.py b/plugins/cliconf/eos.py index 20badd1ba..30ad512cc 100644 --- a/plugins/cliconf/eos.py +++ b/plugins/cliconf/eos.py @@ -210,7 +210,6 @@ def edit_config( resp = {} session = None - # diff_onbox = self.get_option("diff_onbox") if self.supports_sessions(): session = session_name() From c68972e8d95aa88d6ca25ec84f2b0093ab2fc2a2 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Thu, 4 Jan 2024 16:14:16 +0530 Subject: [PATCH 05/14] update tests Signed-off-by: rohitthakur2590 --- docs/arista.eos.eos_config_module.rst | 52 +++++++++++++++++++ plugins/cliconf/eos.py | 1 - .../module_utils/network/eos/utils/utils.py | 7 ++- plugins/modules/eos_config.py | 16 +++--- .../targets/eos_config/tests/cli/backup.yaml | 17 ++++++ 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/docs/arista.eos.eos_config_module.rst b/docs/arista.eos.eos_config_module.rst index 100a809fe..37b9891be 100644 --- a/docs/arista.eos.eos_config_module.rst +++ b/docs/arista.eos.eos_config_module.rst @@ -132,6 +132,58 @@ Parameters
The ordered set of commands to push on to the command stack if a change needs to be made. This allows the playbook designer the opportunity to perform configuration commands prior to pushing any changes without affecting how the set of commands are matched against the system.
+ + +
+ context_diff + +
+ dictionary +
+ + + + +
Specify the off-box diff options
+ + + + + +
+ context_lines + +
+ integer +
+ + + + +
Specify The number of context lines, by default it includes all lines.
+ + + + + +
+ enable + +
+ boolean +
+ + +
    Choices: +
  • no
  • +
  • yes
  • +
+ + +
Enable off box diff
+ + +
diff --git a/plugins/cliconf/eos.py b/plugins/cliconf/eos.py index 30ad512cc..38e384624 100644 --- a/plugins/cliconf/eos.py +++ b/plugins/cliconf/eos.py @@ -210,7 +210,6 @@ def edit_config( resp = {} session = None - if self.supports_sessions(): session = session_name() resp.update({"session": session}) diff --git a/plugins/module_utils/network/eos/utils/utils.py b/plugins/module_utils/network/eos/utils/utils.py index f19a87736..8f0c16348 100644 --- a/plugins/module_utils/network/eos/utils/utils.py +++ b/plugins/module_utils/network/eos/utils/utils.py @@ -84,6 +84,9 @@ def numerical_sort(string_int_list): as_int_list.sort() return list(set(as_int_list)) -def unified_diff(content1, content2): - unified_diff = difflib.unified_diff(content1, content2, n=70, lineterm='\n') +def unified_diff(content1, content2, count): + """ + Provide the unified diff in context to number of lines specified with count + """ + unified_diff = difflib.unified_diff(content1, content2, n=count, lineterm='\n') return "\n".join(unified_diff) diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 34b27df42..cc043cc6e 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -140,8 +140,8 @@ false, the command is issued without the all keyword type: bool default: false - off_box_diff: - description: Specify the off-box diff parameters + context_diff: + description: Specify the off-box diff options type: dict suboptions: enable: @@ -386,7 +386,7 @@ def main(): parents=dict(type="list", elements="str"), before=dict(type="list", elements="str"), after=dict(type="list", elements="str"), - off_box_diff=dict(type="dict", options=dict( + context_diff=dict(type="dict", options=dict( enable=dict(type="bool"), context_lines=dict(type="int") )), match=dict( @@ -501,11 +501,15 @@ def main(): commit=commit, ) result["changed"] = True - if module.params["diff_against"] == "session": if "diff" in response: - if module.params.get("off_box_diff"): - result["off_box_diff"] = unified_diff(candidate.split("\n"), running.split("\n")) + context_diff = module.params.get("context_diff") + if context_diff and context_diff.get("enable"): + if context_diff.get("context_lines"): + count = context_diff.get("context_lines") + else: + count = max(len(candidate), len(running)) + result["context_diff"] = unified_diff(candidate.split("\n"), running.split("\n"), count) else: result["diff"] = {"prepared": response["diff"]} else: diff --git a/tests/integration/targets/eos_config/tests/cli/backup.yaml b/tests/integration/targets/eos_config/tests/cli/backup.yaml index 11d36af97..6038520ea 100644 --- a/tests/integration/targets/eos_config/tests/cli/backup.yaml +++ b/tests/integration/targets/eos_config/tests/cli/backup.yaml @@ -97,6 +97,23 @@ that: - result.changed == true +- name: take configuration backup in custom filename + become: true + register: result + arista.eos.eos_config: + src: ./fixtures/candidate.cfg + backup: true + context_diff: + enable: true + context_lines: 10 + enable: true + backup_options: + filename: backup.cfg + +- ansible.builtin.assert: + that: + - result.context_diff is defined + - name: check if the backup file-2 exist ansible.builtin.find: paths: "{{ role_path }}/backup/backup.cfg" From 295fde7c43135fa2148b33831d6c83742d9f71ac Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Thu, 4 Jan 2024 16:54:21 +0530 Subject: [PATCH 06/14] update unit tests Signed-off-by: rohitthakur2590 --- .../tests/cli/fixtures/candidate.cfg | 41 +++++++++++++++++++ .../network/eos/fixtures/eos_candidate.cfg | 7 ++++ .../modules/network/eos/test_eos_config.py | 34 +++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 tests/integration/targets/eos_config/tests/cli/fixtures/candidate.cfg create mode 100644 tests/unit/modules/network/eos/fixtures/eos_candidate.cfg diff --git a/tests/integration/targets/eos_config/tests/cli/fixtures/candidate.cfg b/tests/integration/targets/eos_config/tests/cli/fixtures/candidate.cfg new file mode 100644 index 000000000..dc8830829 --- /dev/null +++ b/tests/integration/targets/eos_config/tests/cli/fixtures/candidate.cfg @@ -0,0 +1,41 @@ +! Command: show running-config +! device: arista (vEOS, EOS-4.24.6M) +! +! boot system flash:/vEOS-lab.swi +! +transceiver qsfp default-mode 4x10G +! +service routing protocols model ribd +! +logging buffered 81926 +logging source-interface Loopback6 +! +hostname candidate_arista_11 +ip name-server vrf default 1.1.1.1 +dns domain ansible.test +! +ntp server 1.1.1.1 local-interface Management1 +! +spanning-tree mode mstp +! +enable password sha512 $6$564ex9PpX2GFfJow$hNQ.0oKDPaFWC1NouHXZvOBk5Iutk71gyZDairQKQIqbZvNWiNYhuNEYBiX579xiK5HuLRgRNknd5dWmQNr3Y1 +no aaa root +aaa authentication policy local allow-nopassword-remote-login +! +! +interface Ethernet1 + no switchport +! +interface Ethernet2 + description "This is candidate config sample" + shutdown + no switchport +! +ip routing +! +management api http-commands + protocol http + protocol unix-socket + no shutdown +! +end \ No newline at end of file diff --git a/tests/unit/modules/network/eos/fixtures/eos_candidate.cfg b/tests/unit/modules/network/eos/fixtures/eos_candidate.cfg new file mode 100644 index 000000000..87266dcbd --- /dev/null +++ b/tests/unit/modules/network/eos/fixtures/eos_candidate.cfg @@ -0,0 +1,7 @@ +hostname switch02 +! +interface Ethernet1 + description test interface + no shutdown +! +ip routing diff --git a/tests/unit/modules/network/eos/test_eos_config.py b/tests/unit/modules/network/eos/test_eos_config.py index 3a28710ee..47bedb645 100644 --- a/tests/unit/modules/network/eos/test_eos_config.py +++ b/tests/unit/modules/network/eos/test_eos_config.py @@ -299,6 +299,40 @@ def test_eos_config_src_replace(self): result["commands"], ) + def test_eos_config_context_diff(self): + src = load_fixture("eos_candidate.cfg") + args = dict(src=src, + backup=True, + context_diff=dict(enable=True), + backup_options=dict( + filename="backup.cfg", + dir_path="./" + ), + ) + set_module_args(args) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff(src, self.running_config), + ) + result = self.execute_module(changed=True) + self.assertIn("context_diff", result) + + def test_eos_config_context_diff_lines(self): + src = load_fixture("eos_candidate.cfg") + args = dict(src=src, + backup=True, + context_diff=dict(enable=True, context_lines=10), + backup_options=dict( + filename="backup.cfg", + dir_path="./" + ), + ) + set_module_args(args) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff(src, self.running_config), + ) + result = self.execute_module(changed=True) + self.assertIn("context_diff", result) + def test_eos_config_lines_block(self): lines = ["hostname switch01", "ip domain-name eng.ansible.com"] args = dict(lines=lines, replace="block") From 5f275c7af25ce377d426e99f7f56fbff1153b2e9 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Thu, 4 Jan 2024 18:25:25 +0530 Subject: [PATCH 07/14] update file paths Signed-off-by: rohitthakur2590 --- .../fixtures/candidate.cfg => templates/defaults/candidate.j2} | 0 tests/integration/targets/eos_config/tests/cli/backup.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/integration/targets/eos_config/{tests/cli/fixtures/candidate.cfg => templates/defaults/candidate.j2} (100%) diff --git a/tests/integration/targets/eos_config/tests/cli/fixtures/candidate.cfg b/tests/integration/targets/eos_config/templates/defaults/candidate.j2 similarity index 100% rename from tests/integration/targets/eos_config/tests/cli/fixtures/candidate.cfg rename to tests/integration/targets/eos_config/templates/defaults/candidate.j2 diff --git a/tests/integration/targets/eos_config/tests/cli/backup.yaml b/tests/integration/targets/eos_config/tests/cli/backup.yaml index 6038520ea..79dfe0dd2 100644 --- a/tests/integration/targets/eos_config/tests/cli/backup.yaml +++ b/tests/integration/targets/eos_config/tests/cli/backup.yaml @@ -101,7 +101,7 @@ become: true register: result arista.eos.eos_config: - src: ./fixtures/candidate.cfg + src: defaults/candidate.j2 backup: true context_diff: enable: true From cb25aff9eefd56d6688eeea34027a2ad8e913088 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Fri, 5 Jan 2024 14:49:24 +0530 Subject: [PATCH 08/14] update tests Signed-off-by: rohitthakur2590 --- tests/integration/targets/eos_config/tests/cli/backup.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/targets/eos_config/tests/cli/backup.yaml b/tests/integration/targets/eos_config/tests/cli/backup.yaml index 79dfe0dd2..955ed39da 100644 --- a/tests/integration/targets/eos_config/tests/cli/backup.yaml +++ b/tests/integration/targets/eos_config/tests/cli/backup.yaml @@ -97,7 +97,7 @@ that: - result.changed == true -- name: take configuration backup in custom filename +- name: get the context diff with backup config become: true register: result arista.eos.eos_config: @@ -106,7 +106,6 @@ context_diff: enable: true context_lines: 10 - enable: true backup_options: filename: backup.cfg From 768032e4d9a7ea76a07c385cbb7aa2b7ccd8004a Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 8 Jan 2024 16:03:13 +0530 Subject: [PATCH 09/14] update tests Signed-off-by: rohitthakur2590 --- plugins/cliconf/eos.py | 2 +- .../templates/defaults/candidate.j2 | 33 ------------------- .../targets/eos_config/tests/cli/backup.yaml | 2 +- 3 files changed, 2 insertions(+), 35 deletions(-) diff --git a/plugins/cliconf/eos.py b/plugins/cliconf/eos.py index 38e384624..9c6fb753c 100644 --- a/plugins/cliconf/eos.py +++ b/plugins/cliconf/eos.py @@ -378,6 +378,7 @@ def get_diff( else: configdiffobjs = candidate_obj.items + diff["config_diff"] = dumps(configdiffobjs, "commands") if configdiffobjs else "" return diff @@ -449,7 +450,6 @@ def get_option_values(self): "format": ["text", "json"], "diff_match": ["line", "strict", "exact", "none"], "diff_replace": ["line", "block", "config"], - "diff_onbox": [True, False], "output": ["text", "json"], } diff --git a/tests/integration/targets/eos_config/templates/defaults/candidate.j2 b/tests/integration/targets/eos_config/templates/defaults/candidate.j2 index dc8830829..d18ff28b0 100644 --- a/tests/integration/targets/eos_config/templates/defaults/candidate.j2 +++ b/tests/integration/targets/eos_config/templates/defaults/candidate.j2 @@ -1,41 +1,8 @@ ! Command: show running-config -! device: arista (vEOS, EOS-4.24.6M) -! -! boot system flash:/vEOS-lab.swi -! -transceiver qsfp default-mode 4x10G -! -service routing protocols model ribd -! -logging buffered 81926 -logging source-interface Loopback6 -! -hostname candidate_arista_11 -ip name-server vrf default 1.1.1.1 -dns domain ansible.test -! -ntp server 1.1.1.1 local-interface Management1 -! -spanning-tree mode mstp -! -enable password sha512 $6$564ex9PpX2GFfJow$hNQ.0oKDPaFWC1NouHXZvOBk5Iutk71gyZDairQKQIqbZvNWiNYhuNEYBiX579xiK5HuLRgRNknd5dWmQNr3Y1 -no aaa root -aaa authentication policy local allow-nopassword-remote-login -! -! -interface Ethernet1 - no switchport ! interface Ethernet2 description "This is candidate config sample" shutdown no switchport ! -ip routing -! -management api http-commands - protocol http - protocol unix-socket - no shutdown -! end \ No newline at end of file diff --git a/tests/integration/targets/eos_config/tests/cli/backup.yaml b/tests/integration/targets/eos_config/tests/cli/backup.yaml index 955ed39da..8fa491684 100644 --- a/tests/integration/targets/eos_config/tests/cli/backup.yaml +++ b/tests/integration/targets/eos_config/tests/cli/backup.yaml @@ -107,7 +107,7 @@ enable: true context_lines: 10 backup_options: - filename: backup.cfg + filename: running_backup.cfg - ansible.builtin.assert: that: From 5ba12baa4ec6fedfa4eb14727fcff80129226623 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 8 Jan 2024 19:05:48 +0530 Subject: [PATCH 10/14] Update return param and example Signed-off-by: rohitthakur2590 --- .../fragments/off_box_diff_enhancement.yaml | 2 +- docs/arista.eos.eos_config_module.rst | 27 +++++++++++++++++++ plugins/modules/eos_config.py | 20 ++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/changelogs/fragments/off_box_diff_enhancement.yaml b/changelogs/fragments/off_box_diff_enhancement.yaml index 9a5c74391..e42f846aa 100644 --- a/changelogs/fragments/off_box_diff_enhancement.yaml +++ b/changelogs/fragments/off_box_diff_enhancement.yaml @@ -1,3 +1,3 @@ --- minor_changes: - - Implement off-box-diff optional feature. + - eos_config - Implement off-box-diff optional feature. diff --git a/docs/arista.eos.eos_config_module.rst b/docs/arista.eos.eos_config_module.rst index 37b9891be..24bf4ceb1 100644 --- a/docs/arista.eos.eos_config_module.rst +++ b/docs/arista.eos.eos_config_module.rst @@ -449,6 +449,16 @@ Examples filename: backup.cfg dir_path: /home/user + - name:Get the full context diff + arista.eos.eos_config: + src: candidate.cfg + backup: true + context_diff: + enable: true + backup_options: + filename: backup.cfg + dir_path: /home/user + Return Values @@ -497,6 +507,23 @@ Common return values are documented `here ['hostname switch01', 'interface Ethernet1', 'no shutdown'] + + +
+ context_diff + +
+ string +
+ + + +
The diff between candidate and target config.
+
+
Sample:
+
' --- +++ @@ -1,7 +1,7 @@ ! Command: show running-config -! device: arista (vEOS, EOS-4.24.6M) +! device: candidate-arista-11 (vEOS, EOS-4.24.6M)'
+ +
diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index cc043cc6e..cc19f8e22 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -282,6 +282,16 @@ backup_options: filename: backup.cfg dir_path: /home/user + +- name:Get the full context diff + arista.eos.eos_config: + src: candidate.cfg + backup: true + context_diff: + enable: true + backup_options: + filename: backup.cfg + dir_path: /home/user """ RETURN = """ @@ -320,6 +330,16 @@ returned: when backup is true type: str sample: "22:28:34" +context_diff: + description: The diff between candidate and target config. + type: str + sample: ''' + --- + +++ + @@ -1,7 +1,7 @@ + ! Command: show running-config + -! device: arista (vEOS, EOS-4.24.6M) + +! device: candidate-arista-11 (vEOS, EOS-4.24.6M)''' """ from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule From ea5b00ba3eb7fe9672b4e921b4beeea456c32523 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 8 Jan 2024 19:17:48 +0530 Subject: [PATCH 11/14] Update return param and example Signed-off-by: rohitthakur2590 --- docs/arista.eos.eos_config_module.rst | 2 +- plugins/modules/eos_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/arista.eos.eos_config_module.rst b/docs/arista.eos.eos_config_module.rst index 24bf4ceb1..83e4d737f 100644 --- a/docs/arista.eos.eos_config_module.rst +++ b/docs/arista.eos.eos_config_module.rst @@ -449,7 +449,7 @@ Examples filename: backup.cfg dir_path: /home/user - - name:Get the full context diff + - name: Get the full context diff arista.eos.eos_config: src: candidate.cfg backup: true diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index cc19f8e22..97dd1f710 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -283,7 +283,7 @@ filename: backup.cfg dir_path: /home/user -- name:Get the full context diff +- name: Get the full context diff arista.eos.eos_config: src: candidate.cfg backup: true From 6d4f4f851612d154fde724e71c1e8014b3547802 Mon Sep 17 00:00:00 2001 From: rohitthakur2590 Date: Mon, 15 Jan 2024 17:32:02 +0530 Subject: [PATCH 12/14] update with retruned key Signed-off-by: rohitthakur2590 --- docs/arista.eos.eos_config_module.rst | 2 +- plugins/modules/eos_config.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/arista.eos.eos_config_module.rst b/docs/arista.eos.eos_config_module.rst index 83e4d737f..39285b781 100644 --- a/docs/arista.eos.eos_config_module.rst +++ b/docs/arista.eos.eos_config_module.rst @@ -516,7 +516,7 @@ Common return values are documented `here string - + when user opt for off-box-diff through context_diff option.
The diff between candidate and target config.

diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 97dd1f710..5377db5c5 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -332,6 +332,7 @@ sample: "22:28:34" context_diff: description: The diff between candidate and target config. + returned: when user opt for off-box-diff through context_diff option. type: str sample: ''' --- From 2e6a1ff1e5515e702a501d7ef0ac4194e672ce70 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:02:40 +0000 Subject: [PATCH 13/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../module_utils/network/eos/utils/utils.py | 4 ++- plugins/modules/eos_config.py | 18 ++++++---- .../templates/defaults/candidate.j2 | 4 +-- .../modules/network/eos/test_eos_config.py | 34 ++++++++++--------- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/plugins/module_utils/network/eos/utils/utils.py b/plugins/module_utils/network/eos/utils/utils.py index 8f0c16348..109ea7fb1 100644 --- a/plugins/module_utils/network/eos/utils/utils.py +++ b/plugins/module_utils/network/eos/utils/utils.py @@ -12,6 +12,7 @@ import difflib + def get_interface_number(name): digits = "" for char in name: @@ -84,9 +85,10 @@ def numerical_sort(string_int_list): as_int_list.sort() return list(set(as_int_list)) + def unified_diff(content1, content2, count): """ Provide the unified diff in context to number of lines specified with count """ - unified_diff = difflib.unified_diff(content1, content2, n=count, lineterm='\n') + unified_diff = difflib.unified_diff(content1, content2, n=count, lineterm="\n") return "\n".join(unified_diff) diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 5377db5c5..6b617d5f7 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -349,7 +349,6 @@ NetworkConfig, dumps, ) -from ansible_collections.arista.eos.plugins.module_utils.network.eos.utils.utils import unified_diff from ansible_collections.arista.eos.plugins.module_utils.network.eos.eos import ( get_config, @@ -358,6 +357,7 @@ load_config, run_commands, ) +from ansible_collections.arista.eos.plugins.module_utils.network.eos.utils.utils import unified_diff def get_candidate(module): @@ -407,9 +407,13 @@ def main(): parents=dict(type="list", elements="str"), before=dict(type="list", elements="str"), after=dict(type="list", elements="str"), - context_diff=dict(type="dict", options=dict( - enable=dict(type="bool"), context_lines=dict(type="int") - )), + context_diff=dict( + type="dict", + options=dict( + enable=dict(type="bool"), + context_lines=dict(type="int"), + ), + ), match=dict( default="line", choices=["line", "strict", "exact", "none"], @@ -524,13 +528,15 @@ def main(): result["changed"] = True if module.params["diff_against"] == "session": if "diff" in response: - context_diff = module.params.get("context_diff") + context_diff = module.params.get("context_diff") if context_diff and context_diff.get("enable"): if context_diff.get("context_lines"): count = context_diff.get("context_lines") else: count = max(len(candidate), len(running)) - result["context_diff"] = unified_diff(candidate.split("\n"), running.split("\n"), count) + result["context_diff"] = unified_diff( + candidate.split("\n"), running.split("\n"), count + ) else: result["diff"] = {"prepared": response["diff"]} else: diff --git a/tests/integration/targets/eos_config/templates/defaults/candidate.j2 b/tests/integration/targets/eos_config/templates/defaults/candidate.j2 index d18ff28b0..a8ac1b2f2 100644 --- a/tests/integration/targets/eos_config/templates/defaults/candidate.j2 +++ b/tests/integration/targets/eos_config/templates/defaults/candidate.j2 @@ -1,8 +1,8 @@ ! Command: show running-config ! interface Ethernet2 - description "This is candidate config sample" + description "This is candidate config sample" shutdown no switchport ! -end \ No newline at end of file +end diff --git a/tests/unit/modules/network/eos/test_eos_config.py b/tests/unit/modules/network/eos/test_eos_config.py index 47bedb645..959c5c2f9 100644 --- a/tests/unit/modules/network/eos/test_eos_config.py +++ b/tests/unit/modules/network/eos/test_eos_config.py @@ -301,14 +301,15 @@ def test_eos_config_src_replace(self): def test_eos_config_context_diff(self): src = load_fixture("eos_candidate.cfg") - args = dict(src=src, - backup=True, - context_diff=dict(enable=True), - backup_options=dict( - filename="backup.cfg", - dir_path="./" - ), - ) + args = dict( + src=src, + backup=True, + context_diff=dict(enable=True), + backup_options=dict( + filename="backup.cfg", + dir_path="./", + ), + ) set_module_args(args) self.conn.get_diff = MagicMock( return_value=self.cliconf_obj.get_diff(src, self.running_config), @@ -318,14 +319,15 @@ def test_eos_config_context_diff(self): def test_eos_config_context_diff_lines(self): src = load_fixture("eos_candidate.cfg") - args = dict(src=src, - backup=True, - context_diff=dict(enable=True, context_lines=10), - backup_options=dict( - filename="backup.cfg", - dir_path="./" - ), - ) + args = dict( + src=src, + backup=True, + context_diff=dict(enable=True, context_lines=10), + backup_options=dict( + filename="backup.cfg", + dir_path="./", + ), + ) set_module_args(args) self.conn.get_diff = MagicMock( return_value=self.cliconf_obj.get_diff(src, self.running_config), From 8b52b55ee188ad0bec5ff31bd4922d1dda6b7416 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:07:38 +0000 Subject: [PATCH 14/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- plugins/modules/eos_config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/modules/eos_config.py b/plugins/modules/eos_config.py index 6b617d5f7..4b79a3712 100644 --- a/plugins/modules/eos_config.py +++ b/plugins/modules/eos_config.py @@ -535,7 +535,9 @@ def main(): else: count = max(len(candidate), len(running)) result["context_diff"] = unified_diff( - candidate.split("\n"), running.split("\n"), count + candidate.split("\n"), + running.split("\n"), + count, ) else: result["diff"] = {"prepared": response["diff"]}