From 7b46703e6f23c78c06a70e71f2b4d4499264c61d Mon Sep 17 00:00:00 2001 From: Julian Wecke Date: Fri, 31 Jan 2025 16:53:59 +0100 Subject: [PATCH 1/3] lldp: Ignoring values for keys already defined This fixes crashes when the lldpctl output has lines for unknown tlvs that redefine a key in the middle of the nested dict data structure. --- plugins/modules/lldp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/modules/lldp.py b/plugins/modules/lldp.py index baefb09d912..ceca32d2782 100644 --- a/plugins/modules/lldp.py +++ b/plugins/modules/lldp.py @@ -67,7 +67,8 @@ def gather_lldp(module): for path_component in path_components: current_dict[path_component] = current_dict.get(path_component, {}) current_dict = current_dict[path_component] - current_dict[final] = value + if final not in current_dict: + current_dict[final] = value return output_dict From 12c9d57a765db20dd6808a39aa5d3c41fd0c76f4 Mon Sep 17 00:00:00 2001 From: Julian Wecke Date: Sat, 1 Feb 2025 20:37:34 +0100 Subject: [PATCH 2/3] lldp: handling attributes that are defined multiple times - Fix crash caused by certain lldpctl output where an attribute is defined as branch and leaf - Adds multivalues parameter to control behavior when lldpctl outputs an attribute multiple times --- ...ling-attributes-defined-multiple-times.yml | 4 +++ plugins/modules/lldp.py | 31 ++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/9657-lldp-handling-attributes-defined-multiple-times.yml diff --git a/changelogs/fragments/9657-lldp-handling-attributes-defined-multiple-times.yml b/changelogs/fragments/9657-lldp-handling-attributes-defined-multiple-times.yml new file mode 100644 index 00000000000..d98e68439de --- /dev/null +++ b/changelogs/fragments/9657-lldp-handling-attributes-defined-multiple-times.yml @@ -0,0 +1,4 @@ +bugfixes: + - lldp - fix crash caused by certain lldpctl output where an attribute is defined as branch and leaf +minor_changes: + - lldp - adds ``multivalues`` parameter to control behavior when lldpctl outputs an attribute multiple times diff --git a/plugins/modules/lldp.py b/plugins/modules/lldp.py index ceca32d2782..8b3d2856b92 100644 --- a/plugins/modules/lldp.py +++ b/plugins/modules/lldp.py @@ -22,7 +22,12 @@ support: none diff_mode: support: none -options: {} +options: + multivalues: + description: If lldpctl outputs an attribute multiple time represent all values as a list. + required: false + type: bool + default: false author: "Andy Hill (@andyhky)" notes: - Requires C(lldpd) running and LLDP enabled on switches. @@ -53,7 +58,7 @@ def gather_lldp(module): if output: output_dict = {} current_dict = {} - lldp_entries = output.split("\n") + lldp_entries = output.strip().split("\n") for entry in lldp_entries: if entry.startswith('lldp'): @@ -61,19 +66,35 @@ def gather_lldp(module): path = path.split(".") path_components, final = path[:-1], path[-1] else: - value = current_dict[final] + '\n' + entry + current_dict[final] += '\n' + entry + continue current_dict = output_dict for path_component in path_components: current_dict[path_component] = current_dict.get(path_component, {}) + if type(current_dict[path_component]) is not dict: + current_dict[path_component] = {'value': current_dict[path_component]} current_dict = current_dict[path_component] - if final not in current_dict: + + if final in current_dict and type(current_dict[final]) is dict: + current_dict = current_dict[final] + final = 'value' + + if final not in current_dict or not module.params['multivalues']: current_dict[final] = value + elif type(current_dict[final]) is str: + current_dict[final] = [current_dict[final], value] + elif type(current_dict[final]) is list: + current_dict[final].append(value) + return output_dict def main(): - module = AnsibleModule({}) + module_args = dict( + multivalues=dict(type='bool', equired=False, default=False) + ) + module = AnsibleModule(module_args) lldp_output = gather_lldp(module) try: From 636595c6a07130547a7b34488dfca20571c4fd6d Mon Sep 17 00:00:00 2001 From: Julian Wecke Date: Sun, 2 Feb 2025 09:58:57 +0100 Subject: [PATCH 3/3] lldp: using isinstance instead of type --- plugins/modules/lldp.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/modules/lldp.py b/plugins/modules/lldp.py index 8b3d2856b92..71d9253660d 100644 --- a/plugins/modules/lldp.py +++ b/plugins/modules/lldp.py @@ -72,19 +72,19 @@ def gather_lldp(module): current_dict = output_dict for path_component in path_components: current_dict[path_component] = current_dict.get(path_component, {}) - if type(current_dict[path_component]) is not dict: + if not isinstance(current_dict[path_component], dict): current_dict[path_component] = {'value': current_dict[path_component]} current_dict = current_dict[path_component] - if final in current_dict and type(current_dict[final]) is dict: + if final in current_dict and isinstance(current_dict[final], dict): current_dict = current_dict[final] final = 'value' if final not in current_dict or not module.params['multivalues']: current_dict[final] = value - elif type(current_dict[final]) is str: + elif isinstance(current_dict[final], str): current_dict[final] = [current_dict[final], value] - elif type(current_dict[final]) is list: + elif isinstance(current_dict[final], list): current_dict[final].append(value) return output_dict @@ -92,7 +92,7 @@ def gather_lldp(module): def main(): module_args = dict( - multivalues=dict(type='bool', equired=False, default=False) + multivalues=dict(type='bool', required=False, default=False) ) module = AnsibleModule(module_args)