diff --git a/homeassistant/components/tailscale/binary_sensor.py b/homeassistant/components/tailscale/binary_sensor.py index 6569b40ada2..65ac69d89c7 100644 --- a/homeassistant/components/tailscale/binary_sensor.py +++ b/homeassistant/components/tailscale/binary_sensor.py @@ -46,37 +46,61 @@ BINARY_SENSORS: tuple[TailscaleBinarySensorEntityDescription, ...] = ( key="client_supports_hair_pinning", translation_key="client_supports_hair_pinning", entity_category=EntityCategory.DIAGNOSTIC, - is_on_fn=lambda device: device.client_connectivity.client_supports.hair_pinning, + is_on_fn=lambda device: ( + device.client_connectivity.client_supports.hair_pinning + if device.client_connectivity is not None + else None + ), ), TailscaleBinarySensorEntityDescription( key="client_supports_ipv6", translation_key="client_supports_ipv6", entity_category=EntityCategory.DIAGNOSTIC, - is_on_fn=lambda device: device.client_connectivity.client_supports.ipv6, + is_on_fn=lambda device: ( + device.client_connectivity.client_supports.ipv6 + if device.client_connectivity is not None + else None + ), ), TailscaleBinarySensorEntityDescription( key="client_supports_pcp", translation_key="client_supports_pcp", entity_category=EntityCategory.DIAGNOSTIC, - is_on_fn=lambda device: device.client_connectivity.client_supports.pcp, + is_on_fn=lambda device: ( + device.client_connectivity.client_supports.pcp + if device.client_connectivity is not None + else None + ), ), TailscaleBinarySensorEntityDescription( key="client_supports_pmp", translation_key="client_supports_pmp", entity_category=EntityCategory.DIAGNOSTIC, - is_on_fn=lambda device: device.client_connectivity.client_supports.pmp, + is_on_fn=lambda device: ( + device.client_connectivity.client_supports.pmp + if device.client_connectivity is not None + else None + ), ), TailscaleBinarySensorEntityDescription( key="client_supports_udp", translation_key="client_supports_udp", entity_category=EntityCategory.DIAGNOSTIC, - is_on_fn=lambda device: device.client_connectivity.client_supports.udp, + is_on_fn=lambda device: ( + device.client_connectivity.client_supports.udp + if device.client_connectivity is not None + else None + ), ), TailscaleBinarySensorEntityDescription( key="client_supports_upnp", translation_key="client_supports_upnp", entity_category=EntityCategory.DIAGNOSTIC, - is_on_fn=lambda device: device.client_connectivity.client_supports.upnp, + is_on_fn=lambda device: ( + device.client_connectivity.client_supports.upnp + if device.client_connectivity is not None + else None + ), ), ) diff --git a/homeassistant/components/tailscale/manifest.json b/homeassistant/components/tailscale/manifest.json index 7d571fe0675..8c005888387 100644 --- a/homeassistant/components/tailscale/manifest.json +++ b/homeassistant/components/tailscale/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/tailscale", "integration_type": "hub", "iot_class": "cloud_polling", - "requirements": ["tailscale==0.6.1"] + "requirements": ["tailscale==0.6.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 8466a231922..e3aa82fa971 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2858,7 +2858,7 @@ systembridgeconnector==4.1.5 systembridgemodels==4.2.4 # homeassistant.components.tailscale -tailscale==0.6.1 +tailscale==0.6.2 # homeassistant.components.tank_utility tank-utility==1.5.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 964ccad34a6..e3e22a2d901 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2314,7 +2314,7 @@ systembridgeconnector==4.1.5 systembridgemodels==4.2.4 # homeassistant.components.tailscale -tailscale==0.6.1 +tailscale==0.6.2 # homeassistant.components.tellduslive tellduslive==0.10.12 diff --git a/tests/components/tailscale/fixtures/devices.json b/tests/components/tailscale/fixtures/devices.json index 66dc262127a..fdfd1d9259a 100644 --- a/tests/components/tailscale/fixtures/devices.json +++ b/tests/components/tailscale/fixtures/devices.json @@ -104,6 +104,28 @@ "upnp": false } } + }, + { + "addresses": ["100.11.11.113"], + "id": "123458", + "user": "frenck", + "name": "host-no-connectivity.homeassistant.github", + "hostname": "host-no-connectivity", + "clientVersion": "1.14.0-t5cff36945-g809e87bba", + "updateAvailable": true, + "os": "linux", + "created": "2021-08-29T09:49:06Z", + "lastSeen": "2021-11-15T20:37:03Z", + "keyExpiryDisabled": false, + "expires": "2022-02-25T09:49:06Z", + "authorized": true, + "isExternal": false, + "machineKey": "mkey:mock", + "nodeKey": "nodekey:mock", + "blocksIncomingConnections": false, + "enabledRoutes": ["0.0.0.0/0", "10.10.10.0/23", "::/0"], + "advertisedRoutes": ["0.0.0.0/0", "10.10.10.0/23", "::/0"], + "clientConnectivity": null } ] } diff --git a/tests/components/tailscale/snapshots/test_diagnostics.ambr b/tests/components/tailscale/snapshots/test_diagnostics.ambr index eba8d9bd145..f3f90c641ea 100644 --- a/tests/components/tailscale/snapshots/test_diagnostics.ambr +++ b/tests/components/tailscale/snapshots/test_diagnostics.ambr @@ -82,6 +82,38 @@ 'update_available': True, 'user': '**REDACTED**', }), + dict({ + 'addresses': '**REDACTED**', + 'advertised_routes': list([ + '0.0.0.0/0', + '10.10.10.0/23', + '::/0', + ]), + 'authorized': True, + 'blocks_incoming_connections': False, + 'client_connectivity': None, + 'client_version': '1.14.0-t5cff36945-g809e87bba', + 'created': '2021-08-29T09:49:06+00:00', + 'device_id': '**REDACTED**', + 'enabled_routes': list([ + '0.0.0.0/0', + '10.10.10.0/23', + '::/0', + ]), + 'expires': '2022-02-25T09:49:06+00:00', + 'hostname': '**REDACTED**', + 'is_external': False, + 'key_expiry_disabled': False, + 'last_seen': '2021-11-15T20:37:03+00:00', + 'machine_key': '**REDACTED**', + 'name': '**REDACTED**', + 'node_key': '**REDACTED**', + 'os': 'linux', + 'tags': list([ + ]), + 'update_available': True, + 'user': '**REDACTED**', + }), ]), }) # --- diff --git a/tests/components/tailscale/test_binary_sensor.py b/tests/components/tailscale/test_binary_sensor.py index b2b593101d7..e0ac97865f0 100644 --- a/tests/components/tailscale/test_binary_sensor.py +++ b/tests/components/tailscale/test_binary_sensor.py @@ -6,7 +6,12 @@ from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, ) from homeassistant.components.tailscale.const import DOMAIN -from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_FRIENDLY_NAME, EntityCategory +from homeassistant.const import ( + ATTR_DEVICE_CLASS, + ATTR_FRIENDLY_NAME, + STATE_UNKNOWN, + EntityCategory, +) from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er @@ -122,3 +127,19 @@ async def test_tailscale_binary_sensors( device_entry.configuration_url == "https://login.tailscale.com/admin/machines/100.11.11.111" ) + + # Check host without client connectivity attribute + state = hass.states.get("binary_sensor.host_no_connectivity_supports_hairpinning") + entry = entity_registry.async_get( + "binary_sensor.host_no_connectivity_supports_hairpinning" + ) + assert entry + assert state + assert entry.unique_id == "123458_client_supports_hair_pinning" + assert entry.entity_category == EntityCategory.DIAGNOSTIC + assert state.state == STATE_UNKNOWN + assert ( + state.attributes.get(ATTR_FRIENDLY_NAME) + == "host-no-connectivity Supports hairpinning" + ) + assert ATTR_DEVICE_CLASS not in state.attributes