From 2859055b36c05c93098e39ad47a511db4d2c0c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Tue, 7 Nov 2023 23:52:18 +0100 Subject: [PATCH] Add instance id to the cloud integration (#103162) --- homeassistant/components/cloud/client.py | 1 + homeassistant/components/cloud/const.py | 1 + homeassistant/components/cloud/prefs.py | 15 +++++++++++++++ homeassistant/components/cloud/strings.json | 1 + homeassistant/components/cloud/system_health.py | 1 + tests/components/cloud/test_client.py | 8 ++++++-- tests/components/cloud/test_system_health.py | 2 ++ 7 files changed, 27 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/cloud/client.py b/homeassistant/components/cloud/client.py index 41ea4aa2b7d..019936869a1 100644 --- a/homeassistant/components/cloud/client.py +++ b/homeassistant/components/cloud/client.py @@ -230,6 +230,7 @@ class CloudClient(Interface): "alias": self.cloud.remote.alias, }, "version": HA_VERSION, + "instance_id": self.prefs.instance_id, } async def async_alexa_message(self, payload: dict[Any, Any]) -> dict[Any, Any]: diff --git a/homeassistant/components/cloud/const.py b/homeassistant/components/cloud/const.py index bd9d61cde16..6e20978ec8d 100644 --- a/homeassistant/components/cloud/const.py +++ b/homeassistant/components/cloud/const.py @@ -13,6 +13,7 @@ PREF_GOOGLE_REPORT_STATE = "google_report_state" PREF_ALEXA_ENTITY_CONFIGS = "alexa_entity_configs" PREF_ALEXA_REPORT_STATE = "alexa_report_state" PREF_DISABLE_2FA = "disable_2fa" +PREF_INSTANCE_ID = "instance_id" PREF_SHOULD_EXPOSE = "should_expose" PREF_GOOGLE_LOCAL_WEBHOOK_ID = "google_local_webhook_id" PREF_USERNAME = "username" diff --git a/homeassistant/components/cloud/prefs.py b/homeassistant/components/cloud/prefs.py index 57179431574..4cc02867347 100644 --- a/homeassistant/components/cloud/prefs.py +++ b/homeassistant/components/cloud/prefs.py @@ -3,6 +3,7 @@ from __future__ import annotations from collections.abc import Callable, Coroutine from typing import Any +import uuid from homeassistant.auth.const import GROUP_ID_ADMIN from homeassistant.auth.models import User @@ -33,6 +34,7 @@ from .const import ( PREF_GOOGLE_REPORT_STATE, PREF_GOOGLE_SECURE_DEVICES_PIN, PREF_GOOGLE_SETTINGS_VERSION, + PREF_INSTANCE_ID, PREF_REMOTE_DOMAIN, PREF_TTS_DEFAULT_VOICE, PREF_USERNAME, @@ -91,6 +93,13 @@ class CloudPreferences: PREF_GOOGLE_LOCAL_WEBHOOK_ID: webhook.async_generate_id(), } ) + if PREF_INSTANCE_ID not in self._prefs: + await self._save_prefs( + { + **self._prefs, + PREF_INSTANCE_ID: uuid.uuid4().hex, + } + ) @callback def async_listen_updates( @@ -264,6 +273,11 @@ class CloudPreferences: """Return the published cloud webhooks.""" return self._prefs.get(PREF_CLOUDHOOKS, {}) # type: ignore[no-any-return] + @property + def instance_id(self) -> str | None: + """Return the instance ID.""" + return self._prefs.get(PREF_INSTANCE_ID) + @property def tts_default_voice(self) -> tuple[str, str]: """Return the default TTS voice.""" @@ -320,6 +334,7 @@ class CloudPreferences: PREF_GOOGLE_ENTITY_CONFIGS: {}, PREF_GOOGLE_SETTINGS_VERSION: GOOGLE_SETTINGS_VERSION, PREF_GOOGLE_LOCAL_WEBHOOK_ID: webhook.async_generate_id(), + PREF_INSTANCE_ID: uuid.uuid4().hex, PREF_GOOGLE_SECURE_DEVICES_PIN: None, PREF_REMOTE_DOMAIN: None, PREF_USERNAME: username, diff --git a/homeassistant/components/cloud/strings.json b/homeassistant/components/cloud/strings.json index aba2e770bc9..9c1f29cfcaf 100644 --- a/homeassistant/components/cloud/strings.json +++ b/homeassistant/components/cloud/strings.json @@ -13,6 +13,7 @@ "alexa_enabled": "Alexa Enabled", "google_enabled": "Google Enabled", "logged_in": "Logged In", + "instance_id": "Instance ID", "subscription_expiration": "Subscription Expiration" } }, diff --git a/homeassistant/components/cloud/system_health.py b/homeassistant/components/cloud/system_health.py index 0dfd69344f3..d149e13c996 100644 --- a/homeassistant/components/cloud/system_health.py +++ b/homeassistant/components/cloud/system_health.py @@ -37,6 +37,7 @@ async def system_health_info(hass: HomeAssistant) -> dict[str, Any]: data["google_enabled"] = client.prefs.google_enabled data["remote_server"] = cloud.remote.snitun_server data["certificate_status"] = cloud.remote.certificate_status + data["instance_id"] = client.prefs.instance_id data["can_reach_cert_server"] = system_health.async_check_can_reach_url( hass, f"https://{cloud.acme_server}/directory" diff --git a/tests/components/cloud/test_client.py b/tests/components/cloud/test_client.py index e205ba5f6e8..63ec6ad569d 100644 --- a/tests/components/cloud/test_client.py +++ b/tests/components/cloud/test_client.py @@ -1,6 +1,6 @@ """Test the cloud.iot module.""" from datetime import timedelta -from unittest.mock import AsyncMock, MagicMock, Mock, patch +from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, patch import aiohttp from aiohttp import web @@ -357,7 +357,10 @@ async def test_system_msg(hass: HomeAssistant) -> None: async def test_cloud_connection_info(hass: HomeAssistant) -> None: """Test connection info msg.""" - with patch("hass_nabucasa.Cloud.initialize"): + with patch("hass_nabucasa.Cloud.initialize"), patch( + "uuid.UUID.hex", new_callable=PropertyMock + ) as hexmock: + hexmock.return_value = "12345678901234567890" setup = await async_setup_component(hass, "cloud", {"cloud": {}}) assert setup cloud = hass.data["cloud"] @@ -372,4 +375,5 @@ async def test_cloud_connection_info(hass: HomeAssistant) -> None: "alias": None, }, "version": HA_VERSION, + "instance_id": "12345678901234567890", } diff --git a/tests/components/cloud/test_system_health.py b/tests/components/cloud/test_system_health.py index 79e45e9ba26..c540394b937 100644 --- a/tests/components/cloud/test_system_health.py +++ b/tests/components/cloud/test_system_health.py @@ -46,6 +46,7 @@ async def test_cloud_system_health( remote_enabled=True, alexa_enabled=True, google_enabled=False, + instance_id="12345678901234567890", ), ), ) @@ -70,4 +71,5 @@ async def test_cloud_system_health( "can_reach_cert_server": "ok", "can_reach_cloud_auth": {"type": "failed", "error": "unreachable"}, "can_reach_cloud": "ok", + "instance_id": "12345678901234567890", }