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 0000000000..364013afc8 --- /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 (https://github.com/ansible-collections/community.general/pull/9657). +minor_changes: + - lldp - adds ``multivalues`` parameter to control behavior when lldpctl outputs an attribute multiple times (https://github.com/ansible-collections/community.general/pull/9657). diff --git a/plugins/modules/lldp.py b/plugins/modules/lldp.py index baefb09d91..7f4a820257 100644 --- a/plugins/modules/lldp.py +++ b/plugins/modules/lldp.py @@ -22,7 +22,12 @@ attributes: 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,26 +58,49 @@ def gather_lldp(module): if output: output_dict = {} current_dict = {} - lldp_entries = output.split("\n") + lldp_entries = output.strip().split("\n") + final = "" for entry in lldp_entries: if entry.startswith('lldp'): path, value = entry.strip().split("=", 1) path = path.split(".") path_components, final = path[:-1], path[-1] + elif final in current_dict and isinstance(current_dict[final], str): + current_dict[final] += '\n' + entry + continue + elif final in current_dict and isinstance(current_dict[final], list): + current_dict[final][-1] += '\n' + entry + continue else: - value = 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 not isinstance(current_dict[path_component], dict): + current_dict[path_component] = {'value': current_dict[path_component]} current_dict = current_dict[path_component] - current_dict[final] = value + + if final in current_dict and isinstance(current_dict[final], dict) and module.params['multivalues']: + current_dict = current_dict[final] + final = 'value' + + if final not in current_dict or not module.params['multivalues']: + current_dict[final] = value + elif isinstance(current_dict[final], str): + current_dict[final] = [current_dict[final], value] + elif isinstance(current_dict[final], list): + current_dict[final].append(value) + return output_dict def main(): - module = AnsibleModule({}) + module_args = dict( + multivalues=dict(type='bool', required=False, default=False) + ) + module = AnsibleModule(module_args) lldp_output = gather_lldp(module) try: