Skip to content

Commit

Permalink
Interface names and default (#615)
Browse files Browse the repository at this point in the history
Also Fix breaking change in mypy 0.900 and install missing stub package for paramiko
  • Loading branch information
romainx committed Jun 20, 2021
1 parent 8be8a29 commit 5c46c79
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 5 deletions.
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mock
pytest-cov
pytest-xdist
paramiko
types-paramiko
tornado<5
salt
pywinrm
Expand Down
23 changes: 23 additions & 0 deletions test/test_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,3 +677,26 @@ def test_addr_namespace(host):
with pytest.raises(NotImplementedError):
# nc is not available so an error is raised
assert not namespace_lookup.port("443").is_reachable


@pytest.mark.parametrize(
"family",
["inet", None],
)
def test_interface(host, family):
# exist
assert host.interface("eth0", family=family).exists
assert not host.interface("does_not_exist", family=family).exists
# adresses
addresses = host.interface.default(family).addresses
assert len(addresses) > 0
for add in addresses:
try:
ip_address(add)
except ValueError:
pytest.fail(f"{add} is not a valid IP address")
# names and default
assert "eth0" in host.interface.names()
default_itf = host.interface.default(family)
assert default_itf.name == "eth0"
assert default_itf.exists
64 changes: 59 additions & 5 deletions testinfra/modules/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,20 @@


class Interface(Module):
"""Test network interfaces"""
"""Test network interfaces
def __init__(self, name):
>>> host.interface("eth0").exists
True
Optionally, the protocol family to use can be enforced.
>>> host.interface("eth0", "inet6").adresses
['fe80::e291:f5ff:fe98:6b8c']
"""

def __init__(self, name, family=None):
self.name = name
self.family = family
super().__init__()

@property
Expand Down Expand Up @@ -49,30 +59,74 @@ def get_module_class(cls, host):
return BSDInterface
raise NotImplementedError

@classmethod
def names(cls):
"""Return the names of all the interfaces.
>>> host.interface.names()
['lo', 'tunl0', 'ip6tnl0', 'eth0']
"""
raise NotImplementedError

@classmethod
def default(cls, family=None):
"""Return the interface used for the default route.
>>> host.interface.default()
<interface eth0>
Optionally, the protocol family to use can be enforced.
>>> host.interface.default("inet6")
None
"""
raise NotImplementedError


class LinuxInterface(Interface):
@cached_property
def _ip(self):
return self.find_command("ip")
ip_cmd = self.find_command("ip")
if self.family is not None:
ip_cmd = f"{ip_cmd} -f {self.family}"
return ip_cmd

@property
def exists(self):
return self.run_test("%s link show %s", self._ip, self.name).rc == 0
return self.run_test("{} link show %s".format(self._ip), self.name).rc == 0

@property
def speed(self):
return int(self.check_output("cat /sys/class/net/%s/speed", self.name))

@property
def addresses(self):
stdout = self.check_output("%s addr show %s", self._ip, self.name)
stdout = self.check_output("{} addr show %s".format(self._ip), self.name)
addrs = []
for line in stdout.splitlines():
splitted = [e.strip() for e in line.split(" ") if e]
if splitted and splitted[0] in ("inet", "inet6"):
addrs.append(splitted[1].split("/", 1)[0])
return addrs

@classmethod
def default(cls, family=None):
_default = cls(None, family=family)
out = cls.check_output("{} route ls".format(_default._ip))
for line in out.splitlines():
if "default" in line:
_default.name = line.strip().rsplit(" ", 1)[-1]
return _default

@classmethod
def names(cls):
# -o is to tell the ip command to return 1 line per interface
out = cls.check_output("{} -o link show".format(cls(None)._ip))
interfaces = []
for line in out.splitlines():
interfaces.append(line.strip().split(": ", 2)[1].split("@", 1)[0])
return interfaces


class BSDInterface(Interface):
@property
Expand Down

0 comments on commit 5c46c79

Please sign in to comment.