Use only IPv4 for zeroconf in bluesound integration (#140226)

* Use only ipv4 for zeroconf

* Fix tests

* Use only ip_address for ip version check

* Add test

* Reduce test
This commit is contained in:
Louis Christ 2025-03-14 10:20:16 +01:00 committed by GitHub
parent 2b0a2e7644
commit d952e8186f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 7 deletions

View File

@ -75,6 +75,9 @@ class BluesoundConfigFlow(ConfigFlow, domain=DOMAIN):
self, discovery_info: ZeroconfServiceInfo self, discovery_info: ZeroconfServiceInfo
) -> ConfigFlowResult: ) -> ConfigFlowResult:
"""Handle a flow initialized by zeroconf discovery.""" """Handle a flow initialized by zeroconf discovery."""
# the player can have an ipv6 address, but the api is only available on ipv4
if discovery_info.ip_address.version != 4:
return self.async_abort(reason="no_ipv4_address")
if discovery_info.port is not None: if discovery_info.port is not None:
self._port = discovery_info.port self._port = discovery_info.port

View File

@ -19,7 +19,8 @@
"abort": { "abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]", "already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]" "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
"no_ipv4_address": "No IPv4 address found."
}, },
"error": { "error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"

View File

@ -1,5 +1,6 @@
"""Test the Bluesound config flow.""" """Test the Bluesound config flow."""
from ipaddress import IPv4Address, IPv6Address
from unittest.mock import AsyncMock from unittest.mock import AsyncMock
from pyblu.errors import PlayerUnreachableError from pyblu.errors import PlayerUnreachableError
@ -121,8 +122,8 @@ async def test_zeroconf_flow_success(
DOMAIN, DOMAIN,
context={"source": SOURCE_ZEROCONF}, context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo( data=ZeroconfServiceInfo(
ip_address="1.1.1.1", ip_address=IPv4Address("1.1.1.1"),
ip_addresses=["1.1.1.1"], ip_addresses=[IPv4Address("1.1.1.1")],
port=11000, port=11000,
hostname="player-name1111", hostname="player-name1111",
type="_musc._tcp.local.", type="_musc._tcp.local.",
@ -160,8 +161,8 @@ async def test_zeroconf_flow_cannot_connect(
DOMAIN, DOMAIN,
context={"source": SOURCE_ZEROCONF}, context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo( data=ZeroconfServiceInfo(
ip_address="1.1.1.1", ip_address=IPv4Address("1.1.1.1"),
ip_addresses=["1.1.1.1"], ip_addresses=[IPv4Address("1.1.1.1")],
port=11000, port=11000,
hostname="player-name1111", hostname="player-name1111",
type="_musc._tcp.local.", type="_musc._tcp.local.",
@ -187,8 +188,8 @@ async def test_zeroconf_flow_already_configured(
DOMAIN, DOMAIN,
context={"source": SOURCE_ZEROCONF}, context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo( data=ZeroconfServiceInfo(
ip_address="1.1.1.2", ip_address=IPv4Address("1.1.1.2"),
ip_addresses=["1.1.1.2"], ip_addresses=[IPv4Address("1.1.1.2")],
port=11000, port=11000,
hostname="player-name1112", hostname="player-name1112",
type="_musc._tcp.local.", type="_musc._tcp.local.",
@ -203,3 +204,23 @@ async def test_zeroconf_flow_already_configured(
assert config_entry.data[CONF_HOST] == "1.1.1.2" assert config_entry.data[CONF_HOST] == "1.1.1.2"
player_mocks.player_data_for_already_configured.player.sync_status.assert_called_once() player_mocks.player_data_for_already_configured.player.sync_status.assert_called_once()
async def test_zeroconf_flow_no_ipv4_address(hass: HomeAssistant) -> None:
"""Test abort flow when no ipv4 address is found in zeroconf data."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
ip_address=IPv6Address("2001:db8::1"),
ip_addresses=[IPv6Address("2001:db8::1")],
port=11000,
hostname="player-name1112",
type="_musc._tcp.local.",
name="player-name._musc._tcp.local.",
properties={},
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "no_ipv4_address"