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 <goran.johansson@shiftit.se> * Apply suggestions from code review Co-authored-by: G Johansson <goran.johansson@shiftit.se> * make default ports the same * test migration from future error * linting * Small tweaks --------- Co-authored-by: G Johansson <goran.johansson@shiftit.se>pull/119912/head^2
parent
9723b97f4b
commit
adcd0cc2a4
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue