From 42039cd4368e074fd5c902c104e6b217015d3b51 Mon Sep 17 00:00:00 2001 From: Roman Belyakovsky Date: Tue, 1 Aug 2017 20:11:43 +0200 Subject: [PATCH] New module: manage debian network interfaces file /etc/network/interfaces (system/interfaces_file) (#25295) * Added new module interfaces_file * interfaces_file: added unit tests * interfaces_file: added golden files for unit tests * interfaces_file: moved to system modules * interfaces_file: fixed code formatting and convention issues --- lib/ansible/modules/system/interfaces_file.py | 395 ++++++++++++++++++ test/units/modules/system/__init__.py | 0 .../system/interfaces_file/__init__.py | 0 .../default_dhcp.test_no_changes | 6 + .../default_dhcp.test_no_changes.json | 18 + .../golden_output/default_dhcp_add_aggi_up | 6 + .../default_dhcp_add_aggi_up.exceptions.txt | 8 + .../default_dhcp_add_aggi_up.json | 18 + .../default_dhcp_add_and_delete_aggi_up | 6 + ...dhcp_add_and_delete_aggi_up.exceptions.txt | 17 + .../default_dhcp_add_and_delete_aggi_up.json | 18 + .../default_dhcp_set_aggi_and_eth0_mtu | 7 + ..._dhcp_set_aggi_and_eth0_mtu.exceptions.txt | 8 + .../default_dhcp_set_aggi_and_eth0_mtu.json | 18 + .../default_dhcp_set_aggi_slaves | 6 + ...efault_dhcp_set_aggi_slaves.exceptions.txt | 8 + .../default_dhcp_set_aggi_slaves.json | 18 + .../golden_output/servers.com.test_no_changes | 58 +++ .../servers.com.test_no_changes.json | 101 +++++ .../golden_output/servers.com_add_aggi_up | 59 +++ .../servers.com_add_aggi_up.exceptions.txt | 0 .../servers.com_add_aggi_up.json | 101 +++++ .../servers.com_add_and_delete_aggi_up | 58 +++ ....com_add_and_delete_aggi_up.exceptions.txt | 0 .../servers.com_add_and_delete_aggi_up.json | 101 +++++ .../servers.com_set_aggi_and_eth0_mtu | 58 +++ ...s.com_set_aggi_and_eth0_mtu.exceptions.txt | 8 + .../servers.com_set_aggi_and_eth0_mtu.json | 101 +++++ .../golden_output/servers.com_set_aggi_slaves | 58 +++ ...servers.com_set_aggi_slaves.exceptions.txt | 0 .../servers.com_set_aggi_slaves.json | 101 +++++ .../fixtures/input/default_dhcp | 6 + .../fixtures/input/servers.com | 58 +++ .../interfaces_file/test_interfaces_file.py | 140 +++++++ 34 files changed, 1565 insertions(+) create mode 100755 lib/ansible/modules/system/interfaces_file.py create mode 100644 test/units/modules/system/__init__.py create mode 100644 test/units/modules/system/interfaces_file/__init__.py create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.exceptions.txt create mode 100644 test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.json create mode 100644 test/units/modules/system/interfaces_file/fixtures/input/default_dhcp create mode 100644 test/units/modules/system/interfaces_file/fixtures/input/servers.com create mode 100644 test/units/modules/system/interfaces_file/test_interfaces_file.py diff --git a/lib/ansible/modules/system/interfaces_file.py b/lib/ansible/modules/system/interfaces_file.py new file mode 100755 index 00000000000..da342f5a42b --- /dev/null +++ b/lib/ansible/modules/system/interfaces_file.py @@ -0,0 +1,395 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# (c) 2016, Roman Belyakovsky +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +ANSIBLE_METADATA = {'metadata_version': '1.0', + 'status': ['stableinterface'], + 'supported_by': 'community'} + +DOCUMENTATION = ''' +--- +module: interfaces_file +short_description: Tweak settings in /etc/network/interfaces files +extends_documentation_fragment: files +description: + - Manage (add, remove, change) individual interface options in an interfaces-style file without having + to manage the file as a whole with, say, M(template) or M(assemble). Interface has to be presented in a file. + - Read information about interfaces from interfaces-styled files +version_added: "2.4" +options: + dest: + description: + - Path to the interfaces file + required: false + default: /etc/network/interfaces + iface: + description: + - Name of the interface, required for value changes or option remove + required: false + default: null + option: + description: + - Name of the option, required for value changes or option remove + required: false + default: null + value: + description: + - If I(option) is not presented for the I(interface) and I(state) is C(present) option will be added. + If I(option) already exists and is not C(pre-up), C(up), C(post-up) or C(down), it's value will be updated. + C(pre-up), C(up), C(post-up) and C(down) options can't be updated, only adding new options, removing existing + ones or cleaning the whole option set are supported + required: false + default: null + backup: + description: + - Create a backup file including the timestamp information so you can get + the original file back if you somehow clobbered it incorrectly. + required: false + default: "no" + choices: [ "yes", "no" ] + state: + description: + - If set to C(absent) the option or section will be removed if present instead of created. + required: false + default: "present" + choices: [ "present", "absent" ] + +notes: + - If option is defined multiple times last one will be updated but all will be deleted in case of an absent state +requirements: [] +author: "Roman Belyakovsky (@hryamzik)" +''' + +RETURN = ''' +dest: + description: destination file/path + returned: success + type: string + sample: "/etc/network/interfaces" +ifaces: + description: interfaces dictionary + returned: success + type: complex + contains: + ifaces: + description: interface dictionary + returned: success + type: dictionary + contains: + eth0: + description: Name of the interface + returned: success + type: dictionary + contains: + address_family: + description: interface address family + returned: success + type: string + sample: "inet" + method: + description: interface method + returned: success + type: string + sample: "manual" + mtu: + description: other options, all values returned as strings + returned: success + type: string + sample: "1500" + pre-up: + description: list of C(pre-up) scripts + returned: success + type: list + sample: + - "route add -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" + - "route add -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" + up: + description: list of C(up) scripts + returned: success + type: list + sample: + - "route add -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" + - "route add -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" + post-up: + description: list of C(post-up) scripts + returned: success + type: list + sample: + - "route add -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" + - "route add -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" + down: + description: list of C(down) scripts + returned: success + type: list + sample: + - "route del -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" + - "route del -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" +... +''' + +EXAMPLES = ''' +# Set eth1 mtu configuration value to 8000 +- interfaces_file: + dest: /etc/network/interfaces.d/eth1.cfg + iface: eth1 + option: mtu + value: 8000 + backup: yes + state: present + register: eth1_cfg +''' + +import os +import tempfile +import re +from ansible.module_utils.basic import AnsibleModule + + +def lineDict(line): + return {'line': line, 'line_type': 'unknown'} + + +def optionDict(line, iface, option, value): + return {'line': line, 'iface': iface, 'option': option, 'value': value, 'line_type': 'option'} + + +def getValueFromLine(s): + spaceRe = re.compile('\s+') + for m in spaceRe.finditer(s): + pass + valueEnd = m.start() + option = s.split()[0] + optionStart = s.find(option) + optionLen = len(option) + valueStart = re.search('\s', s[optionLen + optionStart:]).end() + optionLen + optionStart + return s[valueStart:valueEnd] + + +def read_interfaces_file(module, filename): + f = open(filename, 'r') + return read_interfaces_lines(module, f) + + +def read_interfaces_lines(module, line_strings): + lines = [] + ifaces = {} + currently_processing = None + i = 0 + for line in line_strings: + i += 1 + words = line.split() + if len(words) < 1: + lines.append(lineDict(line)) + continue + if words[0][0] == "#": + lines.append(lineDict(line)) + continue + if words[0] == "mapping": + # currmap = calloc(1, sizeof *currmap); + lines.append(lineDict(line)) + currently_processing = "MAPPING" + elif words[0] == "source": + lines.append(lineDict(line)) + currently_processing = "NONE" + elif words[0] == "source-dir": + lines.append(lineDict(line)) + currently_processing = "NONE" + elif words[0] == "iface": + currif = { + "pre-up": [], + "up": [], + "down": [], + "post-up": [] + } + iface_name, address_family_name, method_name = words[1:4] + if len(words) != 4: + module.fail_json(msg="Incorrect number of parameters (%d) in line %d, must be exectly 3" % (len(words), i)) + # TODO: put line and count parameters + return None, None + + currif['address_family'] = address_family_name + currif['method'] = method_name + + ifaces[iface_name] = currif + lines.append({'line': line, 'iface': iface_name, 'line_type': 'iface', 'params': currif}) + currently_processing = "IFACE" + elif words[0] == "auto": + lines.append(lineDict(line)) + currently_processing = "NONE" + elif words[0] == "allow-": + lines.append(lineDict(line)) + currently_processing = "NONE" + elif words[0] == "no-auto-down": + lines.append(lineDict(line)) + currently_processing = "NONE" + elif words[0] == "no-scripts": + lines.append(lineDict(line)) + currently_processing = "NONE" + else: + if currently_processing == "IFACE": + option_name = words[0] + # TODO: if option_name in currif.options + value = getValueFromLine(line) + lines.append(optionDict(line, iface_name, option_name, value)) + if option_name in ["pre-up", "up", "down", "post-up"]: + currif[option_name].append(value) + else: + currif[option_name] = value + elif currently_processing == "MAPPING": + lines.append(lineDict(line)) + elif currently_processing == "NONE": + lines.append(lineDict(line)) + else: + module.fail_json(msg="misplaced option %s in line %d" % (line, i)) + return None, None + return lines, ifaces + + +def setInterfaceOption(module, lines, iface, option, raw_value, state): + value = str(raw_value) + changed = False + + iface_lines = [item for item in lines if "iface" in item and item["iface"] == iface] + + if len(iface_lines) < 1: + # interface not found + module.fail_json(msg="Error: interface %s not found" % iface) + return changed + + iface_options = list(filter(lambda i: i['line_type'] == 'option', iface_lines)) + target_options = list(filter(lambda i: i['option'] == option, iface_options)) + + if state == "present": + if len(target_options) < 1: + changed = True + # add new option + last_line_dict = iface_lines[-1] + lines = addOptionAfterLine(option, value, iface, lines, last_line_dict, iface_options) + else: + if option in ["pre-up", "up", "down", "post-up"]: + if len(list(filter(lambda i: i['value'] == value, target_options))) < 1: + changed = True + lines = addOptionAfterLine(option, value, iface, lines, target_options[-1], iface_options) + else: + # if more than one option found edit the last one + if target_options[-1]['value'] != value: + changed = True + target_option = target_options[-1] + old_line = target_option['line'] + old_value = target_option['value'] + prefix_start = old_line.find(option) + optionLen = len(option) + old_value_position = re.search("\s+".join(old_value.split()), old_line[prefix_start + optionLen:]) + start = old_value_position.start() + prefix_start + optionLen + end = old_value_position.end() + prefix_start + optionLen + line = old_line[:start] + value + old_line[end:] + index = len(lines) - lines[::-1].index(target_option) - 1 + lines[index] = optionDict(line, iface, option, value) + elif state == "absent": + if len(target_options) >= 1: + if option in ["pre-up", "up", "down", "post-up"] and value is not None and value != "None": + for target_option in filter(lambda i: i['value'] == value, target_options): + changed = True + lines = list(filter(lambda l: l != target_option, lines)) + else: + changed = True + for target_option in target_options: + lines = list(filter(lambda l: l != target_option, lines)) + else: + module.fail_json(msg="Error: unsupported state %s, has to be either present or absent" % state) + + return changed, lines + pass + + +def addOptionAfterLine(option, value, iface, lines, last_line_dict, iface_options): + last_line = last_line_dict['line'] + prefix_start = last_line.find(last_line.split()[0]) + suffix_start = last_line.rfind(last_line.split()[-1]) + len(last_line.split()[-1]) + prefix = last_line[:prefix_start] + + if len(iface_options) < 1: + # interface has no options, ident + prefix += " " + + line = prefix + "%s %s" % (option, value) + last_line[suffix_start:] + option_dict = optionDict(line, iface, option, value) + index = len(lines) - lines[::-1].index(last_line_dict) + lines.insert(index, option_dict) + return lines + + +def write_changes(module, lines, dest): + + tmpfd, tmpfile = tempfile.mkstemp() + f = os.fdopen(tmpfd, 'wb') + f.writelines(lines) + f.close() + module.atomic_move(tmpfile, os.path.realpath(dest)) + + +def main(): + module = AnsibleModule( + argument_spec=dict( + dest=dict(default='/etc/network/interfaces', required=False), + iface=dict(required=False), + option=dict(required=False), + value=dict(required=False), + backup=dict(default='no', type='bool'), + state=dict(default='present', choices=['present', 'absent']), + ), + add_file_common_args=True, + supports_check_mode=True + ) + + dest = os.path.expanduser(module.params['dest']) + + iface = module.params['iface'] + option = module.params['option'] + value = module.params['value'] + backup = module.params['backup'] + state = module.params['state'] + + if option is not None and iface is None: + module.fail_json(msg="Inteface must be set if option is defined") + + if option is not None and state == "present" and value is None: + module.fail_json(msg="Value must be set if option is defined and state is 'present'") + + lines, ifaces = read_interfaces_file(module, dest) + + changed = False + + if option is not None: + changed, lines = setInterfaceOption(module, lines, iface, option, value, state) + + if changed: + _, ifaces = read_interfaces_lines(module, [d['line'] for d in lines if 'line' in d]) + + if changed and not module.check_mode: + if backup: + module.backup_local(dest) + write_changes(module, [d['line'] for d in lines if 'line' in d], dest) + + module.exit_json(dest=dest, changed=changed, ifaces=ifaces) + + +if __name__ == '__main__': + main() diff --git a/test/units/modules/system/__init__.py b/test/units/modules/system/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/system/interfaces_file/__init__.py b/test/units/modules/system/interfaces_file/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes new file mode 100644 index 00000000000..bd4522ec09f --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes @@ -0,0 +1,6 @@ +# The loopback network interface +auto lo eth0 +iface lo inet loopback + +# The primary network interface +iface eth0 inet dhcp diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes.json new file mode 100644 index 00000000000..bffc17a9897 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp.test_no_changes.json @@ -0,0 +1,18 @@ +{ + "eth0": { + "address_family": "inet", + "down": [], + "method": "dhcp", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up new file mode 100644 index 00000000000..bd4522ec09f --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up @@ -0,0 +1,6 @@ +# The loopback network interface +auto lo eth0 +iface lo inet loopback + +# The primary network interface +iface eth0 inet dhcp diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.exceptions.txt new file mode 100644 index 00000000000..8d223b041b6 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.exceptions.txt @@ -0,0 +1,8 @@ +[0] fail_json message: Error: interface aggi not found +options: +{ + "iface": "aggi", + "option": "up", + "state": "present", + "value": "route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi" +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.json new file mode 100644 index 00000000000..bffc17a9897 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_aggi_up.json @@ -0,0 +1,18 @@ +{ + "eth0": { + "address_family": "inet", + "down": [], + "method": "dhcp", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up new file mode 100644 index 00000000000..bd4522ec09f --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up @@ -0,0 +1,6 @@ +# The loopback network interface +auto lo eth0 +iface lo inet loopback + +# The primary network interface +iface eth0 inet dhcp diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.exceptions.txt new file mode 100644 index 00000000000..1c9adbd9fcf --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.exceptions.txt @@ -0,0 +1,17 @@ +[0] fail_json message: Error: interface aggi not found +options: +{ + "iface": "aggi", + "option": "up", + "state": "present", + "value": "route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi" +} +===== +[1] fail_json message: Error: interface aggi not found +options: +{ + "iface": "aggi", + "option": "up", + "state": "absent", + "value": null +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.json new file mode 100644 index 00000000000..bffc17a9897 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_add_and_delete_aggi_up.json @@ -0,0 +1,18 @@ +{ + "eth0": { + "address_family": "inet", + "down": [], + "method": "dhcp", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu new file mode 100644 index 00000000000..7bbad22a5e3 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu @@ -0,0 +1,7 @@ +# The loopback network interface +auto lo eth0 +iface lo inet loopback + +# The primary network interface +iface eth0 inet dhcp + mtu 1350 diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.exceptions.txt new file mode 100644 index 00000000000..3f0da8b1c71 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.exceptions.txt @@ -0,0 +1,8 @@ +[0] fail_json message: Error: interface aggi not found +options: +{ + "iface": "aggi", + "option": "mtu", + "state": "present", + "value": "1350" +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.json new file mode 100644 index 00000000000..bffc17a9897 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_and_eth0_mtu.json @@ -0,0 +1,18 @@ +{ + "eth0": { + "address_family": "inet", + "down": [], + "method": "dhcp", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves new file mode 100644 index 00000000000..bd4522ec09f --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves @@ -0,0 +1,6 @@ +# The loopback network interface +auto lo eth0 +iface lo inet loopback + +# The primary network interface +iface eth0 inet dhcp diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.exceptions.txt new file mode 100644 index 00000000000..0af87750b71 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.exceptions.txt @@ -0,0 +1,8 @@ +[0] fail_json message: Error: interface aggi not found +options: +{ + "iface": "aggi", + "option": "slaves", + "state": "present", + "value": "int1 int3" +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.json new file mode 100644 index 00000000000..bffc17a9897 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/default_dhcp_set_aggi_slaves.json @@ -0,0 +1,18 @@ +{ + "eth0": { + "address_family": "inet", + "down": [], + "method": "dhcp", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes new file mode 100644 index 00000000000..4356aa47d7e --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes @@ -0,0 +1,58 @@ + auto aggi + iface aggi inet static + hwaddress ether 22:44:77:88:D5:96 + address 10.44.15.196 + netmask 255.255.255.248 + mtu 1500 + slaves int1 int2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K aggi tx off tso off + + auto agge + iface agge inet manual + + auto br0 + iface br0 inet static + bridge_ports agge + hwaddress ether 22:44:77:88:D5:98 + address 188.44.133.76 + netmask 255.255.255.248 + gateway 188.44.133.75 + slaves ext1 ext2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K agge tx off tso off + + up route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi + up route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi + up route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi + + auto int1 + iface int1 inet manual + bond-master aggi + + auto int2 + iface int2 inet manual + bond-master aggi + + auto ext1 + iface ext1 inet manual + bond-master agge + + auto ext2 + iface ext2 inet manual + bond-master agge + + auto lo + iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes.json new file mode 100644 index 00000000000..0460b552a9d --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com.test_no_changes.json @@ -0,0 +1,101 @@ +{ + "agge": { + "address_family": "inet", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "aggi": { + "address": "10.44.15.196", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "down": [], + "hwaddress": "ether 22:44:77:88:D5:96", + "method": "static", + "mtu": "1500", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K aggi tx off tso off" + ], + "pre-up": [], + "slaves": "int1 int2", + "up": [] + }, + "br0": { + "address": "188.44.133.76", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "bridge_ports": "agge", + "down": [], + "gateway": "188.44.133.75", + "hwaddress": "ether 22:44:77:88:D5:98", + "method": "static", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K agge tx off tso off" + ], + "pre-up": [], + "slaves": "ext1 ext2", + "up": [ + "route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi", + "route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi", + "route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi" + ] + }, + "ext1": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "ext2": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int1": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int2": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up new file mode 100644 index 00000000000..a8428de1bc5 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up @@ -0,0 +1,59 @@ + auto aggi + iface aggi inet static + hwaddress ether 22:44:77:88:D5:96 + address 10.44.15.196 + netmask 255.255.255.248 + mtu 1500 + slaves int1 int2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K aggi tx off tso off + up route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi + + auto agge + iface agge inet manual + + auto br0 + iface br0 inet static + bridge_ports agge + hwaddress ether 22:44:77:88:D5:98 + address 188.44.133.76 + netmask 255.255.255.248 + gateway 188.44.133.75 + slaves ext1 ext2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K agge tx off tso off + + up route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi + up route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi + up route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi + + auto int1 + iface int1 inet manual + bond-master aggi + + auto int2 + iface int2 inet manual + bond-master aggi + + auto ext1 + iface ext1 inet manual + bond-master agge + + auto ext2 + iface ext2 inet manual + bond-master agge + + auto lo + iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.exceptions.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.json new file mode 100644 index 00000000000..0460b552a9d --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_aggi_up.json @@ -0,0 +1,101 @@ +{ + "agge": { + "address_family": "inet", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "aggi": { + "address": "10.44.15.196", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "down": [], + "hwaddress": "ether 22:44:77:88:D5:96", + "method": "static", + "mtu": "1500", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K aggi tx off tso off" + ], + "pre-up": [], + "slaves": "int1 int2", + "up": [] + }, + "br0": { + "address": "188.44.133.76", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "bridge_ports": "agge", + "down": [], + "gateway": "188.44.133.75", + "hwaddress": "ether 22:44:77:88:D5:98", + "method": "static", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K agge tx off tso off" + ], + "pre-up": [], + "slaves": "ext1 ext2", + "up": [ + "route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi", + "route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi", + "route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi" + ] + }, + "ext1": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "ext2": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int1": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int2": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up new file mode 100644 index 00000000000..4356aa47d7e --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up @@ -0,0 +1,58 @@ + auto aggi + iface aggi inet static + hwaddress ether 22:44:77:88:D5:96 + address 10.44.15.196 + netmask 255.255.255.248 + mtu 1500 + slaves int1 int2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K aggi tx off tso off + + auto agge + iface agge inet manual + + auto br0 + iface br0 inet static + bridge_ports agge + hwaddress ether 22:44:77:88:D5:98 + address 188.44.133.76 + netmask 255.255.255.248 + gateway 188.44.133.75 + slaves ext1 ext2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K agge tx off tso off + + up route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi + up route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi + up route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi + + auto int1 + iface int1 inet manual + bond-master aggi + + auto int2 + iface int2 inet manual + bond-master aggi + + auto ext1 + iface ext1 inet manual + bond-master agge + + auto ext2 + iface ext2 inet manual + bond-master agge + + auto lo + iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.exceptions.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.json new file mode 100644 index 00000000000..0460b552a9d --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_add_and_delete_aggi_up.json @@ -0,0 +1,101 @@ +{ + "agge": { + "address_family": "inet", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "aggi": { + "address": "10.44.15.196", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "down": [], + "hwaddress": "ether 22:44:77:88:D5:96", + "method": "static", + "mtu": "1500", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K aggi tx off tso off" + ], + "pre-up": [], + "slaves": "int1 int2", + "up": [] + }, + "br0": { + "address": "188.44.133.76", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "bridge_ports": "agge", + "down": [], + "gateway": "188.44.133.75", + "hwaddress": "ether 22:44:77:88:D5:98", + "method": "static", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K agge tx off tso off" + ], + "pre-up": [], + "slaves": "ext1 ext2", + "up": [ + "route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi", + "route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi", + "route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi" + ] + }, + "ext1": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "ext2": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int1": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int2": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu new file mode 100644 index 00000000000..8554d039864 --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu @@ -0,0 +1,58 @@ + auto aggi + iface aggi inet static + hwaddress ether 22:44:77:88:D5:96 + address 10.44.15.196 + netmask 255.255.255.248 + mtu 1350 + slaves int1 int2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K aggi tx off tso off + + auto agge + iface agge inet manual + + auto br0 + iface br0 inet static + bridge_ports agge + hwaddress ether 22:44:77:88:D5:98 + address 188.44.133.76 + netmask 255.255.255.248 + gateway 188.44.133.75 + slaves ext1 ext2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K agge tx off tso off + + up route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi + up route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi + up route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi + + auto int1 + iface int1 inet manual + bond-master aggi + + auto int2 + iface int2 inet manual + bond-master aggi + + auto ext1 + iface ext1 inet manual + bond-master agge + + auto ext2 + iface ext2 inet manual + bond-master agge + + auto lo + iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.exceptions.txt new file mode 100644 index 00000000000..764c9cb016c --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.exceptions.txt @@ -0,0 +1,8 @@ +[1] fail_json message: Error: interface eth0 not found +options: +{ + "iface": "eth0", + "option": "mtu", + "state": "present", + "value": "1350" +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.json new file mode 100644 index 00000000000..0460b552a9d --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_and_eth0_mtu.json @@ -0,0 +1,101 @@ +{ + "agge": { + "address_family": "inet", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "aggi": { + "address": "10.44.15.196", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "down": [], + "hwaddress": "ether 22:44:77:88:D5:96", + "method": "static", + "mtu": "1500", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K aggi tx off tso off" + ], + "pre-up": [], + "slaves": "int1 int2", + "up": [] + }, + "br0": { + "address": "188.44.133.76", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "bridge_ports": "agge", + "down": [], + "gateway": "188.44.133.75", + "hwaddress": "ether 22:44:77:88:D5:98", + "method": "static", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K agge tx off tso off" + ], + "pre-up": [], + "slaves": "ext1 ext2", + "up": [ + "route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi", + "route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi", + "route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi" + ] + }, + "ext1": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "ext2": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int1": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int2": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves new file mode 100644 index 00000000000..0118fcdf27d --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves @@ -0,0 +1,58 @@ + auto aggi + iface aggi inet static + hwaddress ether 22:44:77:88:D5:96 + address 10.44.15.196 + netmask 255.255.255.248 + mtu 1500 + slaves int1 int3 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K aggi tx off tso off + + auto agge + iface agge inet manual + + auto br0 + iface br0 inet static + bridge_ports agge + hwaddress ether 22:44:77:88:D5:98 + address 188.44.133.76 + netmask 255.255.255.248 + gateway 188.44.133.75 + slaves ext1 ext2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K agge tx off tso off + + up route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi + up route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi + up route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi + + auto int1 + iface int1 inet manual + bond-master aggi + + auto int2 + iface int2 inet manual + bond-master aggi + + auto ext1 + iface ext1 inet manual + bond-master agge + + auto ext2 + iface ext2 inet manual + bond-master agge + + auto lo + iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.exceptions.txt b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.exceptions.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.json b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.json new file mode 100644 index 00000000000..0460b552a9d --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/golden_output/servers.com_set_aggi_slaves.json @@ -0,0 +1,101 @@ +{ + "agge": { + "address_family": "inet", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "aggi": { + "address": "10.44.15.196", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "down": [], + "hwaddress": "ether 22:44:77:88:D5:96", + "method": "static", + "mtu": "1500", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K aggi tx off tso off" + ], + "pre-up": [], + "slaves": "int1 int2", + "up": [] + }, + "br0": { + "address": "188.44.133.76", + "address_family": "inet", + "bond_downdelay": "200", + "bond_lacp_rate": "slow", + "bond_miimon": "100", + "bond_mode": "4", + "bond_updelay": "200", + "bond_xmit_hash_policy": "layer3+4", + "bridge_ports": "agge", + "down": [], + "gateway": "188.44.133.75", + "hwaddress": "ether 22:44:77:88:D5:98", + "method": "static", + "netmask": "255.255.255.248", + "post-up": [ + "/sbin/ethtool -K agge tx off tso off" + ], + "pre-up": [], + "slaves": "ext1 ext2", + "up": [ + "route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi", + "route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi", + "route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi" + ] + }, + "ext1": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "ext2": { + "address_family": "inet", + "bond-master": "agge", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int1": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "int2": { + "address_family": "inet", + "bond-master": "aggi", + "down": [], + "method": "manual", + "post-up": [], + "pre-up": [], + "up": [] + }, + "lo": { + "address_family": "inet", + "down": [], + "method": "loopback", + "post-up": [], + "pre-up": [], + "up": [] + } +} \ No newline at end of file diff --git a/test/units/modules/system/interfaces_file/fixtures/input/default_dhcp b/test/units/modules/system/interfaces_file/fixtures/input/default_dhcp new file mode 100644 index 00000000000..bd4522ec09f --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/input/default_dhcp @@ -0,0 +1,6 @@ +# The loopback network interface +auto lo eth0 +iface lo inet loopback + +# The primary network interface +iface eth0 inet dhcp diff --git a/test/units/modules/system/interfaces_file/fixtures/input/servers.com b/test/units/modules/system/interfaces_file/fixtures/input/servers.com new file mode 100644 index 00000000000..4356aa47d7e --- /dev/null +++ b/test/units/modules/system/interfaces_file/fixtures/input/servers.com @@ -0,0 +1,58 @@ + auto aggi + iface aggi inet static + hwaddress ether 22:44:77:88:D5:96 + address 10.44.15.196 + netmask 255.255.255.248 + mtu 1500 + slaves int1 int2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K aggi tx off tso off + + auto agge + iface agge inet manual + + auto br0 + iface br0 inet static + bridge_ports agge + hwaddress ether 22:44:77:88:D5:98 + address 188.44.133.76 + netmask 255.255.255.248 + gateway 188.44.133.75 + slaves ext1 ext2 + bond_mode 4 + bond_miimon 100 + bond_downdelay 200 + bond_updelay 200 + bond_lacp_rate slow + bond_xmit_hash_policy layer3+4 + post-up /sbin/ethtool -K agge tx off tso off + + up route add -net 10.0.0.0/8 gw 10.44.15.117 dev aggi + up route add -net 192.168.0.0/16 gw 10.44.15.117 dev aggi + up route add -net 188.44.208.0/21 gw 10.44.15.117 dev aggi + + auto int1 + iface int1 inet manual + bond-master aggi + + auto int2 + iface int2 inet manual + bond-master aggi + + auto ext1 + iface ext1 inet manual + bond-master agge + + auto ext2 + iface ext2 inet manual + bond-master agge + + auto lo + iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/test/units/modules/system/interfaces_file/test_interfaces_file.py b/test/units/modules/system/interfaces_file/test_interfaces_file.py new file mode 100644 index 00000000000..1e275d87efd --- /dev/null +++ b/test/units/modules/system/interfaces_file/test_interfaces_file.py @@ -0,0 +1,140 @@ +# (c) 2017, Roman Belyakovsky +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ansible.compat.tests import unittest +import ansible.module_utils.basic +from ansible.modules.system import interfaces_file +import os +import json +import sys +import io +import inspect +import json + + +class AnsibleFailJson(Exception): + pass + + +class ModuleMocked(): + def fail_json(self, msg): + raise AnsibleFailJson(msg) + pass + + +module = ModuleMocked() +fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'input') +golden_output_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'golden_output') + + +class TestInterfacesFileModule(unittest.TestCase): + def getTestFiles(self): + return next(os.walk(fixture_path))[2] + + def compareInterfacesLinesToFile(self, interfaces_lines, path, testname=None): + if not testname: + testname = "%s.%s" % (path, inspect.stack()[1][3]) + self.compareStringWithFile("".join([d['line'] for d in interfaces_lines if 'line' in d]), testname) + + def compareInterfacesToFile(self, ifaces, path, testname=None): + if not testname: + testname = "%s.%s.json" % (path, inspect.stack()[1][3]) + self.compareStringWithFile(json.dumps(ifaces, sort_keys=True, indent=4, separators=(',', ': ')), testname) + + def compareStringWithFile(self, string, path): + # self.assertEqual("","_",msg=path) + testfilepath = os.path.join(golden_output_path, path) + goldenstring = string + if not os.path.isfile(testfilepath): + f = io.open(testfilepath, 'wb') + f.write(string) + f.close() + else: + with open(testfilepath, 'r') as goldenfile: + goldenstring = goldenfile.read() + goldenfile.close() + self.assertEqual(string, goldenstring) + + def test_no_changes(self): + for testfile in self.getTestFiles(): + path = os.path.join(fixture_path, testfile) + lines, ifaces = interfaces_file.read_interfaces_file(module, path) + self.compareInterfacesLinesToFile(lines, testfile) + self.compareInterfacesToFile(ifaces, testfile) + + def test_add_up_aoption_to_aggi(self): + testcases = { + "add_aggi_up": [ + { + 'iface': 'aggi', + 'option': 'up', + 'value': 'route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi', + 'state': 'present', + } + ], + "add_and_delete_aggi_up": [ + { + 'iface': 'aggi', + 'option': 'up', + 'value': 'route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi', + 'state': 'present', + }, + { + 'iface': 'aggi', + 'option': 'up', + 'value': None, + 'state': 'absent', + }, + ], + "set_aggi_slaves": [ + { + 'iface': 'aggi', + 'option': 'slaves', + 'value': 'int1 int3', + 'state': 'present', + }, + ], + "set_aggi_and_eth0_mtu": [ + { + 'iface': 'aggi', + 'option': 'mtu', + 'value': '1350', + 'state': 'present', + }, + { + 'iface': 'eth0', + 'option': 'mtu', + 'value': '1350', + 'state': 'present', + }, + ], + } + for testname, options_list in testcases.items(): + for testfile in self.getTestFiles(): + path = os.path.join(fixture_path, testfile) + lines, ifaces = interfaces_file.read_interfaces_file(module, path) + fail_json_iterations = [] + for i, options in enumerate(options_list): + try: + _, lines = interfaces_file.setInterfaceOption(module, lines, options['iface'], options['option'], options['value'], options['state']) + except AnsibleFailJson as e: + fail_json_iterations.append("[%d] fail_json message: %s\noptions:\n%s" % + (i, str(e), json.dumps(options, sort_keys=True, indent=4, separators=(',', ': ')))) + self.compareStringWithFile("\n=====\n".join(fail_json_iterations), "%s_%s.exceptions.txt" % (testfile, testname)) + + self.compareInterfacesLinesToFile(lines, testfile, "%s_%s" % (testfile, testname)) + self.compareInterfacesToFile(ifaces, testfile, "%s_%s.json" % (testfile, testname))