From adcd0cc2a40d7662fde1bde3286d6a3de7e407cf Mon Sep 17 00:00:00 2001 From: HarvsG <11440490+HarvsG@users.noreply.github.com> Date: Tue, 18 Jun 2024 21:24:36 +0100 Subject: [PATCH] DNS IP custom ports for IPv4 (#113993) * squash DNS IP enable port * linting * fix config entries in tests. * fix more config entries * fix parameter order * Add defaults for legacy config entries * test legacy config are not broken * test driven migration * define versions for future proofing * remove defaults as should be covered by migrations in the future * adds config migration * spacing * Review: remove unnecessary statements Co-authored-by: G Johansson * Apply suggestions from code review Co-authored-by: G Johansson * make default ports the same * test migration from future error * linting * Small tweaks --------- Co-authored-by: G Johansson --- homeassistant/components/dnsip/__init__.py | 38 ++++++++- homeassistant/components/dnsip/config_flow.py | 47 ++++++++--- homeassistant/components/dnsip/const.py | 2 + homeassistant/components/dnsip/sensor.py | 12 ++- homeassistant/components/dnsip/strings.json | 10 ++- tests/components/dnsip/test_config_flow.py | 29 ++++++- tests/components/dnsip/test_init.py | 80 ++++++++++++++++++- tests/components/dnsip/test_sensor.py | 50 +++++++++++- 8 files changed, 246 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/dnsip/__init__.py b/homeassistant/components/dnsip/__init__.py index 78309b5f2bf..37e0f60849f 100644 --- a/homeassistant/components/dnsip/__init__.py +++ b/homeassistant/components/dnsip/__init__.py @@ -3,9 +3,10 @@ from __future__ import annotations from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant +from homeassistant.const import CONF_PORT +from homeassistant.core import _LOGGER, HomeAssistant -from .const import PLATFORMS +from .const import CONF_PORT_IPV6, DEFAULT_PORT, PLATFORMS async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -25,3 +26,36 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload dnsip config entry.""" return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) + + +async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: + """Migrate old entry to a newer version.""" + + if config_entry.version > 1: + # This means the user has downgraded from a future version + return False + + if config_entry.version < 2 and config_entry.minor_version < 2: + version = config_entry.version + minor_version = config_entry.minor_version + _LOGGER.debug( + "Migrating configuration from version %s.%s", + version, + minor_version, + ) + + new_options = {**config_entry.options} + new_options[CONF_PORT] = DEFAULT_PORT + new_options[CONF_PORT_IPV6] = DEFAULT_PORT + + hass.config_entries.async_update_entry( + config_entry, options=new_options, minor_version=2 + ) + + _LOGGER.debug( + "Migration to configuration version %s.%s successful", + 1, + 2, + ) + + return True diff --git a/homeassistant/components/dnsip/config_flow.py b/homeassistant/components/dnsip/config_flow.py index 21a29465050..6dda0c03910 100644 --- a/homeassistant/components/dnsip/config_flow.py +++ b/homeassistant/components/dnsip/config_flow.py @@ -16,7 +16,7 @@ from homeassistant.config_entries import ( ConfigFlowResult, OptionsFlowWithConfigEntry, ) -from homeassistant.const import CONF_NAME +from homeassistant.const import CONF_NAME, CONF_PORT from homeassistant.core import callback import homeassistant.helpers.config_validation as cv @@ -25,10 +25,12 @@ from .const import ( CONF_IPV4, CONF_IPV6, CONF_IPV6_V4, + CONF_PORT_IPV6, CONF_RESOLVER, CONF_RESOLVER_IPV6, DEFAULT_HOSTNAME, DEFAULT_NAME, + DEFAULT_PORT, DEFAULT_RESOLVER, DEFAULT_RESOLVER_IPV6, DOMAIN, @@ -42,32 +44,42 @@ DATA_SCHEMA = vol.Schema( DATA_SCHEMA_ADV = vol.Schema( { vol.Required(CONF_HOSTNAME, default=DEFAULT_HOSTNAME): cv.string, - vol.Optional(CONF_RESOLVER, default=DEFAULT_RESOLVER): cv.string, - vol.Optional(CONF_RESOLVER_IPV6, default=DEFAULT_RESOLVER_IPV6): cv.string, + vol.Optional(CONF_RESOLVER): cv.string, + vol.Optional(CONF_PORT): cv.port, + vol.Optional(CONF_RESOLVER_IPV6): cv.string, + vol.Optional(CONF_PORT_IPV6): cv.port, } ) async def async_validate_hostname( - hostname: str, resolver_ipv4: str, resolver_ipv6: str + hostname: str, + resolver_ipv4: str, + resolver_ipv6: str, + port: int, + port_ipv6: int, ) -> dict[str, bool]: """Validate hostname.""" - async def async_check(hostname: str, resolver: str, qtype: str) -> bool: + async def async_check( + hostname: str, resolver: str, qtype: str, port: int = 53 + ) -> bool: """Return if able to resolve hostname.""" result = False with contextlib.suppress(DNSError): result = bool( - await aiodns.DNSResolver(nameservers=[resolver]).query(hostname, qtype) + await aiodns.DNSResolver( + nameservers=[resolver], udp_port=port, tcp_port=port + ).query(hostname, qtype) ) return result result: dict[str, bool] = {} tasks = await asyncio.gather( - async_check(hostname, resolver_ipv4, "A"), - async_check(hostname, resolver_ipv6, "AAAA"), - async_check(hostname, resolver_ipv4, "AAAA"), + async_check(hostname, resolver_ipv4, "A", port=port), + async_check(hostname, resolver_ipv6, "AAAA", port=port_ipv6), + async_check(hostname, resolver_ipv4, "AAAA", port=port), ) result[CONF_IPV4] = tasks[0] @@ -81,6 +93,7 @@ class DnsIPConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for dnsip integration.""" VERSION = 1 + MINOR_VERSION = 2 @staticmethod @callback @@ -102,8 +115,12 @@ class DnsIPConfigFlow(ConfigFlow, domain=DOMAIN): name = DEFAULT_NAME if hostname == DEFAULT_HOSTNAME else hostname resolver = user_input.get(CONF_RESOLVER, DEFAULT_RESOLVER) resolver_ipv6 = user_input.get(CONF_RESOLVER_IPV6, DEFAULT_RESOLVER_IPV6) + port = user_input.get(CONF_PORT, DEFAULT_PORT) + port_ipv6 = user_input.get(CONF_PORT_IPV6, DEFAULT_PORT) - validate = await async_validate_hostname(hostname, resolver, resolver_ipv6) + validate = await async_validate_hostname( + hostname, resolver, resolver_ipv6, port, port_ipv6 + ) set_resolver = resolver if validate[CONF_IPV6]: @@ -129,7 +146,9 @@ class DnsIPConfigFlow(ConfigFlow, domain=DOMAIN): }, options={ CONF_RESOLVER: resolver, + CONF_PORT: port, CONF_RESOLVER_IPV6: set_resolver, + CONF_PORT_IPV6: port_ipv6, }, ) @@ -156,11 +175,15 @@ class DnsIPOptionsFlowHandler(OptionsFlowWithConfigEntry): errors = {} if user_input is not None: resolver = user_input.get(CONF_RESOLVER, DEFAULT_RESOLVER) + port = user_input.get(CONF_PORT, DEFAULT_PORT) resolver_ipv6 = user_input.get(CONF_RESOLVER_IPV6, DEFAULT_RESOLVER_IPV6) + port_ipv6 = user_input.get(CONF_PORT_IPV6, DEFAULT_PORT) validate = await async_validate_hostname( self.config_entry.data[CONF_HOSTNAME], resolver, resolver_ipv6, + port, + port_ipv6, ) if ( @@ -178,7 +201,9 @@ class DnsIPOptionsFlowHandler(OptionsFlowWithConfigEntry): title=self.config_entry.title, data={ CONF_RESOLVER: resolver, + CONF_PORT: port, CONF_RESOLVER_IPV6: resolver_ipv6, + CONF_PORT_IPV6: port_ipv6, }, ) @@ -186,7 +211,9 @@ class DnsIPOptionsFlowHandler(OptionsFlowWithConfigEntry): vol.Schema( { vol.Optional(CONF_RESOLVER): cv.string, + vol.Optional(CONF_PORT): cv.port, vol.Optional(CONF_RESOLVER_IPV6): cv.string, + vol.Optional(CONF_PORT_IPV6): cv.port, } ), self.config_entry.options, diff --git a/homeassistant/components/dnsip/const.py b/homeassistant/components/dnsip/const.py index 41116bde61a..2e81099df34 100644 --- a/homeassistant/components/dnsip/const.py +++ b/homeassistant/components/dnsip/const.py @@ -8,6 +8,7 @@ PLATFORMS = [Platform.SENSOR] CONF_HOSTNAME = "hostname" CONF_RESOLVER = "resolver" CONF_RESOLVER_IPV6 = "resolver_ipv6" +CONF_PORT_IPV6 = "port_ipv6" CONF_IPV4 = "ipv4" CONF_IPV6 = "ipv6" CONF_IPV6_V4 = "ipv6_v4" @@ -16,4 +17,5 @@ DEFAULT_HOSTNAME = "myip.opendns.com" DEFAULT_IPV6 = False DEFAULT_NAME = "myip" DEFAULT_RESOLVER = "208.67.222.222" +DEFAULT_PORT = 53 DEFAULT_RESOLVER_IPV6 = "2620:119:53::53" diff --git a/homeassistant/components/dnsip/sensor.py b/homeassistant/components/dnsip/sensor.py index d3527bda3f2..726198e14cc 100644 --- a/homeassistant/components/dnsip/sensor.py +++ b/homeassistant/components/dnsip/sensor.py @@ -11,7 +11,7 @@ from aiodns.error import DNSError from homeassistant.components.sensor import SensorEntity from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_NAME +from homeassistant.const import CONF_NAME, CONF_PORT from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -20,6 +20,7 @@ from .const import ( CONF_HOSTNAME, CONF_IPV4, CONF_IPV6, + CONF_PORT_IPV6, CONF_RESOLVER, CONF_RESOLVER_IPV6, DOMAIN, @@ -53,12 +54,14 @@ async def async_setup_entry( resolver_ipv4 = entry.options[CONF_RESOLVER] resolver_ipv6 = entry.options[CONF_RESOLVER_IPV6] + port_ipv4 = entry.options[CONF_PORT] + port_ipv6 = entry.options[CONF_PORT_IPV6] entities = [] if entry.data[CONF_IPV4]: - entities.append(WanIpSensor(name, hostname, resolver_ipv4, False)) + entities.append(WanIpSensor(name, hostname, resolver_ipv4, False, port_ipv4)) if entry.data[CONF_IPV6]: - entities.append(WanIpSensor(name, hostname, resolver_ipv6, True)) + entities.append(WanIpSensor(name, hostname, resolver_ipv6, True, port_ipv6)) async_add_entities(entities, update_before_add=True) @@ -75,12 +78,13 @@ class WanIpSensor(SensorEntity): hostname: str, resolver: str, ipv6: bool, + port: int, ) -> None: """Initialize the DNS IP sensor.""" self._attr_name = "IPv6" if ipv6 else None self._attr_unique_id = f"{hostname}_{ipv6}" self.hostname = hostname - self.resolver = aiodns.DNSResolver() + self.resolver = aiodns.DNSResolver(tcp_port=port, udp_port=port) self.resolver.nameservers = [resolver] self.querytype = "AAAA" if ipv6 else "A" self._retries = DEFAULT_RETRIES diff --git a/homeassistant/components/dnsip/strings.json b/homeassistant/components/dnsip/strings.json index d402e27287c..d8258a65d6a 100644 --- a/homeassistant/components/dnsip/strings.json +++ b/homeassistant/components/dnsip/strings.json @@ -5,7 +5,9 @@ "data": { "hostname": "The hostname for which to perform the DNS query", "resolver": "Resolver for IPV4 lookup", - "resolver_ipv6": "Resolver for IPV6 lookup" + "port": "Port for IPV4 lookup", + "resolver_ipv6": "Resolver for IPV6 lookup", + "port_ipv6": "Port for IPV6 lookup" } } }, @@ -18,7 +20,9 @@ "init": { "data": { "resolver": "[%key:component::dnsip::config::step::user::data::resolver%]", - "resolver_ipv6": "[%key:component::dnsip::config::step::user::data::resolver_ipv6%]" + "port": "[%key:component::dnsip::config::step::user::data::port%]", + "resolver_ipv6": "[%key:component::dnsip::config::step::user::data::resolver_ipv6%]", + "port_ipv6": "[%key:component::dnsip::config::step::user::data::port_ipv6%]" } } }, @@ -26,7 +30,7 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_service%]" }, "error": { - "invalid_resolver": "Invalid IP address for resolver" + "invalid_resolver": "Invalid IP address or port for resolver" } } } diff --git a/tests/components/dnsip/test_config_flow.py b/tests/components/dnsip/test_config_flow.py index ff089be0e1e..99dc5781d16 100644 --- a/tests/components/dnsip/test_config_flow.py +++ b/tests/components/dnsip/test_config_flow.py @@ -13,12 +13,13 @@ from homeassistant.components.dnsip.const import ( CONF_HOSTNAME, CONF_IPV4, CONF_IPV6, + CONF_PORT_IPV6, CONF_RESOLVER, CONF_RESOLVER_IPV6, DOMAIN, ) from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import CONF_NAME +from homeassistant.const import CONF_NAME, CONF_PORT from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType @@ -66,6 +67,8 @@ async def test_form(hass: HomeAssistant) -> None: assert result2["options"] == { "resolver": "208.67.222.222", "resolver_ipv6": "2620:119:53::53", + "port": 53, + "port_ipv6": 53, } assert len(mock_setup_entry.mock_calls) == 1 @@ -96,6 +99,8 @@ async def test_form_adv(hass: HomeAssistant) -> None: CONF_HOSTNAME: "home-assistant.io", CONF_RESOLVER: "8.8.8.8", CONF_RESOLVER_IPV6: "2620:119:53::53", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, ) await hass.async_block_till_done() @@ -111,6 +116,8 @@ async def test_form_adv(hass: HomeAssistant) -> None: assert result2["options"] == { "resolver": "8.8.8.8", "resolver_ipv6": "2620:119:53::53", + "port": 53, + "port_ipv6": 53, } assert len(mock_setup_entry.mock_calls) == 1 @@ -152,6 +159,8 @@ async def test_flow_already_exist(hass: HomeAssistant) -> None: options={ CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::5", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, unique_id="home-assistant.io", ).add_to_hass(hass) @@ -197,6 +206,8 @@ async def test_options_flow(hass: HomeAssistant) -> None: options={ CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::5", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, ) entry.add_to_hass(hass) @@ -218,6 +229,8 @@ async def test_options_flow(hass: HomeAssistant) -> None: user_input={ CONF_RESOLVER: "8.8.8.8", CONF_RESOLVER_IPV6: "2001:4860:4860::8888", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, ) await hass.async_block_till_done() @@ -226,6 +239,8 @@ async def test_options_flow(hass: HomeAssistant) -> None: assert result["data"] == { "resolver": "8.8.8.8", "resolver_ipv6": "2001:4860:4860::8888", + "port": 53, + "port_ipv6": 53, } assert entry.state is ConfigEntryState.LOADED @@ -245,6 +260,8 @@ async def test_options_flow_empty_return(hass: HomeAssistant) -> None: options={ CONF_RESOLVER: "8.8.8.8", CONF_RESOLVER_IPV6: "2620:119:53::1", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, ) entry.add_to_hass(hass) @@ -271,6 +288,8 @@ async def test_options_flow_empty_return(hass: HomeAssistant) -> None: assert result["data"] == { "resolver": "208.67.222.222", "resolver_ipv6": "2620:119:53::53", + "port": 53, + "port_ipv6": 53, } entry = hass.config_entries.async_get_entry(entry.entry_id) @@ -283,6 +302,8 @@ async def test_options_flow_empty_return(hass: HomeAssistant) -> None: assert entry.options == { "resolver": "208.67.222.222", "resolver_ipv6": "2620:119:53::53", + "port": 53, + "port_ipv6": 53, } @@ -294,6 +315,8 @@ async def test_options_flow_empty_return(hass: HomeAssistant) -> None: CONF_NAME: "home-assistant.io", CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::5", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, CONF_IPV4: True, CONF_IPV6: False, }, @@ -302,6 +325,8 @@ async def test_options_flow_empty_return(hass: HomeAssistant) -> None: CONF_NAME: "home-assistant.io", CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::5", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, CONF_IPV4: False, CONF_IPV6: True, }, @@ -334,6 +359,8 @@ async def test_options_error(hass: HomeAssistant, p_input: dict[str, str]) -> No { CONF_RESOLVER: "192.168.200.34", CONF_RESOLVER_IPV6: "2001:4860:4860::8888", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, ) await hass.async_block_till_done() diff --git a/tests/components/dnsip/test_init.py b/tests/components/dnsip/test_init.py index 3d816bebe60..ac5da227bde 100644 --- a/tests/components/dnsip/test_init.py +++ b/tests/components/dnsip/test_init.py @@ -8,12 +8,14 @@ from homeassistant.components.dnsip.const import ( CONF_HOSTNAME, CONF_IPV4, CONF_IPV6, + CONF_PORT_IPV6, CONF_RESOLVER, CONF_RESOLVER_IPV6, + DEFAULT_PORT, DOMAIN, ) from homeassistant.config_entries import SOURCE_USER, ConfigEntryState -from homeassistant.const import CONF_NAME +from homeassistant.const import CONF_NAME, CONF_PORT from homeassistant.core import HomeAssistant from . import RetrieveDNS @@ -35,6 +37,8 @@ async def test_load_unload_entry(hass: HomeAssistant) -> None: options={ CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::53", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, entry_id="1", unique_id="home-assistant.io", @@ -52,3 +56,77 @@ async def test_load_unload_entry(hass: HomeAssistant) -> None: assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.NOT_LOADED + + +async def test_port_migration( + hass: HomeAssistant, +) -> None: + """Test migration of the config entry from no ports to with ports.""" + + entry = MockConfigEntry( + domain=DOMAIN, + source=SOURCE_USER, + data={ + CONF_HOSTNAME: "home-assistant.io", + CONF_NAME: "home-assistant.io", + CONF_IPV4: True, + CONF_IPV6: True, + }, + options={ + CONF_RESOLVER: "208.67.222.222", + CONF_RESOLVER_IPV6: "2620:119:53::53", + }, + entry_id="1", + unique_id="home-assistant.io", + version=1, + minor_version=1, + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.dnsip.sensor.aiodns.DNSResolver", + return_value=RetrieveDNS(), + ): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.version == 1 + assert entry.minor_version == 2 + assert entry.options[CONF_PORT] == DEFAULT_PORT + assert entry.options[CONF_PORT_IPV6] == DEFAULT_PORT + assert entry.state is ConfigEntryState.LOADED + + +async def test_migrate_error_from_future(hass: HomeAssistant) -> None: + """Test a future version isn't migrated.""" + + entry = MockConfigEntry( + domain=DOMAIN, + source=SOURCE_USER, + data={ + CONF_HOSTNAME: "home-assistant.io", + CONF_NAME: "home-assistant.io", + CONF_IPV4: True, + CONF_IPV6: True, + "some_new_data": "new_value", + }, + options={ + CONF_RESOLVER: "208.67.222.222", + CONF_RESOLVER_IPV6: "2620:119:53::53", + }, + entry_id="1", + unique_id="home-assistant.io", + version=2, + minor_version=1, + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.dnsip.sensor.aiodns.DNSResolver", + return_value=RetrieveDNS(), + ): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + entry = hass.config_entries.async_get_entry(entry.entry_id) + assert entry.state is ConfigEntryState.MIGRATION_ERROR diff --git a/tests/components/dnsip/test_sensor.py b/tests/components/dnsip/test_sensor.py index 0a81804a689..66cb5cc6ad9 100644 --- a/tests/components/dnsip/test_sensor.py +++ b/tests/components/dnsip/test_sensor.py @@ -12,13 +12,14 @@ from homeassistant.components.dnsip.const import ( CONF_HOSTNAME, CONF_IPV4, CONF_IPV6, + CONF_PORT_IPV6, CONF_RESOLVER, CONF_RESOLVER_IPV6, DOMAIN, ) from homeassistant.components.dnsip.sensor import SCAN_INTERVAL from homeassistant.config_entries import SOURCE_USER -from homeassistant.const import CONF_NAME, STATE_UNAVAILABLE +from homeassistant.const import CONF_NAME, CONF_PORT, STATE_UNAVAILABLE from homeassistant.core import HomeAssistant from . import RetrieveDNS @@ -40,6 +41,8 @@ async def test_sensor(hass: HomeAssistant) -> None: options={ CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::53", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, entry_id="1", unique_id="home-assistant.io", @@ -67,6 +70,49 @@ async def test_sensor(hass: HomeAssistant) -> None: ] +async def test_legacy_sensor(hass: HomeAssistant) -> None: + """Test the DNS IP sensor configured before the addition of ports.""" + entry = MockConfigEntry( + domain=DOMAIN, + source=SOURCE_USER, + data={ + CONF_HOSTNAME: "home-assistant.io", + CONF_NAME: "home-assistant.io", + CONF_IPV4: True, + CONF_IPV6: True, + }, + options={ + CONF_RESOLVER: "208.67.222.222", + CONF_RESOLVER_IPV6: "2620:119:53::53", + }, + entry_id="1", + unique_id="home-assistant.io", + version=1, + minor_version=1, + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.dnsip.sensor.aiodns.DNSResolver", + return_value=RetrieveDNS(), + ): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + state1 = hass.states.get("sensor.home_assistant_io") + state2 = hass.states.get("sensor.home_assistant_io_ipv6") + + assert state1.state == "1.1.1.1" + assert state1.attributes["ip_addresses"] == ["1.1.1.1", "1.2.3.4"] + assert state2.state == "2001:db8::77:dead:beef" + assert state2.attributes["ip_addresses"] == [ + "2001:db8::77:dead:beef", + "2001:db8:66::dead:beef", + "2001:db8:77::dead:beef", + "2001:db8:77::face:b00c", + ] + + async def test_sensor_no_response( hass: HomeAssistant, freezer: FrozenDateTimeFactory ) -> None: @@ -83,6 +129,8 @@ async def test_sensor_no_response( options={ CONF_RESOLVER: "208.67.222.222", CONF_RESOLVER_IPV6: "2620:119:53::53", + CONF_PORT: 53, + CONF_PORT_IPV6: 53, }, entry_id="1", unique_id="home-assistant.io",