mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Ensure zeroconf uses the newest non-link local address in discovery (#58257)
This commit is contained in:
parent
50e0c58310
commit
5958e6a3f9
@ -469,13 +469,15 @@ def info_from_service(service: AsyncServiceInfo) -> HaServiceInfo | None:
|
||||
if isinstance(value, bytes):
|
||||
properties[key] = value.decode("utf-8")
|
||||
|
||||
if not service.addresses:
|
||||
addresses = service.addresses
|
||||
|
||||
if not addresses:
|
||||
return None
|
||||
if (host := _first_non_link_local_or_v6_address(addresses)) is None:
|
||||
return None
|
||||
|
||||
address = service.addresses[0]
|
||||
|
||||
return {
|
||||
"host": str(ip_address(address)),
|
||||
"host": str(host),
|
||||
"port": service.port,
|
||||
"hostname": service.server,
|
||||
"type": service.type,
|
||||
@ -484,6 +486,15 @@ def info_from_service(service: AsyncServiceInfo) -> HaServiceInfo | None:
|
||||
}
|
||||
|
||||
|
||||
def _first_non_link_local_or_v6_address(addresses: list[bytes]) -> str | None:
|
||||
"""Return the first ipv6 or non-link local ipv4 address."""
|
||||
for address in addresses:
|
||||
ip_addr = ip_address(address)
|
||||
if not ip_addr.is_link_local or ip_addr.version == 6:
|
||||
return str(ip_addr)
|
||||
return None
|
||||
|
||||
|
||||
def _suppress_invalid_properties(properties: dict) -> None:
|
||||
"""Suppress any properties that will cause zeroconf to fail to startup."""
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "zeroconf",
|
||||
"name": "Zero-configuration networking (zeroconf)",
|
||||
"documentation": "https://www.home-assistant.io/integrations/zeroconf",
|
||||
"requirements": ["zeroconf==0.36.8"],
|
||||
"requirements": ["zeroconf==0.36.9"],
|
||||
"dependencies": ["network", "api"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"quality_scale": "internal",
|
||||
|
@ -32,7 +32,7 @@ sqlalchemy==1.4.23
|
||||
voluptuous-serialize==2.4.0
|
||||
voluptuous==0.12.2
|
||||
yarl==1.6.3
|
||||
zeroconf==0.36.8
|
||||
zeroconf==0.36.9
|
||||
|
||||
pycryptodome>=3.6.6
|
||||
|
||||
|
@ -2465,7 +2465,7 @@ youtube_dl==2021.06.06
|
||||
zengge==0.2
|
||||
|
||||
# homeassistant.components.zeroconf
|
||||
zeroconf==0.36.8
|
||||
zeroconf==0.36.9
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.62
|
||||
|
@ -1427,7 +1427,7 @@ yeelight==0.7.8
|
||||
youless-api==0.14
|
||||
|
||||
# homeassistant.components.zeroconf
|
||||
zeroconf==0.36.8
|
||||
zeroconf==0.36.9
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.62
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Test Zeroconf component setup process."""
|
||||
from ipaddress import ip_address
|
||||
from typing import Any
|
||||
from unittest.mock import call, patch
|
||||
|
||||
from zeroconf import InterfaceChoice, IPVersion, ServiceStateChange
|
||||
@ -39,7 +40,9 @@ def service_update_mock(ipv6, zeroconf, services, handlers, *, limit_service=Non
|
||||
handlers[0](zeroconf, service, f"_name.{service}", ServiceStateChange.Added)
|
||||
|
||||
|
||||
def get_service_info_mock(service_type, name, *args, **kwargs):
|
||||
def get_service_info_mock(
|
||||
service_type: str, name: str, *args: Any, **kwargs: Any
|
||||
) -> AsyncServiceInfo:
|
||||
"""Return service info for get_service_info."""
|
||||
return AsyncServiceInfo(
|
||||
service_type,
|
||||
@ -53,7 +56,9 @@ def get_service_info_mock(service_type, name, *args, **kwargs):
|
||||
)
|
||||
|
||||
|
||||
def get_service_info_mock_without_an_address(service_type, name):
|
||||
def get_service_info_mock_without_an_address(
|
||||
service_type: str, name: str
|
||||
) -> AsyncServiceInfo:
|
||||
"""Return service info for get_service_info without any addresses."""
|
||||
return AsyncServiceInfo(
|
||||
service_type,
|
||||
@ -633,6 +638,42 @@ async def test_info_from_service_with_addresses(hass):
|
||||
assert info is None
|
||||
|
||||
|
||||
async def test_info_from_service_with_link_local_address_first(hass):
|
||||
"""Test that the link local address is ignored."""
|
||||
service_type = "_test._tcp.local."
|
||||
service_info = get_service_info_mock(service_type, f"test.{service_type}")
|
||||
service_info.addresses = ["169.254.12.3", "192.168.66.12"]
|
||||
info = zeroconf.info_from_service(service_info)
|
||||
assert info["host"] == "192.168.66.12"
|
||||
|
||||
|
||||
async def test_info_from_service_with_link_local_address_second(hass):
|
||||
"""Test that the link local address is ignored."""
|
||||
service_type = "_test._tcp.local."
|
||||
service_info = get_service_info_mock(service_type, f"test.{service_type}")
|
||||
service_info.addresses = ["192.168.66.12", "169.254.12.3"]
|
||||
info = zeroconf.info_from_service(service_info)
|
||||
assert info["host"] == "192.168.66.12"
|
||||
|
||||
|
||||
async def test_info_from_service_with_link_local_address_only(hass):
|
||||
"""Test that the link local address is ignored."""
|
||||
service_type = "_test._tcp.local."
|
||||
service_info = get_service_info_mock(service_type, f"test.{service_type}")
|
||||
service_info.addresses = ["169.254.12.3"]
|
||||
info = zeroconf.info_from_service(service_info)
|
||||
assert info is None
|
||||
|
||||
|
||||
async def test_info_from_service_prefers_ipv4(hass):
|
||||
"""Test that ipv4 addresses are preferred."""
|
||||
service_type = "_test._tcp.local."
|
||||
service_info = get_service_info_mock(service_type, f"test.{service_type}")
|
||||
service_info.addresses = ["2001:db8:3333:4444:5555:6666:7777:8888", "192.168.66.12"]
|
||||
info = zeroconf.info_from_service(service_info)
|
||||
assert info["host"] == "192.168.66.12"
|
||||
|
||||
|
||||
async def test_get_instance(hass, mock_async_zeroconf):
|
||||
"""Test we get an instance."""
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
|
Loading…
x
Reference in New Issue
Block a user