diff options
| -rw-r--r-- | cloudinit/net/__init__.py | 16 | ||||
| -rw-r--r-- | cloudinit/net/tests/test_init.py | 22 | ||||
| -rw-r--r-- | cloudinit/sources/__init__.py | 2 | ||||
| -rw-r--r-- | cloudinit/util.py | 14 | 
4 files changed, 39 insertions, 15 deletions
| diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 08eaf0a3..cb8c1601 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -978,6 +978,22 @@ def is_ip_address(s: str) -> bool:      return True +def is_ipv4_address(s: str) -> bool: +    """Returns a bool indicating if ``s`` is an IPv4 address. + +    :param s: +        The string to test. + +    :return: +        A bool indicating if the string contains an IPv4 address or not. +    """ +    try: +        ipaddress.IPv4Address(s) +    except ValueError: +        return False +    return True + +  class EphemeralIPv4Network(object):      """Context manager which sets up temporary static network configuration. diff --git a/cloudinit/net/tests/test_init.py b/cloudinit/net/tests/test_init.py index 909f43c8..32e70b4c 100644 --- a/cloudinit/net/tests/test_init.py +++ b/cloudinit/net/tests/test_init.py @@ -1316,4 +1316,26 @@ class TestIsIpAddress:          expected_call = mock.call(mock.sentinel.ip_address_in)          assert [expected_call] == m_ip_address.call_args_list + +class TestIsIpv4Address: +    """Tests for net.is_ipv4_address. + +    Instead of testing with values we rely on the ipaddress stdlib module to +    handle all values correctly, so simply test that is_ipv4_address defers to +    the ipaddress module correctly. +    """ + +    @pytest.mark.parametrize('ipv4address_mock,expected_return', ( +        (mock.Mock(side_effect=ValueError), False), +        (mock.Mock(return_value=ipaddress.IPv4Address('192.168.0.1')), True), +    )) +    def test_is_ip_address(self, ipv4address_mock, expected_return): +        with mock.patch('cloudinit.net.ipaddress.IPv4Address', +                        ipv4address_mock) as m_ipv4address: +            ret = net.is_ipv4_address(mock.sentinel.ip_address_in) +        assert expected_return == ret +        expected_call = mock.call(mock.sentinel.ip_address_in) +        assert [expected_call] == m_ipv4address.call_args_list + +  # vi: ts=4 expandtab diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py index a6e6d202..923e3cea 100644 --- a/cloudinit/sources/__init__.py +++ b/cloudinit/sources/__init__.py @@ -602,7 +602,7 @@ class DataSource(metaclass=abc.ABCMeta):              # if there is an ipv4 address in 'local-hostname', then              # make up a hostname (LP: #475354) in format ip-xx.xx.xx.xx              lhost = self.metadata['local-hostname'] -            if util.is_ipv4(lhost): +            if net.is_ipv4_address(lhost):                  toks = []                  if resolve_ip:                      toks = util.gethostbyaddr(lhost) diff --git a/cloudinit/util.py b/cloudinit/util.py index 541a486b..f8e28d2d 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -528,20 +528,6 @@ def multi_log(text, console=True, stderr=True,              log.log(log_level, text) -def is_ipv4(instr): -    """determine if input string is a ipv4 address. return boolean.""" -    toks = instr.split('.') -    if len(toks) != 4: -        return False - -    try: -        toks = [x for x in toks if 0 <= int(x) < 256] -    except Exception: -        return False - -    return len(toks) == 4 - -  @lru_cache()  def is_BSD():      return 'BSD' in platform.system() | 
