diff options
author | ansible-zuul[bot] <48994755+ansible-zuul[bot]@users.noreply.github.com> | 2019-08-09 18:52:36 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-09 18:52:36 +0000 |
commit | fbe294b702e757252a66f64edf66bce060e87494 (patch) | |
tree | 6910d3c526815c0e21f20cfbccd08bea727cf11c /plugins/modules | |
parent | 4a485b24db1abf87cdf0d4ef2f7acb1159aaab68 (diff) | |
parent | 5fb9df4e907a6ab2da7a6c2dafdec9c1971e8d44 (diff) | |
download | vyos-ansible-collection-fbe294b702e757252a66f64edf66bce060e87494.tar.gz vyos-ansible-collection-fbe294b702e757252a66f64edf66bce060e87494.zip |
Merge pull request #8 from ansible-network/bt_blacked
Bt blacked
Reviewed-by: Paul Belanger
https://github.com/pabelanger
Diffstat (limited to 'plugins/modules')
-rw-r--r-- | plugins/modules/_vyos_interface.py | 250 | ||||
-rw-r--r-- | plugins/modules/_vyos_l3_interface.py | 143 | ||||
-rw-r--r-- | plugins/modules/vyos_banner.py | 87 | ||||
-rw-r--r-- | plugins/modules/vyos_command.py | 58 | ||||
-rw-r--r-- | plugins/modules/vyos_config.py | 121 | ||||
-rw-r--r-- | plugins/modules/vyos_facts.py | 35 | ||||
-rw-r--r-- | plugins/modules/vyos_interfaces.py | 25 | ||||
-rw-r--r-- | plugins/modules/vyos_l3_interfaces.py | 27 | ||||
-rw-r--r-- | plugins/modules/vyos_linkagg.py | 143 | ||||
-rw-r--r-- | plugins/modules/vyos_lldp.py | 51 | ||||
-rw-r--r-- | plugins/modules/vyos_lldp_interface.py | 98 | ||||
-rw-r--r-- | plugins/modules/vyos_logging.py | 169 | ||||
-rw-r--r-- | plugins/modules/vyos_ping.py | 38 | ||||
-rw-r--r-- | plugins/modules/vyos_static_route.py | 178 | ||||
-rw-r--r-- | plugins/modules/vyos_system.py | 94 | ||||
-rw-r--r-- | plugins/modules/vyos_user.py | 147 | ||||
-rw-r--r-- | plugins/modules/vyos_vlan.py | 188 |
17 files changed, 1005 insertions, 847 deletions
diff --git a/plugins/modules/_vyos_interface.py b/plugins/modules/_vyos_interface.py index e4b989e..ee82107 100644 --- a/plugins/modules/_vyos_interface.py +++ b/plugins/modules/_vyos_interface.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['deprecated'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -174,17 +176,19 @@ from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.connection import exec_command from ansible.module_utils.network.common.utils import conditional, remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import load_config, get_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + get_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def search_obj_in_list(name, lst): for o in lst: - if o['name'] == name: + if o["name"] == name: return o return None @@ -194,92 +198,92 @@ def map_obj_to_commands(updates): commands = list() want, have = updates - params = ('speed', 'description', 'duplex', 'mtu') + params = ("speed", "description", "duplex", "mtu") for w in want: - name = w['name'] - disable = w['disable'] - state = w['state'] + name = w["name"] + disable = w["disable"] + state = w["state"] obj_in_have = search_obj_in_list(name, have) - set_interface = 'set interfaces ethernet ' + name - delete_interface = 'delete interfaces ethernet ' + name + set_interface = "set interfaces ethernet " + name + delete_interface = "delete interfaces ethernet " + name - if state == 'absent' and obj_in_have: + if state == "absent" and obj_in_have: commands.append(delete_interface) - elif state in ('present', 'up', 'down'): + elif state in ("present", "up", "down"): if obj_in_have: for item in params: value = w.get(item) if value and value != obj_in_have.get(item): - if item == 'description': - value = "\'" + str(value) + "\'" - commands.append(set_interface + ' ' + item + ' ' + str(value)) - - if disable and not obj_in_have.get('disable', False): - commands.append(set_interface + ' disable') - elif not disable and obj_in_have.get('disable', False): - commands.append(delete_interface + ' disable') + if item == "description": + value = "'" + str(value) + "'" + commands.append(set_interface + " " + item + " " + str(value)) + + if disable and not obj_in_have.get("disable", False): + commands.append(set_interface + " disable") + elif not disable and obj_in_have.get("disable", False): + commands.append(delete_interface + " disable") else: commands.append(set_interface) for item in params: value = w.get(item) if value: - if item == 'description': - value = "\'" + str(value) + "\'" - commands.append(set_interface + ' ' + item + ' ' + str(value)) + if item == "description": + value = "'" + str(value) + "'" + commands.append(set_interface + " " + item + " " + str(value)) if disable: - commands.append(set_interface + ' disable') + commands.append(set_interface + " disable") return commands def map_config_to_obj(module): - data = get_config(module, flags=['| grep interface']) + data = get_config(module, flags=["| grep interface"]) obj = [] - for line in data.split('\n'): - if line.startswith('set interfaces ethernet'): - match = re.search(r'set interfaces ethernet (\S+)', line, re.M) + for line in data.split("\n"): + if line.startswith("set interfaces ethernet"): + match = re.search(r"set interfaces ethernet (\S+)", line, re.M) name = match.group(1) if name: interface = {} for item in obj: - if item['name'] == name: + if item["name"] == name: interface = item break if not interface: - interface = {'name': name} + interface = {"name": name} obj.append(interface) - match = re.search(r'%s (\S+)' % name, line, re.M) + match = re.search(r"%s (\S+)" % name, line, re.M) if match: param = match.group(1) - if param == 'description': - match = re.search(r'description (.+)', line, re.M) + if param == "description": + match = re.search(r"description (.+)", line, re.M) description = match.group(1).strip("'") - interface['description'] = description - elif param == 'speed': - match = re.search(r'speed (\S+)', line, re.M) + interface["description"] = description + elif param == "speed": + match = re.search(r"speed (\S+)", line, re.M) speed = match.group(1).strip("'") - interface['speed'] = speed - elif param == 'mtu': - match = re.search(r'mtu (\S+)', line, re.M) + interface["speed"] = speed + elif param == "mtu": + match = re.search(r"mtu (\S+)", line, re.M) mtu = match.group(1).strip("'") - interface['mtu'] = int(mtu) - elif param == 'duplex': - match = re.search(r'duplex (\S+)', line, re.M) + interface["mtu"] = int(mtu) + elif param == "duplex": + match = re.search(r"duplex (\S+)", line, re.M) duplex = match.group(1).strip("'") - interface['duplex'] = duplex - elif param.strip("'") == 'disable': - interface['disable'] = True + interface["duplex"] = duplex + elif param.strip("'") == "disable": + interface["disable"] = True return obj def map_params_to_obj(module): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -287,28 +291,28 @@ def map_params_to_obj(module): item[key] = module.params[key] d = item.copy() - if d['enabled']: - d['disable'] = False + if d["enabled"]: + d["disable"] = False else: - d['disable'] = True + d["disable"] = True obj.append(d) else: params = { - 'name': module.params['name'], - 'description': module.params['description'], - 'speed': module.params['speed'], - 'mtu': module.params['mtu'], - 'duplex': module.params['duplex'], - 'delay': module.params['delay'], - 'state': module.params['state'], - 'neighbors': module.params['neighbors'] + "name": module.params["name"], + "description": module.params["description"], + "speed": module.params["speed"], + "mtu": module.params["mtu"], + "duplex": module.params["duplex"], + "delay": module.params["delay"], + "state": module.params["state"], + "neighbors": module.params["neighbors"], } - if module.params['enabled']: - params.update({'disable': False}) + if module.params["enabled"]: + params.update({"disable": False}) else: - params.update({'disable': True}) + params.update({"disable": True}) obj.append(params) return obj @@ -318,53 +322,65 @@ def check_declarative_intent_params(module, want, result): failed_conditions = [] have_neighbors = None for w in want: - want_state = w.get('state') - want_neighbors = w.get('neighbors') + want_state = w.get("state") + want_neighbors = w.get("neighbors") - if want_state not in ('up', 'down') and not want_neighbors: + if want_state not in ("up", "down") and not want_neighbors: continue - if result['changed']: - sleep(w['delay']) + if result["changed"]: + sleep(w["delay"]) - command = 'show interfaces ethernet %s' % w['name'] + command = "show interfaces ethernet %s" % w["name"] rc, out, err = exec_command(module, command) if rc != 0: - module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) - - if want_state in ('up', 'down'): - match = re.search(r'%s (\w+)' % 'state', out, re.M) + module.fail_json( + msg=to_text(err, errors="surrogate_then_replace"), + command=command, + rc=rc, + ) + + if want_state in ("up", "down"): + match = re.search(r"%s (\w+)" % "state", out, re.M) have_state = None if match: have_state = match.group(1) - if have_state is None or not conditional(want_state, have_state.strip().lower()): - failed_conditions.append('state ' + 'eq(%s)' % want_state) + if have_state is None or not conditional( + want_state, have_state.strip().lower() + ): + failed_conditions.append("state " + "eq(%s)" % want_state) if want_neighbors: have_host = [] have_port = [] if have_neighbors is None: - rc, have_neighbors, err = exec_command(module, 'show lldp neighbors detail') + rc, have_neighbors, err = exec_command( + module, "show lldp neighbors detail" + ) if rc != 0: - module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) + module.fail_json( + msg=to_text(err, errors="surrogate_then_replace"), + command=command, + rc=rc, + ) if have_neighbors: - lines = have_neighbors.strip().split('Interface: ') + lines = have_neighbors.strip().split("Interface: ") for line in lines: - field = line.split('\n') - if field[0].split(',')[0].strip() == w['name']: + field = line.split("\n") + if field[0].split(",")[0].strip() == w["name"]: for item in field: - if item.strip().startswith('SysName:'): - have_host.append(item.split(':')[1].strip()) - if item.strip().startswith('PortDescr:'): - have_port.append(item.split(':')[1].strip()) + if item.strip().startswith("SysName:"): + have_host.append(item.split(":")[1].strip()) + if item.strip().startswith("PortDescr:"): + have_port.append(item.split(":")[1].strip()) for item in want_neighbors: - host = item.get('host') - port = item.get('port') + host = item.get("host") + port = item.get("port") if host and host not in have_host: - failed_conditions.append('host ' + host) + failed_conditions.append("host " + host) if port and port not in have_port: - failed_conditions.append('port ' + port) + failed_conditions.append("port " + port) return failed_conditions @@ -372,75 +388,73 @@ def check_declarative_intent_params(module, want, result): def main(): """ main entry point for module execution """ - neighbors_spec = dict( - host=dict(), - port=dict() - ) + neighbors_spec = dict(host=dict(), port=dict()) element_spec = dict( name=dict(), description=dict(), speed=dict(), - mtu=dict(type='int'), - duplex=dict(choices=['full', 'half', 'auto']), - enabled=dict(default=True, type='bool'), - neighbors=dict(type='list', elements='dict', options=neighbors_spec), - delay=dict(default=10, type='int'), - state=dict(default='present', - choices=['present', 'absent', 'up', 'down']) + mtu=dict(type="int"), + duplex=dict(choices=["full", "half", "auto"]), + enabled=dict(default=True, type="bool"), + neighbors=dict(type="list", elements="dict", options=neighbors_spec), + delay=dict(default=10, type="int"), + state=dict(default="present", choices=["present", "absent", "up", "down"]), ) aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) + aggregate_spec["name"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), + aggregate=dict(type="list", elements="dict", options=aggregate_spec) ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_one_of = [['name', 'aggregate']] - mutually_exclusive = [['name', 'aggregate']] + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] - required_together = [['speed', 'duplex']] - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - required_together=required_together, - supports_check_mode=True) + required_together = [["speed", "duplex"]] + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + supports_check_mode=True, + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = map_config_to_obj(module) commands = map_obj_to_commands((want, have)) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode diff = load_config(module, commands, commit=commit) if diff: if module._diff: - result['diff'] = {'prepared': diff} - result['changed'] = True + result["diff"] = {"prepared": diff} + result["changed"] = True failed_conditions = check_declarative_intent_params(module, want, result) if failed_conditions: - msg = 'One or more conditional statements have not been satisfied' + msg = "One or more conditional statements have not been satisfied" module.fail_json(msg=msg, failed_conditions=failed_conditions) module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/_vyos_l3_interface.py b/plugins/modules/_vyos_l3_interface.py index 63f0873..430217c 100644 --- a/plugins/modules/_vyos_l3_interface.py +++ b/plugins/modules/_vyos_l3_interface.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['deprecated'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -101,17 +103,19 @@ from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import is_masklen, validate_ip_address from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import load_config, run_commands - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def is_ipv4(value): if value: - address = value.split('/') + address = value.split("/") if is_masklen(address[1]) and validate_ip_address(address[0]): return True return False @@ -119,7 +123,7 @@ def is_ipv4(value): def is_ipv6(value): if value: - address = value.split('/') + address = value.split("/") if 0 <= int(address[1]) <= 128: try: socket.inet_pton(socket.AF_INET6, address[0]) @@ -131,7 +135,7 @@ def is_ipv6(value): def search_obj_in_list(name, lst): for o in lst: - if o['name'] == name: + if o["name"] == name: return o return None @@ -142,50 +146,58 @@ def map_obj_to_commands(updates, module): want, have = updates for w in want: - name = w['name'] - ipv4 = w['ipv4'] - ipv6 = w['ipv6'] - state = w['state'] + name = w["name"] + ipv4 = w["ipv4"] + ipv6 = w["ipv6"] + state = w["state"] obj_in_have = search_obj_in_list(name, have) - if state == 'absent' and obj_in_have: - if not ipv4 and not ipv6 and (obj_in_have['ipv4'] or obj_in_have['ipv6']): + if state == "absent" and obj_in_have: + if not ipv4 and not ipv6 and (obj_in_have["ipv4"] or obj_in_have["ipv6"]): if name == "lo": - commands.append('delete interfaces loopback lo address') + commands.append("delete interfaces loopback lo address") else: - commands.append('delete interfaces ethernet ' + name + ' address') + commands.append("delete interfaces ethernet " + name + " address") else: - if ipv4 and ipv4 in obj_in_have['ipv4']: + if ipv4 and ipv4 in obj_in_have["ipv4"]: if name == "lo": - commands.append('delete interfaces loopback lo address ' + ipv4) + commands.append("delete interfaces loopback lo address " + ipv4) else: - commands.append('delete interfaces ethernet ' + name + ' address ' + ipv4) - if ipv6 and ipv6 in obj_in_have['ipv6']: + commands.append( + "delete interfaces ethernet " + name + " address " + ipv4 + ) + if ipv6 and ipv6 in obj_in_have["ipv6"]: if name == "lo": - commands.append('delete interfaces loopback lo address ' + ipv6) + commands.append("delete interfaces loopback lo address " + ipv6) else: - commands.append('delete interfaces ethernet ' + name + ' address ' + ipv6) - elif (state == 'present' and obj_in_have): - if ipv4 and ipv4 not in obj_in_have['ipv4']: + commands.append( + "delete interfaces ethernet " + name + " address " + ipv6 + ) + elif state == "present" and obj_in_have: + if ipv4 and ipv4 not in obj_in_have["ipv4"]: if name == "lo": - commands.append('set interfaces loopback lo address ' + ipv4) + commands.append("set interfaces loopback lo address " + ipv4) else: - commands.append('set interfaces ethernet ' + name + ' address ' + ipv4) + commands.append( + "set interfaces ethernet " + name + " address " + ipv4 + ) - if ipv6 and ipv6 not in obj_in_have['ipv6']: + if ipv6 and ipv6 not in obj_in_have["ipv6"]: if name == "lo": - commands.append('set interfaces loopback lo address ' + ipv6) + commands.append("set interfaces loopback lo address " + ipv6) else: - commands.append('set interfaces ethernet ' + name + ' address ' + ipv6) + commands.append( + "set interfaces ethernet " + name + " address " + ipv6 + ) return commands def map_config_to_obj(module): obj = [] - output = run_commands(module, ['show interfaces']) - lines = re.split(r'\n[e|l]', output[0])[1:] + output = run_commands(module, ["show interfaces"]) + lines = re.split(r"\n[e|l]", output[0])[1:] if len(lines) > 0: for line in lines: @@ -195,22 +207,20 @@ def map_config_to_obj(module): ipv4 = [] ipv6 = [] - if splitted_line[0].lower().startswith('th'): - name = 'e' + splitted_line[0].lower() - elif splitted_line[0].lower().startswith('o'): - name = 'l' + splitted_line[0].lower() + if splitted_line[0].lower().startswith("th"): + name = "e" + splitted_line[0].lower() + elif splitted_line[0].lower().startswith("o"): + name = "l" + splitted_line[0].lower() for i in splitted_line[1:]: - if (('.' in i or ':' in i) and '/' in i): - value = i.split(r'\n')[0] + if ("." in i or ":" in i) and "/" in i: + value = i.split(r"\n")[0] if is_ipv4(value): ipv4.append(value) elif is_ipv6(value): ipv6.append(value) - obj.append({'name': name, - 'ipv4': ipv4, - 'ipv6': ipv6}) + obj.append({"name": name, "ipv4": ipv4, "ipv6": ipv6}) return obj @@ -218,7 +228,7 @@ def map_config_to_obj(module): def map_params_to_obj(module): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -227,12 +237,14 @@ def map_params_to_obj(module): obj.append(item.copy()) else: - obj.append({ - 'name': module.params['name'], - 'ipv4': module.params['ipv4'], - 'ipv6': module.params['ipv6'], - 'state': module.params['state'] - }) + obj.append( + { + "name": module.params["name"], + "ipv4": module.params["ipv4"], + "ipv6": module.params["ipv6"], + "state": module.params["state"], + } + ) return obj @@ -244,50 +256,51 @@ def main(): name=dict(), ipv4=dict(), ipv6=dict(), - state=dict(default='present', - choices=['present', 'absent']) + state=dict(default="present", choices=["present", "absent"]), ) aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) + aggregate_spec["name"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), + aggregate=dict(type="list", elements="dict", options=aggregate_spec) ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_one_of = [['name', 'aggregate']] - mutually_exclusive = [['name', 'aggregate']] - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = map_config_to_obj(module) commands = map_obj_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_banner.py b/plugins/modules/vyos_banner.py index 1f8816a..6738624 100644 --- a/plugins/modules/vyos_banner.py +++ b/plugins/modules/vyos_banner.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ --- @@ -86,28 +88,33 @@ commands: import re from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def spec_to_commands(updates, module): commands = list() want, have = updates - state = module.params['state'] - - if state == 'absent': - if have.get('state') != 'absent' or (have.get('state') != 'absent' and - 'text' in have.keys() and have['text']): - commands.append('delete system login banner %s' % module.params['banner']) - - elif state == 'present': - if want['text'] and want['text'].encode().decode('unicode_escape') != have.get('text'): - banner_cmd = 'set system login banner %s ' % module.params['banner'] - banner_cmd += want['text'].strip() + state = module.params["state"] + + if state == "absent": + if have.get("state") != "absent" or ( + have.get("state") != "absent" and "text" in have.keys() and have["text"] + ): + commands.append("delete system login banner %s" % module.params["banner"]) + + elif state == "present": + if want["text"] and want["text"].encode().decode("unicode_escape") != have.get( + "text" + ): + banner_cmd = "set system login banner %s " % module.params["banner"] + banner_cmd += want["text"].strip() commands.append(banner_cmd) return commands @@ -116,28 +123,28 @@ def spec_to_commands(updates, module): def config_to_dict(module): data = get_config(module) output = None - obj = {'banner': module.params['banner'], 'state': 'absent'} + obj = {"banner": module.params["banner"], "state": "absent"} - for line in data.split('\n'): - if line.startswith('set system login banner %s' % obj['banner']): - match = re.findall(r'%s (.*)' % obj['banner'], line, re.M) + for line in data.split("\n"): + if line.startswith("set system login banner %s" % obj["banner"]): + match = re.findall(r"%s (.*)" % obj["banner"], line, re.M) output = match if output: - obj['text'] = output[0].encode().decode('unicode_escape') - obj['state'] = 'present' + obj["text"] = output[0].encode().decode("unicode_escape") + obj["state"] = "present" return obj def map_params_to_obj(module): - text = module.params['text'] + text = module.params["text"] if text: text = "%r" % (str(text).strip()) return { - 'banner': module.params['banner'], - 'text': text, - 'state': module.params['state'] + "banner": module.params["banner"], + "text": text, + "state": module.params["state"], } @@ -145,38 +152,38 @@ def main(): """ main entry point for module execution """ argument_spec = dict( - banner=dict(required=True, choices=['pre-login', 'post-login']), + banner=dict(required=True, choices=["pre-login", "post-login"]), text=dict(), - state=dict(default='present', choices=['present', 'absent']) + state=dict(default="present", choices=["present", "absent"]), ) argument_spec.update(vyos_argument_spec) - required_if = [('state', 'present', ('text',))] + required_if = [("state", "present", ("text",))] - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True) + module = AnsibleModule( + argument_spec=argument_spec, required_if=required_if, supports_check_mode=True + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = config_to_dict(module) commands = spec_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_command.py b/plugins/modules/vyos_command.py index 3570f20..a3593ba 100644 --- a/plugins/modules/vyos_command.py +++ b/plugins/modules/vyos_command.py @@ -16,9 +16,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -142,12 +144,13 @@ from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.parsing import Conditional from ansible.module_utils.network.common.utils import transform_commands, to_lines -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import run_commands - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def parse_commands(module, warnings): @@ -155,10 +158,10 @@ def parse_commands(module, warnings): if module.check_mode: for item in list(commands): - if not item['command'].startswith('show'): + if not item["command"].startswith("show"): warnings.append( - 'Only show commands are supported when using check mode, not ' - 'executing %s' % item['command'] + "Only show commands are supported when using check mode, not " + "executing %s" % item["command"] ) commands.remove(item) @@ -167,13 +170,11 @@ def parse_commands(module, warnings): def main(): spec = dict( - commands=dict(type='list', required=True), - - wait_for=dict(type='list', aliases=['waitfor']), - match=dict(default='all', choices=['all', 'any']), - - retries=dict(default=10, type='int'), - interval=dict(default=1, type='int') + commands=dict(type="list", required=True), + wait_for=dict(type="list", aliases=["waitfor"]), + match=dict(default="all", choices=["all", "any"]), + retries=dict(default=10, type="int"), + interval=dict(default=1, type="int"), ) spec.update(vyos_argument_spec) @@ -181,25 +182,25 @@ def main(): module = AnsibleModule(argument_spec=spec, supports_check_mode=True) warnings = list() - result = {'changed': False, 'warnings': warnings} + result = {"changed": False, "warnings": warnings} commands = parse_commands(module, warnings) - wait_for = module.params['wait_for'] or list() + wait_for = module.params["wait_for"] or list() try: conditionals = [Conditional(c) for c in wait_for] except AttributeError as exc: module.fail_json(msg=to_text(exc)) - retries = module.params['retries'] - interval = module.params['interval'] - match = module.params['match'] + retries = module.params["retries"] + interval = module.params["interval"] + match = module.params["match"] for _ in range(retries): responses = run_commands(module, commands) for item in list(conditionals): if item(responses): - if match == 'any': + if match == "any": conditionals = list() break conditionals.remove(item) @@ -211,16 +212,13 @@ def main(): if conditionals: failed_conditions = [item.raw for item in conditionals] - msg = 'One or more conditional statements have not been satisfied' + msg = "One or more conditional statements have not been satisfied" module.fail_json(msg=msg, failed_conditions=failed_conditions) - result.update({ - 'stdout': responses, - 'stdout_lines': list(to_lines(responses)), - }) + result.update({"stdout": responses, "stdout_lines": list(to_lines(responses))}) module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_config.py b/plugins/modules/vyos_config.py index 7987e14..530fdc3 100644 --- a/plugins/modules/vyos_config.py +++ b/plugins/modules/vyos_config.py @@ -16,9 +16,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -187,28 +189,32 @@ import re from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.connection import ConnectionError -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import load_config, get_config, run_commands +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + get_config, + run_commands, +) -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec, get_connection +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, + get_connection, +) - -DEFAULT_COMMENT = 'configured by vyos_config' +DEFAULT_COMMENT = "configured by vyos_config" CONFIG_FILTERS = [ - re.compile(r'set system login user \S+ authentication encrypted-password') + re.compile(r"set system login user \S+ authentication encrypted-password") ] def get_candidate(module): - contents = module.params['src'] or module.params['lines'] + contents = module.params["src"] or module.params["lines"] - if module.params['src']: + if module.params["src"]: contents = format_commands(contents.splitlines()) - contents = '\n'.join(contents) + contents = "\n".join(contents) return contents @@ -217,25 +223,25 @@ def format_commands(commands): def diff_config(commands, config): - config = [str(c).replace("'", '') for c in config.splitlines()] + config = [str(c).replace("'", "") for c in config.splitlines()] updates = list() visited = set() for line in commands: - item = str(line).replace("'", '') + item = str(line).replace("'", "") - if not item.startswith('set') and not item.startswith('delete'): - raise ValueError('line must start with either `set` or `delete`') + 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 not in config: + elif item.startswith("set") and item not in config: updates.append(line) - elif item.startswith('delete'): + elif item.startswith("delete"): if not config: updates.append(line) else: - item = re.sub(r'delete', 'set', item) + item = re.sub(r"delete", "set", item) for entry in config: if entry.startswith(item) and line not in visited: updates.append(line) @@ -245,12 +251,12 @@ def diff_config(commands, config): def sanitize_config(config, result): - result['filtered'] = list() + result["filtered"] = list() index_to_filter = list() for regex in CONFIG_FILTERS: for index, line in enumerate(list(config)): if regex.search(line): - result['filtered'].append(line) + result["filtered"].append(line) index_to_filter.append(index) # Delete all filtered configs for filter_index in sorted(index_to_filter, reverse=True): @@ -260,7 +266,7 @@ def sanitize_config(config, result): def run(module, result): # get the current active config from the node or passed in via # the config param - config = module.params['config'] or get_config(module) + config = module.params["config"] or get_config(module) # create the candidate config object from the arguments candidate = get_candidate(module) @@ -268,81 +274,78 @@ def run(module, result): # create loadable config that includes only the configuration updates connection = get_connection(module) try: - response = connection.get_diff(candidate=candidate, running=config, diff_match=module.params['match']) + response = connection.get_diff( + candidate=candidate, running=config, diff_match=module.params["match"] + ) except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) + module.fail_json(msg=to_text(exc, errors="surrogate_then_replace")) - commands = response.get('config_diff') + commands = response.get("config_diff") sanitize_config(commands, result) - result['commands'] = commands + result["commands"] = commands commit = not module.check_mode - comment = module.params['comment'] + comment = module.params["comment"] diff = None if commands: diff = load_config(module, commands, commit=commit, comment=comment) - if result.get('filtered'): - result['warnings'].append('Some configuration commands were ' - 'removed, please see the filtered key') + if result.get("filtered"): + result["warnings"].append( + "Some configuration commands were " + "removed, please see the filtered key" + ) - result['changed'] = True + result["changed"] = True if module._diff: - result['diff'] = {'prepared': diff} + result["diff"] = {"prepared": diff} def main(): - backup_spec = dict( - filename=dict(), - dir_path=dict(type='path') - ) + backup_spec = dict(filename=dict(), dir_path=dict(type="path")) argument_spec = dict( - src=dict(type='path'), - lines=dict(type='list'), - - match=dict(default='line', choices=['line', 'none']), - + src=dict(type="path"), + lines=dict(type="list"), + match=dict(default="line", choices=["line", "none"]), comment=dict(default=DEFAULT_COMMENT), - config=dict(), - - backup=dict(type='bool', default=False), - backup_options=dict(type='dict', options=backup_spec), - save=dict(type='bool', default=False), + backup=dict(type="bool", default=False), + backup_options=dict(type="dict", options=backup_spec), + save=dict(type="bool", default=False), ) argument_spec.update(vyos_argument_spec) - mutually_exclusive = [('lines', 'src')] + mutually_exclusive = [("lines", "src")] module = AnsibleModule( argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, - supports_check_mode=True + supports_check_mode=True, ) warnings = list() result = dict(changed=False, warnings=warnings) - if module.params['backup']: - result['__backup__'] = get_config(module=module) + if module.params["backup"]: + result["__backup__"] = get_config(module=module) - if any((module.params['src'], module.params['lines'])): + if any((module.params["src"], module.params["lines"])): run(module, result) - if module.params['save']: - diff = run_commands(module, commands=['configure', 'compare saved'])[1] - if diff != '[edit]': - run_commands(module, commands=['save']) - result['changed'] = True - run_commands(module, commands=['exit']) + if module.params["save"]: + diff = run_commands(module, commands=["configure", "compare saved"])[1] + if diff != "[edit]": + run_commands(module, commands=["save"]) + result["changed"] = True + run_commands(module, commands=["exit"]) module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index 5c8ac51..1e63c5d 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -8,9 +8,11 @@ The module file for vyos_facts """ -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': [u'preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": [u"preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -135,15 +137,17 @@ ansible_net_gather_network_resources: """ from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.argspec.facts.facts import FactsArgs +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.facts.facts import ( + FactsArgs, +) -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.facts.facts import Facts - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( + Facts, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def main(): @@ -156,11 +160,12 @@ def main(): argument_spec.update(vyos_argument_spec) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - warnings = ['default value for `gather_subset` ' - 'will be changed to `min` from `!config` v2.11 onwards'] + warnings = [ + "default value for `gather_subset` " + "will be changed to `min` from `!config` v2.11 onwards" + ] result = Facts(module).get_facts() @@ -170,5 +175,5 @@ def main(): module.exit_json(ansible_facts=ansible_facts, warnings=warnings) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_interfaces.py b/plugins/modules/vyos_interfaces.py index a78a983..ca61f4d 100644 --- a/plugins/modules/vyos_interfaces.py +++ b/plugins/modules/vyos_interfaces.py @@ -27,12 +27,13 @@ The module file for vyos_interfaces """ from __future__ import absolute_import, division, print_function + __metaclass__ = type ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", } DOCUMENTATION = """ @@ -855,12 +856,13 @@ commands: from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.argspec.interfaces.interfaces import InterfacesArgs - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.config.interfaces.interfaces import Interfaces +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.interfaces.interfaces import ( + InterfacesArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.interfaces.interfaces import ( + Interfaces, +) def main(): @@ -869,12 +871,13 @@ def main(): :returns: the result form module invocation """ - module = AnsibleModule(argument_spec=InterfacesArgs.argument_spec, - supports_check_mode=True) + module = AnsibleModule( + argument_spec=InterfacesArgs.argument_spec, supports_check_mode=True + ) result = Interfaces(module).execute_module() module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_l3_interfaces.py b/plugins/modules/vyos_l3_interfaces.py index c2dd461..1a2e453 100644 --- a/plugins/modules/vyos_l3_interfaces.py +++ b/plugins/modules/vyos_l3_interfaces.py @@ -26,13 +26,14 @@ The module file for vyos_l3_interfaces """ -from __future__ import (absolute_import, division, print_function) +from __future__ import absolute_import, division, print_function + __metaclass__ = type ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", } DOCUMENTATION = """ @@ -351,12 +352,13 @@ commands: from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.argspec.l3_interfaces.l3_interfaces import L3_interfacesArgs - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.config.l3_interfaces.l3_interfaces import L3_interfaces +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.l3_interfaces.l3_interfaces import ( + L3_interfacesArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.l3_interfaces.l3_interfaces import ( + L3_interfaces, +) def main(): @@ -365,12 +367,13 @@ def main(): :returns: the result form module invocation """ - module = AnsibleModule(argument_spec=L3_interfacesArgs.argument_spec, - supports_check_mode=True) + module = AnsibleModule( + argument_spec=L3_interfacesArgs.argument_spec, supports_check_mode=True + ) result = L3_interfaces(module).execute_module() module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_linkagg.py b/plugins/modules/vyos_linkagg.py index 71f46ba..7793b6d 100644 --- a/plugins/modules/vyos_linkagg.py +++ b/plugins/modules/vyos_linkagg.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -100,17 +102,19 @@ from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import load_config, run_commands - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def search_obj_in_list(name, lst): for o in lst: - if o['name'] == name: + if o["name"] == name: return o return None @@ -121,51 +125,55 @@ def map_obj_to_commands(updates, module): want, have = updates for w in want: - name = w['name'] - members = w.get('members') or [] - mode = w['mode'] + name = w["name"] + members = w.get("members") or [] + mode = w["mode"] - if mode == 'on': - mode = '802.3ad' + if mode == "on": + mode = "802.3ad" - state = w['state'] + state = w["state"] obj_in_have = search_obj_in_list(name, have) - if state == 'absent': + if state == "absent": if obj_in_have: - for m in obj_in_have['members']: - commands.append('delete interfaces ethernet ' + m + ' bond-group') + for m in obj_in_have["members"]: + commands.append("delete interfaces ethernet " + m + " bond-group") - commands.append('delete interfaces bonding ' + name) + commands.append("delete interfaces bonding " + name) else: if not obj_in_have: - commands.append('set interfaces bonding ' + name + ' mode ' + mode) + commands.append("set interfaces bonding " + name + " mode " + mode) for m in members: - commands.append('set interfaces ethernet ' + m + ' bond-group ' + name) + commands.append( + "set interfaces ethernet " + m + " bond-group " + name + ) - if state == 'down': - commands.append('set interfaces bonding ' + name + ' disable') + if state == "down": + commands.append("set interfaces bonding " + name + " disable") else: - if mode != obj_in_have['mode']: - commands.append('set interfaces bonding ' + name + ' mode ' + mode) + if mode != obj_in_have["mode"]: + commands.append("set interfaces bonding " + name + " mode " + mode) - missing_members = list(set(members) - set(obj_in_have['members'])) + missing_members = list(set(members) - set(obj_in_have["members"])) for m in missing_members: - commands.append('set interfaces ethernet ' + m + ' bond-group ' + name) + commands.append( + "set interfaces ethernet " + m + " bond-group " + name + ) - if state == 'down' and obj_in_have['state'] == 'up': - commands.append('set interfaces bonding ' + name + ' disable') - elif state == 'up' and obj_in_have['state'] == 'down': - commands.append('delete interfaces bonding ' + name + ' disable') + if state == "down" and obj_in_have["state"] == "up": + commands.append("set interfaces bonding " + name + " disable") + elif state == "up" and obj_in_have["state"] == "down": + commands.append("delete interfaces bonding " + name + " disable") return commands def map_config_to_obj(module): obj = [] - output = run_commands(module, ['show interfaces bonding slaves']) + output = run_commands(module, ["show interfaces bonding slaves"]) lines = output[0].splitlines() if len(lines) > 1: @@ -181,17 +189,14 @@ def map_config_to_obj(module): else: members = [] - obj.append({'name': name, - 'mode': mode, - 'members': members, - 'state': state}) + obj.append({"name": name, "mode": mode, "members": members, "state": state}) return obj def map_params_to_obj(module): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -200,12 +205,14 @@ def map_params_to_obj(module): obj.append(item.copy()) else: - obj.append({ - 'name': module.params['name'], - 'mode': module.params['mode'], - 'members': module.params['members'], - 'state': module.params['state'] - }) + obj.append( + { + "name": module.params["name"], + "mode": module.params["mode"], + "members": module.params["members"], + "state": module.params["state"], + } + ) return obj @@ -215,55 +222,65 @@ def main(): """ element_spec = dict( name=dict(), - mode=dict(choices=['802.3ad', 'active-backup', 'broadcast', - 'round-robin', 'transmit-load-balance', - 'adaptive-load-balance', 'xor-hash', 'on'], - default='802.3ad'), - members=dict(type='list'), - state=dict(default='present', - choices=['present', 'absent', 'up', 'down']) + mode=dict( + choices=[ + "802.3ad", + "active-backup", + "broadcast", + "round-robin", + "transmit-load-balance", + "adaptive-load-balance", + "xor-hash", + "on", + ], + default="802.3ad", + ), + members=dict(type="list"), + state=dict(default="present", choices=["present", "absent", "up", "down"]), ) aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) + aggregate_spec["name"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), + aggregate=dict(type="list", elements="dict", options=aggregate_spec) ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_one_of = [['name', 'aggregate']] - mutually_exclusive = [['name', 'aggregate']] - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = map_config_to_obj(module) commands = map_obj_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_lldp.py b/plugins/modules/vyos_lldp.py index fa1ac03..69a62a3 100644 --- a/plugins/modules/vyos_lldp.py +++ b/plugins/modules/vyos_lldp.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -63,18 +65,20 @@ commands: - set service lldp """ from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def has_lldp(module): config = get_config(module).splitlines() - if "set service 'lldp'" in config or 'set service lldp' in config: + if "set service 'lldp'" in config or "set service lldp" in config: return True else: return False @@ -84,42 +88,41 @@ def main(): """ main entry point for module execution """ argument_spec = dict( - interfaces=dict(type='list'), - state=dict(default='present', - choices=['present', 'absent', - 'enabled', 'disabled']) + interfaces=dict(type="list"), + state=dict( + default="present", choices=["present", "absent", "enabled", "disabled"] + ), ) argument_spec.update(vyos_argument_spec) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings HAS_LLDP = has_lldp(module) commands = [] - if module.params['state'] == 'absent' and HAS_LLDP: - commands.append('delete service lldp') - elif module.params['state'] == 'present' and not HAS_LLDP: - commands.append('set service lldp') + if module.params["state"] == "absent" and HAS_LLDP: + commands.append("delete service lldp") + elif module.params["state"] == "present" and not HAS_LLDP: + commands.append("set service lldp") - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_lldp_interface.py b/plugins/modules/vyos_lldp_interface.py index 86a64e3..23d1eab 100644 --- a/plugins/modules/vyos_lldp_interface.py +++ b/plugins/modules/vyos_lldp_interface.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -93,17 +95,19 @@ from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def search_obj_in_list(name, lst): for o in lst: - if o['name'] == name: + if o["name"] == name: return o return None @@ -114,24 +118,28 @@ def map_obj_to_commands(updates, module): want, have = updates for w in want: - name = w['name'] - state = w['state'] + name = w["name"] + state = w["state"] obj_in_have = search_obj_in_list(name, have) - if state == 'absent' and obj_in_have: - commands.append('delete service lldp interface ' + name) - elif state in ('present', 'enabled'): + if state == "absent" and obj_in_have: + commands.append("delete service lldp interface " + name) + elif state in ("present", "enabled"): if not obj_in_have: - commands.append('set service lldp interface ' + name) - elif obj_in_have and obj_in_have['state'] == 'disabled' and state == 'enabled': - commands.append('delete service lldp interface ' + name + ' disable') - elif state == 'disabled': + commands.append("set service lldp interface " + name) + elif ( + obj_in_have + and obj_in_have["state"] == "disabled" + and state == "enabled" + ): + commands.append("delete service lldp interface " + name + " disable") + elif state == "disabled": if not obj_in_have: - commands.append('set service lldp interface ' + name) - commands.append('set service lldp interface ' + name + ' disable') - elif obj_in_have and obj_in_have['state'] != 'disabled': - commands.append('set service lldp interface ' + name + ' disable') + commands.append("set service lldp interface " + name) + commands.append("set service lldp interface " + name + " disable") + elif obj_in_have and obj_in_have["state"] != "disabled": + commands.append("set service lldp interface " + name + " disable") return commands @@ -146,13 +154,13 @@ def map_config_to_obj(module): splitted_line = i.split() if len(splitted_line) > 5: - new_obj = {'name': splitted_line[4]} + new_obj = {"name": splitted_line[4]} if splitted_line[5] == "'disable'": - new_obj['state'] = 'disabled' + new_obj["state"] = "disabled" else: - new_obj = {'name': splitted_line[4][1:-1]} - new_obj['state'] = 'present' + new_obj = {"name": splitted_line[4][1:-1]} + new_obj["state"] = "present" obj.append(new_obj) @@ -162,7 +170,7 @@ def map_config_to_obj(module): def map_params_to_obj(module): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -171,7 +179,7 @@ def map_params_to_obj(module): obj.append(item.copy()) else: - obj.append({'name': module.params['name'], 'state': module.params['state']}) + obj.append({"name": module.params["name"], "state": module.params["state"]}) return obj @@ -181,52 +189,54 @@ def main(): """ element_spec = dict( name=dict(), - state=dict(default='present', - choices=['present', 'absent', - 'enabled', 'disabled']) + state=dict( + default="present", choices=["present", "absent", "enabled", "disabled"] + ), ) aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) + aggregate_spec["name"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), + aggregate=dict(type="list", elements="dict", options=aggregate_spec) ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_one_of = [['name', 'aggregate']] - mutually_exclusive = [['name', 'aggregate']] + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = map_config_to_obj(module) commands = map_obj_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_logging.py b/plugins/modules/vyos_logging.py index a94a8bd..1fd0ca2 100644 --- a/plugins/modules/vyos_logging.py +++ b/plugins/modules/vyos_logging.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ --- @@ -110,12 +112,14 @@ from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def spec_to_commands(updates, module): @@ -123,27 +127,39 @@ def spec_to_commands(updates, module): want, have = updates for w in want: - dest = w['dest'] - name = w['name'] - facility = w['facility'] - level = w['level'] - state = w['state'] - del w['state'] - - if state == 'absent' and w in have: - if w['name']: - commands.append('delete system syslog {0} {1} facility {2} level {3}'.format( - dest, name, facility, level)) + dest = w["dest"] + name = w["name"] + facility = w["facility"] + level = w["level"] + state = w["state"] + del w["state"] + + if state == "absent" and w in have: + if w["name"]: + commands.append( + "delete system syslog {0} {1} facility {2} level {3}".format( + dest, name, facility, level + ) + ) else: - commands.append('delete system syslog {0} facility {1} level {2}'.format( - dest, facility, level)) - elif state == 'present' and w not in have: - if w['name']: - commands.append('set system syslog {0} {1} facility {2} level {3}'.format( - dest, name, facility, level)) + commands.append( + "delete system syslog {0} facility {1} level {2}".format( + dest, facility, level + ) + ) + elif state == "present" and w not in have: + if w["name"]: + commands.append( + "set system syslog {0} {1} facility {2} level {3}".format( + dest, name, facility, level + ) + ) else: - commands.append('set system syslog {0} facility {1} level {2}'.format( - dest, facility, level)) + commands.append( + "set system syslog {0} facility {1} level {2}".format( + dest, facility, level + ) + ) return commands @@ -152,33 +168,32 @@ def config_to_dict(module): data = get_config(module) obj = [] - for line in data.split('\n'): - if line.startswith('set system syslog'): - match = re.search(r'set system syslog (\S+)', line, re.M) + for line in data.split("\n"): + if line.startswith("set system syslog"): + match = re.search(r"set system syslog (\S+)", line, re.M) dest = match.group(1) - if dest == 'host': - match = re.search(r'host (\S+)', line, re.M) + if dest == "host": + match = re.search(r"host (\S+)", line, re.M) name = match.group(1) - elif dest == 'file': - match = re.search(r'file (\S+)', line, re.M) + elif dest == "file": + match = re.search(r"file (\S+)", line, re.M) name = match.group(1) - elif dest == 'user': - match = re.search(r'user (\S+)', line, re.M) + elif dest == "user": + match = re.search(r"user (\S+)", line, re.M) name = match.group(1) else: name = None - if 'facility' in line: - match = re.search(r'facility (\S+)', line, re.M) + if "facility" in line: + match = re.search(r"facility (\S+)", line, re.M) facility = match.group(1) - if 'level' in line: - match = re.search(r'level (\S+)', line, re.M) + if "level" in line: + match = re.search(r"level (\S+)", line, re.M) level = match.group(1).strip("'") - obj.append({'dest': dest, - 'name': name, - 'facility': facility, - 'level': level}) + obj.append( + {"dest": dest, "name": name, "facility": facility, "level": level} + ) return obj @@ -186,7 +201,7 @@ def config_to_dict(module): def map_params_to_obj(module, required_if=None): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -197,16 +212,18 @@ def map_params_to_obj(module, required_if=None): obj.append(item.copy()) else: - if module.params['dest'] not in ('host', 'file', 'user'): - module.params['name'] = None - - obj.append({ - 'dest': module.params['dest'], - 'name': module.params['name'], - 'facility': module.params['facility'], - 'level': module.params['level'], - 'state': module.params['state'] - }) + if module.params["dest"] not in ("host", "file", "user"): + module.params["name"] = None + + obj.append( + { + "dest": module.params["dest"], + "name": module.params["name"], + "facility": module.params["facility"], + "level": module.params["level"], + "state": module.params["state"], + } + ) return obj @@ -215,11 +232,11 @@ def main(): """ main entry point for module execution """ element_spec = dict( - dest=dict(type='str', choices=['console', 'file', 'global', 'host', 'user']), - name=dict(type='str'), - facility=dict(type='str'), - level=dict(type='str'), - state=dict(default='present', choices=['present', 'absent']), + dest=dict(type="str", choices=["console", "file", "global", "host", "user"]), + name=dict(type="str"), + facility=dict(type="str"), + level=dict(type="str"), + state=dict(default="present", choices=["present", "absent"]), ) aggregate_spec = deepcopy(element_spec) @@ -228,40 +245,42 @@ def main(): remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), + aggregate=dict(type="list", elements="dict", options=aggregate_spec) ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_if = [('dest', 'host', ['name', 'facility', 'level']), - ('dest', 'file', ['name', 'facility', 'level']), - ('dest', 'user', ['name', 'facility', 'level']), - ('dest', 'console', ['facility', 'level']), - ('dest', 'global', ['facility', 'level'])] - - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True) + required_if = [ + ("dest", "host", ["name", "facility", "level"]), + ("dest", "file", ["name", "facility", "level"]), + ("dest", "user", ["name", "facility", "level"]), + ("dest", "console", ["facility", "level"]), + ("dest", "global", ["facility", "level"]), + ] + + module = AnsibleModule( + argument_spec=argument_spec, required_if=required_if, supports_check_mode=True + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module, required_if=required_if) have = config_to_dict(module) commands = spec_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_ping.py b/plugins/modules/vyos_ping.py index 762bc80..9e99d48 100644 --- a/plugins/modules/vyos_ping.py +++ b/plugins/modules/vyos_ping.py @@ -20,11 +20,14 @@ # from __future__ import absolute_import, division, print_function + __metaclass__ = type -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} DOCUMENTATION = """ --- @@ -130,11 +133,13 @@ rtt: """ from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import run_commands +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + run_commands, +) -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) import re @@ -146,9 +151,9 @@ def main(): count=dict(type="int", default=5), dest=dict(type="str", required=True), source=dict(type="str"), - ttl=dict(type='int'), - size=dict(type='int'), - interval=dict(type='int'), + ttl=dict(type="int"), + size=dict(type="int"), + interval=dict(type="int"), state=dict(type="str", choices=["absent", "present"], default="present"), ) @@ -176,9 +181,9 @@ def main(): rtt_info, rate_info = None, None for line in ping_results_list: - if line.startswith('rtt'): + if line.startswith("rtt"): rtt_info = line - if line.startswith('%s packets transmitted' % count): + if line.startswith("%s packets transmitted" % count): rate_info = line if rtt_info: @@ -218,9 +223,11 @@ def build_ping(dest, count, size=None, interval=None, source=None, ttl=None): def parse_rate(rate_info): rate_re = re.compile( - r"(?P<tx>\d+) (?:\w+) (?:\w+), (?P<rx>\d+) (?:\w+), (?P<pkt_loss>\d+)% (?:\w+) (?:\w+), (?:\w+) (?P<time>\d+)") + r"(?P<tx>\d+) (?:\w+) (?:\w+), (?P<rx>\d+) (?:\w+), (?P<pkt_loss>\d+)% (?:\w+) (?:\w+), (?:\w+) (?P<time>\d+)" + ) rate_err_re = re.compile( - r"(?P<tx>\d+) (?:\w+) (?:\w+), (?P<rx>\d+) (?:\w+), (?:[+-])(?P<err>\d+) (?:\w+), (?P<pkt_loss>\d+)% (?:\w+) (?:\w+), (?:\w+) (?P<time>\d+)") + r"(?P<tx>\d+) (?:\w+) (?:\w+), (?P<rx>\d+) (?:\w+), (?:[+-])(?P<err>\d+) (?:\w+), (?P<pkt_loss>\d+)% (?:\w+) (?:\w+), (?:\w+) (?P<time>\d+)" + ) if rate_re.match(rate_info): rate = rate_re.match(rate_info) @@ -232,7 +239,8 @@ def parse_rate(rate_info): def parse_rtt(rtt_info): rtt_re = re.compile( - r"rtt (?:.*)=(?:\s*)(?P<min>\d*).(?:\d*)/(?P<avg>\d*).(?:\d*)/(?P<max>\d+).(?:\d*)/(?P<mdev>\d*)") + r"rtt (?:.*)=(?:\s*)(?P<min>\d*).(?:\d*)/(?P<avg>\d*).(?:\d*)/(?P<max>\d+).(?:\d*)/(?P<mdev>\d*)" + ) rtt = rtt_re.match(rtt_info) return rtt.groupdict() diff --git a/plugins/modules/vyos_static_route.py b/plugins/modules/vyos_static_route.py index 3c00bca..dfb1d21 100644 --- a/plugins/modules/vyos_static_route.py +++ b/plugins/modules/vyos_static_route.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -108,31 +110,37 @@ from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def spec_to_commands(updates, module): commands = list() want, have = updates for w in want: - prefix = w['prefix'] - mask = w['mask'] - next_hop = w['next_hop'] - admin_distance = w['admin_distance'] - state = w['state'] - del w['state'] - - if state == 'absent' and w in have: - commands.append('delete protocols static route %s/%s' % (prefix, mask)) - elif state == 'present' and w not in have: - cmd = 'set protocols static route %s/%s next-hop %s' % (prefix, mask, next_hop) - if admin_distance != 'None': - cmd += ' distance %s' % (admin_distance) + prefix = w["prefix"] + mask = w["mask"] + next_hop = w["next_hop"] + admin_distance = w["admin_distance"] + state = w["state"] + del w["state"] + + if state == "absent" and w in have: + commands.append("delete protocols static route %s/%s" % (prefix, mask)) + elif state == "present" and w not in have: + cmd = "set protocols static route %s/%s next-hop %s" % ( + prefix, + mask, + next_hop, + ) + if admin_distance != "None": + cmd += " distance %s" % (admin_distance) commands.append(cmd) return commands @@ -142,38 +150,46 @@ def config_to_dict(module): data = get_config(module) obj = [] - for line in data.split('\n'): - if line.startswith('set protocols static route'): - match = re.search(r'static route (\S+)', line, re.M) - prefix = match.group(1).split('/')[0] - mask = match.group(1).split('/')[1] - if 'next-hop' in line: - match_hop = re.search(r'next-hop (\S+)', line, re.M) + for line in data.split("\n"): + if line.startswith("set protocols static route"): + match = re.search(r"static route (\S+)", line, re.M) + prefix = match.group(1).split("/")[0] + mask = match.group(1).split("/")[1] + if "next-hop" in line: + match_hop = re.search(r"next-hop (\S+)", line, re.M) next_hop = match_hop.group(1).strip("'") - match_distance = re.search(r'distance (\S+)', line, re.M) + match_distance = re.search(r"distance (\S+)", line, re.M) if match_distance is not None: admin_distance = match_distance.group(1)[1:-1] else: admin_distance = None if admin_distance is not None: - obj.append({'prefix': prefix, - 'mask': mask, - 'next_hop': next_hop, - 'admin_distance': admin_distance}) + obj.append( + { + "prefix": prefix, + "mask": mask, + "next_hop": next_hop, + "admin_distance": admin_distance, + } + ) else: - obj.append({'prefix': prefix, - 'mask': mask, - 'next_hop': next_hop, - 'admin_distance': 'None'}) + obj.append( + { + "prefix": prefix, + "mask": mask, + "next_hop": next_hop, + "admin_distance": "None", + } + ) return obj def map_params_to_obj(module, required_together=None): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -182,32 +198,34 @@ def map_params_to_obj(module, required_together=None): module._check_required_together(required_together, item) d = item.copy() - if '/' in d['prefix']: - d['mask'] = d['prefix'].split('/')[1] - d['prefix'] = d['prefix'].split('/')[0] + if "/" in d["prefix"]: + d["mask"] = d["prefix"].split("/")[1] + d["prefix"] = d["prefix"].split("/")[0] - if 'admin_distance' in d: - d['admin_distance'] = str(d['admin_distance']) + if "admin_distance" in d: + d["admin_distance"] = str(d["admin_distance"]) obj.append(d) else: - prefix = module.params['prefix'].strip() - if '/' in prefix: - mask = prefix.split('/')[1] - prefix = prefix.split('/')[0] + prefix = module.params["prefix"].strip() + if "/" in prefix: + mask = prefix.split("/")[1] + prefix = prefix.split("/")[0] else: - mask = module.params['mask'].strip() - next_hop = module.params['next_hop'].strip() - admin_distance = str(module.params['admin_distance']) - state = module.params['state'] - - obj.append({ - 'prefix': prefix, - 'mask': mask, - 'next_hop': next_hop, - 'admin_distance': admin_distance, - 'state': state - }) + mask = module.params["mask"].strip() + next_hop = module.params["next_hop"].strip() + admin_distance = str(module.params["admin_distance"]) + state = module.params["state"] + + obj.append( + { + "prefix": prefix, + "mask": mask, + "next_hop": next_hop, + "admin_distance": admin_distance, + "state": state, + } + ) return obj @@ -216,54 +234,56 @@ def main(): """ main entry point for module execution """ element_spec = dict( - prefix=dict(type='str'), - mask=dict(type='str'), - next_hop=dict(type='str'), - admin_distance=dict(type='int'), - state=dict(default='present', choices=['present', 'absent']) + prefix=dict(type="str"), + mask=dict(type="str"), + next_hop=dict(type="str"), + admin_distance=dict(type="int"), + state=dict(default="present", choices=["present", "absent"]), ) aggregate_spec = deepcopy(element_spec) - aggregate_spec['prefix'] = dict(required=True) + aggregate_spec["prefix"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), + aggregate=dict(type="list", elements="dict", options=aggregate_spec) ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_one_of = [['aggregate', 'prefix']] - required_together = [['prefix', 'next_hop']] - mutually_exclusive = [['aggregate', 'prefix']] + required_one_of = [["aggregate", "prefix"]] + required_together = [["prefix", "next_hop"]] + mutually_exclusive = [["aggregate", "prefix"]] - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - required_together=required_together, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + required_together=required_together, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module, required_together=required_together) have = config_to_dict(module) commands = spec_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_system.py b/plugins/modules/vyos_system.py index 20cf907..9984154 100644 --- a/plugins/modules/vyos_system.py +++ b/plugins/modules/vyos_system.py @@ -17,9 +17,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ @@ -92,20 +94,22 @@ EXAMPLES = """ """ from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def spec_key_to_device_key(key): - device_key = key.replace('_', '-') + device_key = key.replace("_", "-") # domain-search is longer than just it's key - if device_key == 'domain-search': - device_key += ' domain' + if device_key == "domain-search": + device_key += " domain" return device_key @@ -113,17 +117,17 @@ def spec_key_to_device_key(key): def config_to_dict(module): data = get_config(module) - config = {'domain_search': [], 'name_server': []} + config = {"domain_search": [], "name_server": []} - for line in data.split('\n'): - if line.startswith('set system host-name'): - config['host_name'] = line[22:-1] - elif line.startswith('set system domain-name'): - config['domain_name'] = line[24:-1] - elif line.startswith('set system domain-search domain'): - config['domain_search'].append(line[33:-1]) - elif line.startswith('set system name-server'): - config['name_server'].append(line[24:-1]) + for line in data.split("\n"): + if line.startswith("set system host-name"): + config["host_name"] = line[22:-1] + elif line.startswith("set system domain-name"): + config["domain_name"] = line[24:-1] + elif line.startswith("set system domain-search domain"): + config["domain_search"].append(line[33:-1]) + elif line.startswith("set system name-server"): + config["name_server"].append(line[24:-1]) return config @@ -131,13 +135,13 @@ def config_to_dict(module): def spec_to_commands(want, have): commands = [] - state = want.pop('state') + state = want.pop("state") # state='absent' by itself has special meaning - if state == 'absent' and all(v is None for v in want.values()): + if state == "absent" and all(v is None for v in want.values()): # Clear everything for key in have: - commands.append('delete system %s' % spec_key_to_device_key(key)) + commands.append("delete system %s" % spec_key_to_device_key(key)) for key in want: if want[key] is None: @@ -148,19 +152,19 @@ def spec_to_commands(want, have): device_key = spec_key_to_device_key(key) # These keys are lists which may need to be reconciled with the device - if key in ['domain_search', 'name_server']: + if key in ["domain_search", "name_server"]: if not proposed: # Empty list was passed, delete all values commands.append("delete system %s" % device_key) for config in proposed: - if state == 'absent' and config in current: + if state == "absent" and config in current: commands.append("delete system %s '%s'" % (device_key, config)) - elif state == 'present' and config not in current: + elif state == "present" and config not in current: commands.append("set system %s '%s'" % (device_key, config)) else: - if state == 'absent' and current and proposed: - commands.append('delete system %s' % device_key) - elif state == 'present' and proposed and proposed != current: + if state == "absent" and current and proposed: + commands.append("delete system %s" % device_key) + elif state == "present" and proposed and proposed != current: commands.append("set system %s '%s'" % (device_key, proposed)) return commands @@ -168,21 +172,21 @@ def spec_to_commands(want, have): def map_param_to_obj(module): return { - 'host_name': module.params['host_name'], - 'domain_name': module.params['domain_name'], - 'domain_search': module.params['domain_search'], - 'name_server': module.params['name_server'], - 'state': module.params['state'] + "host_name": module.params["host_name"], + "domain_name": module.params["domain_name"], + "domain_search": module.params["domain_search"], + "name_server": module.params["name_server"], + "state": module.params["state"], } def main(): argument_spec = dict( - host_name=dict(type='str'), - domain_name=dict(type='str'), - domain_search=dict(type='list'), - name_server=dict(type='list', aliases=['name_servers']), - state=dict(type='str', default='present', choices=['present', 'absent']), + host_name=dict(type="str"), + domain_name=dict(type="str"), + domain_search=dict(type="list"), + name_server=dict(type="list", aliases=["name_servers"]), + state=dict(type="str", default="present", choices=["present", "absent"]), ) argument_spec.update(vyos_argument_spec) @@ -190,26 +194,26 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, - mutually_exclusive=[('domain_name', 'domain_search')], + mutually_exclusive=[("domain_name", "domain_search")], ) warnings = list() - result = {'changed': False, 'warnings': warnings} + result = {"changed": False, "warnings": warnings} want = map_param_to_obj(module) have = config_to_dict(module) commands = spec_to_commands(want, have) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode response = load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_user.py b/plugins/modules/vyos_user.py index e670d55..74ec720 100644 --- a/plugins/modules/vyos_user.py +++ b/plugins/modules/vyos_user.py @@ -19,9 +19,11 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ --- @@ -137,60 +139,67 @@ from functools import partial from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import get_config, load_config +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) from ansible.module_utils.six import iteritems -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec - +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def validate_level(value, module): - if value not in ('admin', 'operator'): - module.fail_json(msg='level must be either admin or operator, got %s' % value) + if value not in ("admin", "operator"): + module.fail_json(msg="level must be either admin or operator, got %s" % value) def spec_to_commands(updates, module): commands = list() - state = module.params['state'] - update_password = module.params['update_password'] + state = module.params["state"] + update_password = module.params["update_password"] def needs_update(want, have, x): return want.get(x) and (want.get(x) != have.get(x)) def add(command, want, x): - command.append('set system login user %s %s' % (want['name'], x)) + command.append("set system login user %s %s" % (want["name"], x)) for update in updates: want, have = update - if want['state'] == 'absent': - commands.append('delete system login user %s' % want['name']) + if want["state"] == "absent": + commands.append("delete system login user %s" % want["name"]) continue - if needs_update(want, have, 'level'): - add(commands, want, "level %s" % want['level']) + if needs_update(want, have, "level"): + add(commands, want, "level %s" % want["level"]) - if needs_update(want, have, 'full_name'): - add(commands, want, "full-name %s" % want['full_name']) + if needs_update(want, have, "full_name"): + add(commands, want, "full-name %s" % want["full_name"]) - if needs_update(want, have, 'configured_password'): - if update_password == 'always' or not have: - add(commands, want, 'authentication plaintext-password %s' % want['configured_password']) + if needs_update(want, have, "configured_password"): + if update_password == "always" or not have: + add( + commands, + want, + "authentication plaintext-password %s" + % want["configured_password"], + ) return commands def parse_level(data): - match = re.search(r'level (\S+)', data, re.M) + match = re.search(r"level (\S+)", data, re.M) if match: level = match.group(1)[1:-1] return level def parse_full_name(data): - match = re.search(r'full-name (\S+)', data, re.M) + match = re.search(r"full-name (\S+)", data, re.M) if match: full_name = match.group(1)[1:-1] return full_name @@ -199,22 +208,22 @@ def parse_full_name(data): def config_to_dict(module): data = get_config(module) - match = re.findall(r'^set system login user (\S+)', data, re.M) + match = re.findall(r"^set system login user (\S+)", data, re.M) if not match: return list() instances = list() for user in set(match): - regex = r' %s .+$' % user + regex = r" %s .+$" % user cfg = re.findall(regex, data, re.M) - cfg = '\n'.join(cfg) + cfg = "\n".join(cfg) obj = { - 'name': user, - 'state': 'present', - 'configured_password': None, - 'level': parse_level(cfg), - 'full_name': parse_full_name(cfg) + "name": user, + "state": "present", + "configured_password": None, + "level": parse_level(cfg), + "full_name": parse_full_name(cfg), } instances.append(obj) @@ -227,7 +236,7 @@ def get_param_value(key, item, module): value = module.params[key] # validate the param value (if validator func exists) - validator = globals().get('validate_%s' % key) + validator = globals().get("validate_%s" % key) if all((value, validator)): validator(value, module) @@ -235,17 +244,17 @@ def get_param_value(key, item, module): def map_params_to_obj(module): - aggregate = module.params['aggregate'] + aggregate = module.params["aggregate"] if not aggregate: - if not module.params['name'] and module.params['purge']: + if not module.params["name"] and module.params["purge"]: return list() else: - users = [{'name': module.params['name']}] + users = [{"name": module.params["name"]}] else: users = list() for item in aggregate: if not isinstance(item, dict): - users.append({'name': item}) + users.append({"name": item}) else: users.append(item) @@ -253,10 +262,10 @@ def map_params_to_obj(module): for item in users: get_value = partial(get_param_value, item=item, module=module) - item['configured_password'] = get_value('configured_password') - item['full_name'] = get_value('full_name') - item['level'] = get_value('level') - item['state'] = get_value('state') + item["configured_password"] = get_value("configured_password") + item["full_name"] = get_value("full_name") + item["level"] = get_value("level") + item["state"] = get_value("state") objects.append(item) return objects @@ -265,7 +274,7 @@ def map_params_to_obj(module): def update_objects(want, have): updates = list() for entry in want: - item = next((i for i in have if i['name'] == entry['name']), None) + item = next((i for i in have if i["name"] == entry["name"]), None) if item is None: updates.append((entry, {})) elif item: @@ -280,65 +289,69 @@ def main(): """ element_spec = dict( name=dict(), - full_name=dict(), - level=dict(aliases=['role']), - + level=dict(aliases=["role"]), configured_password=dict(no_log=True), - update_password=dict(default='always', choices=['on_create', 'always']), - - state=dict(default='present', choices=['present', 'absent']) + update_password=dict(default="always", choices=["on_create", "always"]), + state=dict(default="present", choices=["present", "absent"]), ) aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) + aggregate_spec["name"] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec, aliases=['users', 'collection']), - purge=dict(type='bool', default=False) + aggregate=dict( + type="list", + elements="dict", + options=aggregate_spec, + aliases=["users", "collection"], + ), + purge=dict(type="bool", default=False), ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - mutually_exclusive = [('name', 'aggregate')] - module = AnsibleModule(argument_spec=argument_spec, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) + mutually_exclusive = [("name", "aggregate")] + module = AnsibleModule( + argument_spec=argument_spec, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) warnings = list() - if module.params['password'] and not module.params['configured_password']: + if module.params["password"] and not module.params["configured_password"]: warnings.append( - 'The "password" argument is used to authenticate the current connection. ' + - 'To set a user password use "configured_password" instead.' + 'The "password" argument is used to authenticate the current connection. ' + + 'To set a user password use "configured_password" instead.' ) - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = config_to_dict(module) commands = spec_to_commands(update_objects(want, have), module) - if module.params['purge']: - want_users = [x['name'] for x in want] - have_users = [x['name'] for x in have] + if module.params["purge"]: + want_users = [x["name"] for x in want] + have_users = [x["name"] for x in have] for item in set(have_users).difference(want_users): - commands.append('delete system login user %s' % item) + commands.append("delete system login user %s" % item) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_vlan.py b/plugins/modules/vyos_vlan.py index 88ab71b..983a50a 100644 --- a/plugins/modules/vyos_vlan.py +++ b/plugins/modules/vyos_vlan.py @@ -5,12 +5,15 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function + __metaclass__ = type -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ --- @@ -122,18 +125,20 @@ from copy import deepcopy from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import load_config, run_commands - -from ansible_collections.vyos.vyos.plugins.module_utils.network. \ - vyos.vyos import vyos_argument_spec +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) def search_obj_in_list(vlan_id, lst): obj = list() for o in lst: - if o['vlan_id'] == vlan_id: + if o["vlan_id"] == vlan_id: obj.append(o) return obj @@ -141,48 +146,52 @@ def search_obj_in_list(vlan_id, lst): def map_obj_to_commands(updates, module): commands = list() want, have = updates - purge = module.params['purge'] + purge = module.params["purge"] for w in want: - vlan_id = w['vlan_id'] - name = w['name'] - address = w['address'] - state = w['state'] - interfaces = w['interfaces'] + vlan_id = w["vlan_id"] + name = w["name"] + address = w["address"] + state = w["state"] + interfaces = w["interfaces"] obj_in_have = search_obj_in_list(vlan_id, have) - if state == 'absent': + if state == "absent": if obj_in_have: for obj in obj_in_have: - for i in obj['interfaces']: - commands.append('delete interfaces ethernet {0} vif {1}'.format(i, vlan_id)) + for i in obj["interfaces"]: + commands.append( + "delete interfaces ethernet {0} vif {1}".format(i, vlan_id) + ) - elif state == 'present': + elif state == "present": if not obj_in_have: - if w['interfaces'] and w['vlan_id']: - for i in w['interfaces']: - cmd = 'set interfaces ethernet {0} vif {1}'.format(i, vlan_id) - if w['name']: - commands.append(cmd + ' description {0}'.format(name)) - elif w['address']: - commands.append(cmd + ' address {0}'.format(address)) + if w["interfaces"] and w["vlan_id"]: + for i in w["interfaces"]: + cmd = "set interfaces ethernet {0} vif {1}".format(i, vlan_id) + if w["name"]: + commands.append(cmd + " description {0}".format(name)) + elif w["address"]: + commands.append(cmd + " address {0}".format(address)) else: commands.append(cmd) if purge: for h in have: - obj_in_want = search_obj_in_list(h['vlan_id'], want) + obj_in_want = search_obj_in_list(h["vlan_id"], want) if not obj_in_want: - for i in h['interfaces']: - commands.append('delete interfaces ethernet {0} vif {1}'.format(i, h['vlan_id'])) + for i in h["interfaces"]: + commands.append( + "delete interfaces ethernet {0} vif {1}".format(i, h["vlan_id"]) + ) return commands def map_params_to_obj(module): obj = [] - aggregate = module.params.get('aggregate') + aggregate = module.params.get("aggregate") if aggregate: for item in aggregate: for key in item: @@ -191,22 +200,24 @@ def map_params_to_obj(module): d = item.copy() - if not d['vlan_id']: - module.fail_json(msg='vlan_id is required') + if not d["vlan_id"]: + module.fail_json(msg="vlan_id is required") - d['vlan_id'] = str(d['vlan_id']) + d["vlan_id"] = str(d["vlan_id"]) module._check_required_one_of(module.required_one_of, item) obj.append(d) else: - obj.append({ - 'vlan_id': str(module.params['vlan_id']), - 'name': module.params['name'], - 'address': module.params['address'], - 'state': module.params['state'], - 'interfaces': module.params['interfaces'], - 'associated_interfaces': module.params['associated_interfaces'] - }) + obj.append( + { + "vlan_id": str(module.params["vlan_id"]), + "name": module.params["name"], + "address": module.params["address"], + "state": module.params["state"], + "interfaces": module.params["interfaces"], + "associated_interfaces": module.params["associated_interfaces"], + } + ) return obj @@ -215,30 +226,30 @@ def map_config_to_obj(module): objs = [] interfaces = list() - output = run_commands(module, 'show interfaces') + output = run_commands(module, "show interfaces") lines = output[0].strip().splitlines()[3:] for l in lines: - splitted_line = re.split(r'\s{2,}', l.strip()) + splitted_line = re.split(r"\s{2,}", l.strip()) obj = {} eth = splitted_line[0].strip("'") - if eth.startswith('eth'): - obj['interfaces'] = [] - if '.' in eth: - interface = eth.split('.')[0] - obj['interfaces'].append(interface) - obj['vlan_id'] = eth.split('.')[-1] + if eth.startswith("eth"): + obj["interfaces"] = [] + if "." in eth: + interface = eth.split(".")[0] + obj["interfaces"].append(interface) + obj["vlan_id"] = eth.split(".")[-1] else: - obj['interfaces'].append(eth) - obj['vlan_id'] = None + obj["interfaces"].append(eth) + obj["vlan_id"] = None - if splitted_line[1].strip("'") != '-': - obj['address'] = splitted_line[1].strip("'") + if splitted_line[1].strip("'") != "-": + obj["address"] = splitted_line[1].strip("'") if len(splitted_line) > 3: - obj['name'] = splitted_line[3].strip("'") - obj['state'] = 'present' + obj["name"] = splitted_line[3].strip("'") + obj["state"] = "present" objs.append(obj) return objs @@ -251,41 +262,44 @@ def check_declarative_intent_params(want, module, result): is_delay = False for w in want: - if w.get('associated_interfaces') is None: + if w.get("associated_interfaces") is None: continue - if result['changed'] and not is_delay: - time.sleep(module.params['delay']) + if result["changed"] and not is_delay: + time.sleep(module.params["delay"]) is_delay = True if have is None: have = map_config_to_obj(module) - obj_in_have = search_obj_in_list(w['vlan_id'], have) + obj_in_have = search_obj_in_list(w["vlan_id"], have) if obj_in_have: for obj in obj_in_have: - obj_interface.extend(obj['interfaces']) + obj_interface.extend(obj["interfaces"]) for w in want: - if w.get('associated_interfaces') is None: + if w.get("associated_interfaces") is None: continue - for i in w['associated_interfaces']: - if (set(obj_interface) - set(w['associated_interfaces'])) != set([]): - module.fail_json(msg='Interface {0} not configured on vlan {1}'.format(i, w['vlan_id'])) + for i in w["associated_interfaces"]: + if (set(obj_interface) - set(w["associated_interfaces"])) != set([]): + module.fail_json( + msg="Interface {0} not configured on vlan {1}".format( + i, w["vlan_id"] + ) + ) def main(): """ main entry point for module execution """ element_spec = dict( - vlan_id=dict(type='int'), + vlan_id=dict(type="int"), name=dict(), address=dict(), - interfaces=dict(type='list'), - associated_interfaces=dict(type='list'), - delay=dict(default=10, type='int'), - state=dict(default='present', - choices=['present', 'absent']) + interfaces=dict(type="list"), + associated_interfaces=dict(type="list"), + delay=dict(default=10, type="int"), + state=dict(default="present", choices=["present", "absent"]), ) aggregate_spec = deepcopy(element_spec) @@ -294,43 +308,47 @@ def main(): remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - purge=dict(default=False, type='bool') + aggregate=dict(type="list", elements="dict", options=aggregate_spec), + purge=dict(default=False, type="bool"), ) argument_spec.update(element_spec) argument_spec.update(vyos_argument_spec) - required_one_of = [['vlan_id', 'aggregate'], - ['aggregate', 'interfaces', 'associated_interfaces']] - - mutually_exclusive = [['vlan_id', 'aggregate']] - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive) + required_one_of = [ + ["vlan_id", "aggregate"], + ["aggregate", "interfaces", "associated_interfaces"], + ] + + mutually_exclusive = [["vlan_id", "aggregate"]] + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + ) warnings = list() - result = {'changed': False} + result = {"changed": False} if warnings: - result['warnings'] = warnings + result["warnings"] = warnings want = map_params_to_obj(module) have = map_config_to_obj(module) commands = map_obj_to_commands((want, have), module) - result['commands'] = commands + result["commands"] = commands if commands: commit = not module.check_mode load_config(module, commands, commit=commit) - result['changed'] = True + result["changed"] = True check_declarative_intent_params(want, module, result) module.exit_json(**result) -if __name__ == '__main__': +if __name__ == "__main__": main() |