diff options
| -rw-r--r-- | cloudinit/net/__init__.py | 19 | ||||
| -rw-r--r-- | cloudinit/net/tests/test_init.py | 33 | 
2 files changed, 47 insertions, 5 deletions
| diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 67e3d578..08eaf0a3 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -6,13 +6,14 @@  # This file is part of cloud-init. See LICENSE file for license information.  import errno +import ipaddress  import logging  import os  import re  from functools import partial -from cloudinit.net.network_state import mask_to_net_prefix  from cloudinit import util +from cloudinit.net.network_state import mask_to_net_prefix  from cloudinit.url_helper import UrlError, readurl  LOG = logging.getLogger(__name__) @@ -961,6 +962,22 @@ def has_url_connectivity(url):      return True +def is_ip_address(s: str) -> bool: +    """Returns a bool indicating if ``s`` is an IP address. + +    :param s: +        The string to test. + +    :return: +        A bool indicating if the string contains an IP address or not. +    """ +    try: +        ipaddress.ip_address(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 a965699a..909f43c8 100644 --- a/cloudinit/net/tests/test_init.py +++ b/cloudinit/net/tests/test_init.py @@ -2,16 +2,19 @@  import copy  import errno -import httpretty +import ipaddress  import os -import requests  import textwrap  from unittest import mock +import httpretty +import pytest +import requests +  import cloudinit.net as net -from cloudinit.util import ensure_file, write_file, ProcessExecutionError -from cloudinit.tests.helpers import CiTestCase, HttprettyTestCase  from cloudinit import safeyaml as yaml +from cloudinit.tests.helpers import CiTestCase, HttprettyTestCase +from cloudinit.util import ProcessExecutionError, ensure_file, write_file  class TestSysDevPath(CiTestCase): @@ -1291,4 +1294,26 @@ class TestNetFailOver(CiTestCase):          m_standby.return_value = False          self.assertFalse(net.is_netfailover(devname, driver)) + +class TestIsIpAddress: +    """Tests for net.is_ip_address. + +    Instead of testing with values we rely on the ipaddress stdlib module to +    handle all values correctly, so simply test that is_ip_address defers to +    the ipaddress module correctly. +    """ + +    @pytest.mark.parametrize('ip_address_side_effect,expected_return', ( +        (ValueError, False), +        (lambda _: ipaddress.IPv4Address('192.168.0.1'), True), +        (lambda _: ipaddress.IPv6Address('2001:db8::'), True), +    )) +    def test_is_ip_address(self, ip_address_side_effect, expected_return): +        with mock.patch('cloudinit.net.ipaddress.ip_address', +                        side_effect=ip_address_side_effect) as m_ip_address: +            ret = net.is_ip_address(mock.sentinel.ip_address_in) +        assert expected_return == ret +        expected_call = mock.call(mock.sentinel.ip_address_in) +        assert [expected_call] == m_ip_address.call_args_list +  # vi: ts=4 expandtab | 
