mirror of
https://github.com/linux-system-roles/network.git
synced 2026-01-23 02:15:17 +00:00
Modularize role
Splitting the role in smaller parts helps to keep the overview and to develop separate tests.
This commit is contained in:
parent
d866422d9d
commit
382c34197b
9 changed files with 1522 additions and 1460 deletions
File diff suppressed because it is too large
Load diff
7
module_utils/network_lsr/__init__.py
Normal file
7
module_utils/network_lsr/__init__.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/python3 -tt
|
||||
# vim: fileencoding=utf8
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
class MyError(Exception):
|
||||
pass
|
||||
1071
module_utils/network_lsr/argument_validator.py
Normal file
1071
module_utils/network_lsr/argument_validator.py
Normal file
File diff suppressed because it is too large
Load diff
282
module_utils/network_lsr/utils.py
Normal file
282
module_utils/network_lsr/utils.py
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
#!/usr/bin/python3 -tt
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# vim: fileencoding=utf8
|
||||
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
|
||||
# pylint: disable=import-error, no-name-in-module
|
||||
from ansible.module_utils.network_lsr import MyError
|
||||
|
||||
|
||||
class Util:
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
STRING_TYPE = str if PY3 else basestring # noqa:F821
|
||||
|
||||
@staticmethod
|
||||
def first(iterable, default=None, pred=None):
|
||||
for v in iterable:
|
||||
if pred is None or pred(v):
|
||||
return v
|
||||
return default
|
||||
|
||||
@staticmethod
|
||||
def check_output(argv):
|
||||
# subprocess.check_output is python 2.7.
|
||||
with open("/dev/null", "wb") as DEVNULL:
|
||||
import subprocess
|
||||
|
||||
env = os.environ.copy()
|
||||
env["LANG"] = "C"
|
||||
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=DEVNULL, env=env)
|
||||
# FIXME: Can we assume this to always be UTF-8?
|
||||
out = p.communicate()[0].decode("UTF-8")
|
||||
if p.returncode != 0:
|
||||
raise MyError("failure calling %s: exit with %s" % (argv, p.returncode))
|
||||
return out
|
||||
|
||||
@classmethod
|
||||
def create_uuid(cls):
|
||||
cls.NM()
|
||||
return str(cls._uuid.uuid4())
|
||||
|
||||
@classmethod
|
||||
def NM(cls):
|
||||
n = getattr(cls, "_NM", None)
|
||||
if n is None:
|
||||
# Installing pygobject in a tox virtualenv does not work out of the
|
||||
# box
|
||||
# pylint: disable=import-error
|
||||
import gi
|
||||
|
||||
gi.require_version("NM", "1.0")
|
||||
from gi.repository import NM, GLib, Gio, GObject
|
||||
|
||||
cls._NM = NM
|
||||
cls._GLib = GLib
|
||||
cls._Gio = Gio
|
||||
cls._GObject = GObject
|
||||
n = NM
|
||||
import uuid
|
||||
|
||||
cls._uuid = uuid
|
||||
return n
|
||||
|
||||
@classmethod
|
||||
def GLib(cls):
|
||||
cls.NM()
|
||||
return cls._GLib
|
||||
|
||||
@classmethod
|
||||
def Gio(cls):
|
||||
cls.NM()
|
||||
return cls._Gio
|
||||
|
||||
@classmethod
|
||||
def GObject(cls):
|
||||
cls.NM()
|
||||
return cls._GObject
|
||||
|
||||
@classmethod
|
||||
def Timestamp(cls):
|
||||
return cls.GLib().get_monotonic_time()
|
||||
|
||||
@classmethod
|
||||
def GMainLoop(cls):
|
||||
gmainloop = getattr(cls, "_GMainLoop", None)
|
||||
if gmainloop is None:
|
||||
gmainloop = cls.GLib().MainLoop()
|
||||
cls._GMainLoop = gmainloop
|
||||
return gmainloop
|
||||
|
||||
@classmethod
|
||||
def GMainLoop_run(cls, timeout=None):
|
||||
if timeout is None:
|
||||
cls.GMainLoop().run()
|
||||
return True
|
||||
|
||||
GLib = cls.GLib()
|
||||
result = []
|
||||
loop = cls.GMainLoop()
|
||||
|
||||
def _timeout_cb(unused):
|
||||
result.append(1)
|
||||
loop.quit()
|
||||
return False
|
||||
|
||||
timeout_id = GLib.timeout_add(int(timeout * 1000), _timeout_cb, None)
|
||||
loop.run()
|
||||
if result:
|
||||
return False
|
||||
GLib.source_remove(timeout_id)
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def GMainLoop_iterate(cls, may_block=False):
|
||||
return cls.GMainLoop().get_context().iteration(may_block)
|
||||
|
||||
@classmethod
|
||||
def GMainLoop_iterate_all(cls):
|
||||
c = 0
|
||||
while cls.GMainLoop_iterate():
|
||||
c += 1
|
||||
return c
|
||||
|
||||
@classmethod
|
||||
def create_cancellable(cls):
|
||||
return cls.Gio().Cancellable.new()
|
||||
|
||||
@classmethod
|
||||
def error_is_cancelled(cls, e):
|
||||
GLib = cls.GLib()
|
||||
if isinstance(e, GLib.GError):
|
||||
if (
|
||||
e.domain == "g-io-error-quark"
|
||||
and e.code == cls.Gio().IOErrorEnum.CANCELLED
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def ifname_valid(ifname):
|
||||
# see dev_valid_name() in kernel's net/core/dev.c
|
||||
if not ifname:
|
||||
return False
|
||||
if ifname in [".", ".."]:
|
||||
return False
|
||||
if len(ifname) >= 16:
|
||||
return False
|
||||
if any([c == "/" or c == ":" or c.isspace() for c in ifname]):
|
||||
return False
|
||||
# FIXME: encoding issues regarding python unicode string
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def mac_aton(mac_str, force_len=None):
|
||||
# we also accept None and '' for convenience.
|
||||
# - None yiels None
|
||||
# - '' yields []
|
||||
if mac_str is None:
|
||||
return mac_str
|
||||
i = 0
|
||||
b = []
|
||||
for c in mac_str:
|
||||
if i == 2:
|
||||
if c != ":":
|
||||
raise MyError("not a valid MAC address: '%s'" % (mac_str))
|
||||
i = 0
|
||||
continue
|
||||
try:
|
||||
if i == 0:
|
||||
n = int(c, 16) * 16
|
||||
i = 1
|
||||
else:
|
||||
assert i == 1
|
||||
n = n + int(c, 16)
|
||||
i = 2
|
||||
b.append(n)
|
||||
except Exception:
|
||||
raise MyError("not a valid MAC address: '%s'" % (mac_str))
|
||||
if i == 1:
|
||||
raise MyError("not a valid MAC address: '%s'" % (mac_str))
|
||||
if force_len is not None:
|
||||
if force_len != len(b):
|
||||
raise MyError(
|
||||
"not a valid MAC address of length %s: '%s'" % (force_len, mac_str)
|
||||
)
|
||||
return b
|
||||
|
||||
@staticmethod
|
||||
def mac_ntoa(mac):
|
||||
if mac is None:
|
||||
return None
|
||||
return ":".join(["%02x" % c for c in mac])
|
||||
|
||||
@staticmethod
|
||||
def mac_norm(mac_str, force_len=None):
|
||||
return Util.mac_ntoa(Util.mac_aton(mac_str, force_len))
|
||||
|
||||
@staticmethod
|
||||
def boolean(arg):
|
||||
if arg is None or isinstance(arg, bool):
|
||||
return arg
|
||||
arg0 = arg
|
||||
if isinstance(arg, Util.STRING_TYPE):
|
||||
arg = arg.lower()
|
||||
|
||||
if arg in ["y", "yes", "on", "1", "true", 1, True]:
|
||||
return True
|
||||
if arg in ["n", "no", "off", "0", "false", 0, False]:
|
||||
return False
|
||||
|
||||
raise MyError("value '%s' is not a boolean" % (arg0))
|
||||
|
||||
@staticmethod
|
||||
def parse_ip(addr, family=None):
|
||||
if addr is None:
|
||||
return (None, None)
|
||||
if family is not None:
|
||||
Util.addr_family_check(family)
|
||||
a = socket.inet_pton(family, addr)
|
||||
else:
|
||||
a = None
|
||||
family = None
|
||||
try:
|
||||
a = socket.inet_pton(socket.AF_INET, addr)
|
||||
family = socket.AF_INET
|
||||
except Exception:
|
||||
a = socket.inet_pton(socket.AF_INET6, addr)
|
||||
family = socket.AF_INET6
|
||||
return (socket.inet_ntop(family, a), family)
|
||||
|
||||
@staticmethod
|
||||
def addr_family_check(family):
|
||||
if family != socket.AF_INET and family != socket.AF_INET6:
|
||||
raise MyError("invalid address family %s" % (family))
|
||||
|
||||
@staticmethod
|
||||
def addr_family_to_v(family):
|
||||
if family is None:
|
||||
return ""
|
||||
if family == socket.AF_INET:
|
||||
return "v4"
|
||||
if family == socket.AF_INET6:
|
||||
return "v6"
|
||||
raise MyError("invalid address family '%s'" % (family))
|
||||
|
||||
@staticmethod
|
||||
def addr_family_default_prefix(family):
|
||||
Util.addr_family_check(family)
|
||||
if family == socket.AF_INET:
|
||||
return 24
|
||||
else:
|
||||
return 64
|
||||
|
||||
@staticmethod
|
||||
def addr_family_valid_prefix(family, prefix):
|
||||
Util.addr_family_check(family)
|
||||
if family == socket.AF_INET:
|
||||
m = 32
|
||||
else:
|
||||
m = 128
|
||||
return prefix >= 0 and prefix <= m
|
||||
|
||||
@staticmethod
|
||||
def parse_address(address, family=None):
|
||||
try:
|
||||
parts = address.split()
|
||||
addr_parts = parts[0].split("/")
|
||||
if len(addr_parts) != 2:
|
||||
raise MyError("expect two addr-parts: ADDR/PLEN")
|
||||
a, family = Util.parse_ip(addr_parts[0], family)
|
||||
prefix = int(addr_parts[1])
|
||||
if not Util.addr_family_valid_prefix(family, prefix):
|
||||
raise MyError("invalid prefix %s" % (prefix))
|
||||
if len(parts) > 1:
|
||||
raise MyError("too many parts")
|
||||
return {"address": a, "family": family, "prefix": prefix}
|
||||
except Exception:
|
||||
raise MyError("invalid address '%s'" % (address))
|
||||
2
pylintrc
2
pylintrc
|
|
@ -16,7 +16,7 @@ ignore-patterns=
|
|||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()) + '/library')"
|
||||
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()) + '/library'); sys.path.append(os.path.dirname(find_pylintrc()) + '/module_utils'); sys.path.append(os.path.dirname(find_pylintrc()) + '/tests')"
|
||||
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
|
|
|
|||
1
tests/roles/linux-system-roles.network/module_utils
Symbolic link
1
tests/roles/linux-system-roles.network/module_utils
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../../module_utils/
|
||||
|
|
@ -12,6 +12,18 @@ import unittest
|
|||
TESTS_BASEDIR = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(1, os.path.join(TESTS_BASEDIR, "..", "library"))
|
||||
|
||||
try:
|
||||
from unittest import mock
|
||||
except ImportError: # py2
|
||||
import mock
|
||||
|
||||
sys.modules["ansible"] = mock.Mock()
|
||||
sys.modules["ansible.module_utils.basic"] = mock.Mock()
|
||||
sys.modules["ansible.module_utils"] = mock.Mock()
|
||||
sys.modules["ansible.module_utils.network_lsr"] = __import__("network_lsr")
|
||||
|
||||
# pylint: disable=import-error
|
||||
import network_lsr
|
||||
import network_connections as n
|
||||
|
||||
from network_connections import SysUtil
|
||||
|
|
@ -51,7 +63,8 @@ def pprint(msg, obj):
|
|||
obj.dump()
|
||||
|
||||
|
||||
ARGS_CONNECTIONS = n.ArgValidator_ListConnections()
|
||||
ARGS_CONNECTIONS = network_lsr.argument_validator.ArgValidator_ListConnections()
|
||||
VALIDATE_ONE_MODE_INITSCRIPTS = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
|
||||
|
||||
class TestValidator(unittest.TestCase):
|
||||
|
|
@ -59,7 +72,7 @@ class TestValidator(unittest.TestCase):
|
|||
self.assertRaises(n.ValidationError, v.validate, value)
|
||||
|
||||
def assert_nm_connection_routes_expected(self, connection, route_list_expected):
|
||||
parser = n.ArgValidatorIPRoute("route[?]")
|
||||
parser = network_lsr.argument_validator.ArgValidatorIPRoute("route[?]")
|
||||
route_list_exp = [parser.validate(r) for r in route_list_expected]
|
||||
route_list_new = itertools.chain(
|
||||
nmutil.setting_ip_config_get_routes(
|
||||
|
|
@ -92,7 +105,7 @@ class TestValidator(unittest.TestCase):
|
|||
if "type" in connection:
|
||||
connection["nm.exists"] = False
|
||||
connection["nm.uuid"] = n.Util.create_uuid()
|
||||
mode = n.ArgValidator_ListConnections.VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
mode = VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
for idx, connection in enumerate(connections):
|
||||
try:
|
||||
ARGS_CONNECTIONS.validate_connection_one(mode, connections, idx)
|
||||
|
|
@ -103,7 +116,9 @@ class TestValidator(unittest.TestCase):
|
|||
self.assertTrue(con_new)
|
||||
self.assertTrue(con_new.verify())
|
||||
if "nm_route_list_current" in kwargs:
|
||||
parser = n.ArgValidatorIPRoute("route[?]")
|
||||
parser = network_lsr.argument_validator.ArgValidatorIPRoute(
|
||||
"route[?]"
|
||||
)
|
||||
s4 = con_new.get_setting(NM.SettingIP4Config)
|
||||
s6 = con_new.get_setting(NM.SettingIP6Config)
|
||||
s4.clear_routes()
|
||||
|
|
@ -132,7 +147,7 @@ class TestValidator(unittest.TestCase):
|
|||
)
|
||||
|
||||
def do_connections_validate_ifcfg(self, input_connections, **kwargs):
|
||||
mode = n.ArgValidator_ListConnections.VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
mode = VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
connections = ARGS_CONNECTIONS.validate(input_connections)
|
||||
for idx, connection in enumerate(connections):
|
||||
try:
|
||||
|
|
@ -165,24 +180,26 @@ class TestValidator(unittest.TestCase):
|
|||
|
||||
def test_validate_str(self):
|
||||
|
||||
v = n.ArgValidatorStr("state")
|
||||
v = network_lsr.argument_validator.ArgValidatorStr("state")
|
||||
self.assertEqual("a", v.validate("a"))
|
||||
self.assertValidationError(v, 1)
|
||||
self.assertValidationError(v, None)
|
||||
|
||||
v = n.ArgValidatorStr("state", required=True)
|
||||
v = network_lsr.argument_validator.ArgValidatorStr("state", required=True)
|
||||
self.assertValidationError(v, None)
|
||||
|
||||
def test_validate_int(self):
|
||||
|
||||
v = n.ArgValidatorNum("state", default_value=None, numeric_type=float)
|
||||
v = network_lsr.argument_validator.ArgValidatorNum(
|
||||
"state", default_value=None, numeric_type=float
|
||||
)
|
||||
self.assertEqual(1, v.validate(1))
|
||||
self.assertEqual(1.5, v.validate(1.5))
|
||||
self.assertEqual(1.5, v.validate("1.5"))
|
||||
self.assertValidationError(v, None)
|
||||
self.assertValidationError(v, "1a")
|
||||
|
||||
v = n.ArgValidatorNum("state", default_value=None)
|
||||
v = network_lsr.argument_validator.ArgValidatorNum("state", default_value=None)
|
||||
self.assertEqual(1, v.validate(1))
|
||||
self.assertEqual(1, v.validate(1.0))
|
||||
self.assertEqual(1, v.validate("1"))
|
||||
|
|
@ -191,12 +208,12 @@ class TestValidator(unittest.TestCase):
|
|||
self.assertValidationError(v, 1.5)
|
||||
self.assertValidationError(v, "1.5")
|
||||
|
||||
v = n.ArgValidatorNum("state", required=True)
|
||||
v = network_lsr.argument_validator.ArgValidatorNum("state", required=True)
|
||||
self.assertValidationError(v, None)
|
||||
|
||||
def test_validate_bool(self):
|
||||
|
||||
v = n.ArgValidatorBool("state")
|
||||
v = network_lsr.argument_validator.ArgValidatorBool("state")
|
||||
self.assertEqual(True, v.validate("yes"))
|
||||
self.assertEqual(True, v.validate("yeS"))
|
||||
self.assertEqual(True, v.validate("Y"))
|
||||
|
|
@ -218,18 +235,22 @@ class TestValidator(unittest.TestCase):
|
|||
self.assertValidationError(v, "Ye")
|
||||
self.assertValidationError(v, "")
|
||||
self.assertValidationError(v, None)
|
||||
v = n.ArgValidatorBool("state", required=True)
|
||||
v = network_lsr.argument_validator.ArgValidatorBool("state", required=True)
|
||||
self.assertValidationError(v, None)
|
||||
|
||||
def test_validate_dict(self):
|
||||
|
||||
v = n.ArgValidatorDict(
|
||||
v = network_lsr.argument_validator.ArgValidatorDict(
|
||||
"dict",
|
||||
nested=[
|
||||
n.ArgValidatorNum("i", required=True),
|
||||
n.ArgValidatorStr("s", required=False, default_value="s_default"),
|
||||
n.ArgValidatorStr(
|
||||
"l", required=False, default_value=n.ArgValidator.MISSING
|
||||
network_lsr.argument_validator.ArgValidatorNum("i", required=True),
|
||||
network_lsr.argument_validator.ArgValidatorStr(
|
||||
"s", required=False, default_value="s_default"
|
||||
),
|
||||
network_lsr.argument_validator.ArgValidatorStr(
|
||||
"l",
|
||||
required=False,
|
||||
default_value=network_lsr.argument_validator.ArgValidator.MISSING,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
@ -242,16 +263,18 @@ class TestValidator(unittest.TestCase):
|
|||
|
||||
def test_validate_list(self):
|
||||
|
||||
v = n.ArgValidatorList("list", nested=n.ArgValidatorNum("i"))
|
||||
v = network_lsr.argument_validator.ArgValidatorList(
|
||||
"list", nested=network_lsr.argument_validator.ArgValidatorNum("i")
|
||||
)
|
||||
self.assertEqual([1, 5], v.validate(["1", 5]))
|
||||
self.assertValidationError(v, [1, "s"])
|
||||
|
||||
def test_1(self):
|
||||
|
||||
def test_empty(self):
|
||||
self.maxDiff = None
|
||||
|
||||
self.do_connections_validate([], [])
|
||||
|
||||
def test_minimal_ethernet(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -295,6 +318,9 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
[{"name": "5", "type": "ethernet"}, {"name": "5"}],
|
||||
)
|
||||
|
||||
def test_up_ethernet(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -333,6 +359,9 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
[{"name": "5", "state": "up", "type": "ethernet"}],
|
||||
)
|
||||
|
||||
def test_up_ethernet_no_autoconnect(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -390,13 +419,19 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_invalid_autoconnect(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_check_invalid([{"name": "a", "autoconnect": True}])
|
||||
|
||||
def test_absent(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[{"name": "5", "state": "absent", "ignore_errors": None}],
|
||||
[{"name": "5", "state": "absent"}],
|
||||
)
|
||||
|
||||
def test_up_ethernet_mac_mtu_static_ip(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -452,6 +487,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_up_single_v4_dns(self):
|
||||
self.maxDiff = None
|
||||
# set single IPv4 DNS server
|
||||
self.do_connections_validate(
|
||||
[
|
||||
|
|
@ -505,6 +542,9 @@ class TestValidator(unittest.TestCase):
|
|||
}
|
||||
],
|
||||
)
|
||||
|
||||
def test_routes(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -634,6 +674,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_vlan(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -763,6 +805,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_macvlan(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -943,73 +987,75 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_bridge_no_dhcp4_auto6(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
"autoconnect": True,
|
||||
"name": "prod2",
|
||||
"parent": None,
|
||||
"ip": {
|
||||
"dhcp4": False,
|
||||
"route_metric6": None,
|
||||
"route_metric4": None,
|
||||
"dns_search": [],
|
||||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"auto6": False,
|
||||
"dns": [],
|
||||
"address": [],
|
||||
"route_append_only": False,
|
||||
"rule_append_only": False,
|
||||
"route": [],
|
||||
},
|
||||
"ethernet": {"autoneg": None, "duplex": None, "speed": 0},
|
||||
"mac": None,
|
||||
"mtu": None,
|
||||
"zone": None,
|
||||
"check_iface_exists": True,
|
||||
"ethernet": {"autoneg": None, "duplex": None, "speed": 0},
|
||||
"force_state_change": None,
|
||||
"state": "up",
|
||||
"master": None,
|
||||
"ignore_errors": None,
|
||||
"interface_name": "bridge2",
|
||||
"type": "bridge",
|
||||
"ip": {
|
||||
"address": [],
|
||||
"auto6": False,
|
||||
"dhcp4": False,
|
||||
"dhcp4_send_hostname": None,
|
||||
"dns": [],
|
||||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
"route_metric4": None,
|
||||
"route_metric6": None,
|
||||
"rule_append_only": False,
|
||||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"mtu": None,
|
||||
"name": "prod2",
|
||||
"parent": None,
|
||||
"slave_type": None,
|
||||
"state": "up",
|
||||
"type": "bridge",
|
||||
"wait": None,
|
||||
"zone": None,
|
||||
},
|
||||
{
|
||||
"autoconnect": True,
|
||||
"name": "prod2-slave1",
|
||||
"parent": None,
|
||||
"ip": {
|
||||
"dhcp4": True,
|
||||
"auto6": True,
|
||||
"address": [],
|
||||
"route_append_only": False,
|
||||
"rule_append_only": False,
|
||||
"route": [],
|
||||
"route_metric6": None,
|
||||
"route_metric4": None,
|
||||
"dns_search": [],
|
||||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"dns": [],
|
||||
},
|
||||
"ethernet": {"autoneg": None, "duplex": None, "speed": 0},
|
||||
"mac": None,
|
||||
"mtu": None,
|
||||
"zone": None,
|
||||
"check_iface_exists": True,
|
||||
"ethernet": {"autoneg": None, "duplex": None, "speed": 0},
|
||||
"force_state_change": None,
|
||||
"state": "up",
|
||||
"master": "prod2",
|
||||
"ignore_errors": None,
|
||||
"interface_name": "eth1",
|
||||
"type": "ethernet",
|
||||
"ip": {
|
||||
"address": [],
|
||||
"auto6": True,
|
||||
"dhcp4": True,
|
||||
"dhcp4_send_hostname": None,
|
||||
"dns": [],
|
||||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
"route_metric4": None,
|
||||
"route_metric6": None,
|
||||
"rule_append_only": False,
|
||||
},
|
||||
"mac": None,
|
||||
"master": "prod2",
|
||||
"mtu": None,
|
||||
"name": "prod2-slave1",
|
||||
"parent": None,
|
||||
"slave_type": "bridge",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"wait": None,
|
||||
"zone": None,
|
||||
},
|
||||
],
|
||||
[
|
||||
|
|
@ -1030,6 +1076,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_bond(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1070,6 +1118,8 @@ class TestValidator(unittest.TestCase):
|
|||
[{"name": "bond1", "state": "up", "type": "bond"}],
|
||||
)
|
||||
|
||||
def test_bond_active_backup(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1117,9 +1167,13 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_invalid_values(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_check_invalid([{}])
|
||||
self.do_connections_check_invalid([{"name": "b", "xxx": 5}])
|
||||
|
||||
def test_ethernet_mac_address(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1157,45 +1211,8 @@ class TestValidator(unittest.TestCase):
|
|||
[{"name": "5", "type": "ethernet", "mac": "AA:bb:cC:DD:ee:FF"}],
|
||||
)
|
||||
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
"name": "5",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"autoconnect": True,
|
||||
"parent": None,
|
||||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"dhcp4": True,
|
||||
"address": [],
|
||||
"route_append_only": False,
|
||||
"rule_append_only": False,
|
||||
"route": [],
|
||||
"dns": [],
|
||||
"dns_search": [],
|
||||
"route_metric6": None,
|
||||
"dhcp4_send_hostname": None,
|
||||
},
|
||||
"ethernet": {"autoneg": None, "duplex": None, "speed": 0},
|
||||
"mac": None,
|
||||
"mtu": None,
|
||||
"zone": None,
|
||||
"master": None,
|
||||
"ignore_errors": None,
|
||||
"interface_name": "5",
|
||||
"check_iface_exists": True,
|
||||
"force_state_change": None,
|
||||
"slave_type": None,
|
||||
"wait": None,
|
||||
}
|
||||
],
|
||||
[{"name": "5", "state": "up", "type": "ethernet"}],
|
||||
)
|
||||
|
||||
def test_ethernet_speed_settings(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1262,6 +1279,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_bridge2(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1307,8 +1326,8 @@ class TestValidator(unittest.TestCase):
|
|||
"ip": {
|
||||
"address": [],
|
||||
"auto6": True,
|
||||
"dhcp4": True,
|
||||
"dhcp4_send_hostname": None,
|
||||
"dhcp4": True,
|
||||
"dns": [],
|
||||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
|
|
@ -1342,6 +1361,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_infiniband(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1406,6 +1427,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_infiniband2(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1477,6 +1500,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_route_metric_prefix(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1563,6 +1588,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_route_v6(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
|
|
@ -1688,6 +1715,8 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_check_invalid(
|
||||
[{"name": "b", "type": "ethernet", "mac": "aa:b"}]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@
|
|||
name: execute python unit tests
|
||||
tasks:
|
||||
- copy:
|
||||
src: ../library/network_connections.py
|
||||
dest: /tmp/test-unit-1/
|
||||
|
||||
- copy:
|
||||
src: test_network_connections.py
|
||||
src: "{{ item }}"
|
||||
dest: /tmp/test-unit-1/
|
||||
loop:
|
||||
- ../library/network_connections.py
|
||||
- test_network_connections.py
|
||||
- ../module_utils/network_lsr
|
||||
|
||||
- file:
|
||||
state: directory
|
||||
|
|
|
|||
6
tox.ini
6
tox.ini
|
|
@ -8,15 +8,16 @@ basepython = python2.7
|
|||
deps =
|
||||
py{26,27,36,37}: pytest-cov
|
||||
py{27,36,37}: pytest>=3.5.1
|
||||
py{26,27}: mock
|
||||
py26: pytest
|
||||
|
||||
[base]
|
||||
passenv = *
|
||||
setenv =
|
||||
PYTHONPATH = {toxinidir}/library
|
||||
PYTHONPATH = {toxinidir}/library:{toxinidir}/module_utils
|
||||
LC_ALL = C
|
||||
changedir = {toxinidir}/tests
|
||||
covtarget = network_connections
|
||||
covtarget = {toxinidir}/library --cov {toxinidir}/module_utils
|
||||
pytesttarget = .
|
||||
|
||||
[testenv:black]
|
||||
|
|
@ -93,6 +94,7 @@ commands =
|
|||
--errors-only \
|
||||
{posargs} \
|
||||
library/network_connections.py \
|
||||
module_utils/network_lsr \
|
||||
tests/test_network_connections.py
|
||||
|
||||
[testenv:flake8]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue