From a1c3ce0ad17f080e009ad9c8f1cc6173e2b67575 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Tue, 27 Sep 2016 18:59:19 -0400 Subject: [PATCH] fixes error when 'delete ...' config command is specified but doesn't exist (#5064) The junos_config module will generate an exception if a 'delete ...' config command is attempted to be loaded into a device configuration. This change will first check to see if the delete command is valid and filter it out of the change set if it is not valid. fixes #5040 --- network/junos/junos_config.py | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/network/junos/junos_config.py b/network/junos/junos_config.py index d7458d956c7..30a2286097b 100644 --- a/network/junos/junos_config.py +++ b/network/junos/junos_config.py @@ -166,6 +166,7 @@ import ansible.module_utils.junos from ansible.module_utils.basic import get_exception from ansible.module_utils.network import NetworkModule, NetworkError +from ansible.module_utils.netcfg import NetworkConfig DEFAULT_COMMENT = 'configured by junos_config' @@ -189,6 +190,46 @@ def guess_format(config): return 'text' +def config_to_commands(config): + set_format = config.startswith('set') or config.startswith('delete') + candidate = NetworkConfig(indent=4, contents=config, device_os='junos') + if not set_format: + candidate = [c.line for c in candidate.items] + commands = list() + # this filters out less specific lines + for item in candidate: + for index, entry in enumerate(commands): + if item.startswith(entry): + del commands[index] + break + commands.append(item) + + else: + commands = str(candidate).split('\n') + + return commands + +def diff_commands(commands, config): + config = [str(c).replace("'", '') for c in config] + + updates = list() + visited = set() + + for item in commands: + if not item.startswith('set') and not item.startswith('delete'): + raise ValueError('line must start with either `set` or `delete`') + + elif item.startswith('set') and item[4:] not in config: + updates.append(item) + + elif item.startswith('delete'): + for entry in config: + if entry.startswith(item[7:]) and item not in visited: + updates.append(item) + visited.add(item) + + return updates + def load_config(module, result): candidate = module.params['lines'] or module.params['src'] @@ -204,6 +245,13 @@ def load_config(module, result): config_format = 'set' kwargs['config_format'] = config_format + # this is done to filter out `delete ...` statements which map to + # nothing in the config as that will cause an exception to be raised + if config_format == 'set': + config = module.config.get_config() + config = config_to_commands(config) + candidate = diff_commands(candidate, config) + diff = module.config.load_config(candidate, **kwargs) if diff: