Check for EA release channel for UniFi Protect (#113432)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Christopher Bailey 2024-03-14 15:07:54 -04:00 committed by GitHub
parent 5512e8b789
commit 1ada10299a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 28 additions and 21 deletions

View File

@ -7,6 +7,7 @@ import logging
from aiohttp.client_exceptions import ServerDisconnectedError from aiohttp.client_exceptions import ServerDisconnectedError
from pyunifiprotect.data import Bootstrap from pyunifiprotect.data import Bootstrap
from pyunifiprotect.data.types import FirmwareReleaseChannel
from pyunifiprotect.exceptions import ClientError, NotAuthorized from pyunifiprotect.exceptions import ClientError, NotAuthorized
# Import the test_util.anonymize module from the pyunifiprotect package # Import the test_util.anonymize module from the pyunifiprotect package
@ -112,19 +113,19 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, data_service.async_stop) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, data_service.async_stop)
) )
if ( if not entry.options.get(CONF_ALLOW_EA, False) and (
not entry.options.get(CONF_ALLOW_EA, False) await nvr_info.get_is_prerelease()
and await nvr_info.get_is_prerelease() or nvr_info.release_channel != FirmwareReleaseChannel.RELEASE
): ):
ir.async_create_issue( ir.async_create_issue(
hass, hass,
DOMAIN, DOMAIN,
"ea_warning", "ea_channel_warning",
is_fixable=True, is_fixable=True,
is_persistent=True, is_persistent=True,
learn_more_url="https://www.home-assistant.io/integrations/unifiprotect#about-unifi-early-access", learn_more_url="https://www.home-assistant.io/integrations/unifiprotect#about-unifi-early-access",
severity=IssueSeverity.WARNING, severity=IssueSeverity.WARNING,
translation_key="ea_warning", translation_key="ea_channel_warning",
translation_placeholders={"version": str(nvr_info.version)}, translation_placeholders={"version": str(nvr_info.version)},
data={"entry_id": entry.entry_id}, data={"entry_id": entry.entry_id},
) )
@ -150,7 +151,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"version": str(nvr_info.version), "version": str(nvr_info.version),
}, },
) )
ir.async_delete_issue(hass, DOMAIN, "ea_warning") ir.async_delete_issue(hass, DOMAIN, "ea_channel_warning")
_LOGGER.exception("Error setting up UniFi Protect integration: %s", err) _LOGGER.exception("Error setting up UniFi Protect integration: %s", err)
raise raise

View File

@ -24,7 +24,7 @@ CONF_DISABLE_RTSP = "disable_rtsp"
CONF_ALL_UPDATES = "all_updates" CONF_ALL_UPDATES = "all_updates"
CONF_OVERRIDE_CHOST = "override_connection_host" CONF_OVERRIDE_CHOST = "override_connection_host"
CONF_MAX_MEDIA = "max_media" CONF_MAX_MEDIA = "max_media"
CONF_ALLOW_EA = "allow_ea" CONF_ALLOW_EA = "allow_ea_channel"
CONFIG_OPTIONS = [ CONFIG_OPTIONS = [
CONF_ALL_UPDATES, CONF_ALL_UPDATES,

View File

@ -6,6 +6,7 @@ import logging
from typing import cast from typing import cast
from pyunifiprotect import ProtectApiClient from pyunifiprotect import ProtectApiClient
from pyunifiprotect.data.types import FirmwareReleaseChannel
import voluptuous as vol import voluptuous as vol
from homeassistant import data_entry_flow from homeassistant import data_entry_flow
@ -68,7 +69,7 @@ class EAConfirm(ProtectRepair):
) )
nvr = await self._api.get_nvr() nvr = await self._api.get_nvr()
if await nvr.get_is_prerelease(): if nvr.release_channel != FirmwareReleaseChannel.RELEASE:
return await self.async_step_confirm() return await self.async_step_confirm()
await self.hass.config_entries.async_reload(self._entry.entry_id) await self.hass.config_entries.async_reload(self._entry.entry_id)
return self.async_create_entry(data={}) return self.async_create_entry(data={})
@ -124,7 +125,7 @@ async def async_create_fix_flow(
data: dict[str, str | int | float | None] | None, data: dict[str, str | int | float | None] | None,
) -> RepairsFlow: ) -> RepairsFlow:
"""Create flow.""" """Create flow."""
if data is not None and issue_id == "ea_warning": if data is not None and issue_id == "ea_channel_warning":
entry_id = cast(str, data["entry_id"]) entry_id = cast(str, data["entry_id"])
if (entry := hass.config_entries.async_get_entry(entry_id)) is not None: if (entry := hass.config_entries.async_get_entry(entry_id)) is not None:
api = async_create_api_client(hass, entry) api = async_create_api_client(hass, entry)

View File

@ -61,16 +61,16 @@
} }
}, },
"issues": { "issues": {
"ea_warning": { "ea_channel_warning": {
"title": "UniFi Protect v{version} is an Early Access version", "title": "UniFi Protect Early Access enabled",
"fix_flow": { "fix_flow": {
"step": { "step": {
"start": { "start": {
"title": "v{version} is an Early Access version", "title": "UniFi Protect Early Access enabled",
"description": "You are using v{version} of UniFi Protect which is an Early Access version. [Early Access versions are not supported by Home Assistant](https://www.home-assistant.io/integrations/unifiprotect#about-unifi-early-access) and it is recommended to go back to a stable release as soon as possible.\n\nBy submitting this form you have either [downgraded UniFi Protect](https://www.home-assistant.io/integrations/unifiprotect#downgrading-unifi-protect) or you agree to run an unsupported version of UniFi Protect." "description": "You are either running an Early Access version of UniFi Protect (v{version}) or opt-ed into a release channel that is not the Official Release Channel. [Home Assistant does not support Early Access versions](https://www.home-assistant.io/integrations/unifiprotect#about-unifi-early-access), so you should immediately switch to the Official Release Channel. Accidentally upgrading to an Early Access version can break your UniFi Protect integration.\n\nBy submitting this form, you have switched back to the Official Release Channel or agree to run an unsupported version of UniFi Protect, which may break your Home Assistant integration at any time."
}, },
"confirm": { "confirm": {
"title": "[%key:component::unifiprotect::issues::ea_warning::fix_flow::step::start::title%]", "title": "[%key:component::unifiprotect::issues::ea_channel_warning::fix_flow::step::start::title%]",
"description": "Are you sure you want to run unsupported versions of UniFi Protect? This may cause your Home Assistant integration to break." "description": "Are you sure you want to run unsupported versions of UniFi Protect? This may cause your Home Assistant integration to break."
} }
} }
@ -78,7 +78,7 @@
}, },
"ea_setup_failed": { "ea_setup_failed": {
"title": "Setup error using Early Access version", "title": "Setup error using Early Access version",
"description": "You are using v{version} of UniFi Protect which is an Early Access version. An unrecoverable error occurred while trying to load the integration. Please [downgrade to a stable version](https://www.home-assistant.io/integrations/unifiprotect#downgrading-unifi-protect) of UniFi Protect to continue using the integration.\n\nError: {error}" "description": "You are using v{version} of UniFi Protect which is an Early Access version. An unrecoverable error occurred while trying to load the integration. Please restore a backup of a stable release of UniFi Protect to continue using the integration.\n\nError: {error}"
}, },
"cloud_user": { "cloud_user": {
"title": "Ubiquiti Cloud Users are not Supported", "title": "Ubiquiti Cloud Users are not Supported",

View File

@ -328,7 +328,7 @@ async def test_form_options(hass: HomeAssistant, ufp_client: ProtectApiClient) -
"disable_rtsp": True, "disable_rtsp": True,
"override_connection_host": True, "override_connection_host": True,
"max_media": 1000, "max_media": 1000,
"allow_ea": False, "allow_ea_channel": False,
} }
await hass.config_entries.async_unload(mock_config.entry_id) await hass.config_entries.async_unload(mock_config.entry_id)

View File

@ -46,12 +46,14 @@ async def test_ea_warning_ignore(
assert len(msg["result"]["issues"]) > 0 assert len(msg["result"]["issues"]) > 0
issue = None issue = None
for i in msg["result"]["issues"]: for i in msg["result"]["issues"]:
if i["issue_id"] == "ea_warning": if i["issue_id"] == "ea_channel_warning":
issue = i issue = i
assert issue is not None assert issue is not None
url = RepairsFlowIndexView.url url = RepairsFlowIndexView.url
resp = await client.post(url, json={"handler": DOMAIN, "issue_id": "ea_warning"}) resp = await client.post(
url, json={"handler": DOMAIN, "issue_id": "ea_channel_warning"}
)
assert resp.status == HTTPStatus.OK assert resp.status == HTTPStatus.OK
data = await resp.json() data = await resp.json()
@ -104,12 +106,14 @@ async def test_ea_warning_fix(
assert len(msg["result"]["issues"]) > 0 assert len(msg["result"]["issues"]) > 0
issue = None issue = None
for i in msg["result"]["issues"]: for i in msg["result"]["issues"]:
if i["issue_id"] == "ea_warning": if i["issue_id"] == "ea_channel_warning":
issue = i issue = i
assert issue is not None assert issue is not None
url = RepairsFlowIndexView.url url = RepairsFlowIndexView.url
resp = await client.post(url, json={"handler": DOMAIN, "issue_id": "ea_warning"}) resp = await client.post(
url, json={"handler": DOMAIN, "issue_id": "ea_channel_warning"}
)
assert resp.status == HTTPStatus.OK assert resp.status == HTTPStatus.OK
data = await resp.json() data = await resp.json()
@ -122,8 +126,9 @@ async def test_ea_warning_fix(
new_nvr = copy(ufp.api.bootstrap.nvr) new_nvr = copy(ufp.api.bootstrap.nvr)
new_nvr.version = Version("2.2.6") new_nvr.version = Version("2.2.6")
new_nvr.release_channel = "release"
mock_msg = Mock() mock_msg = Mock()
mock_msg.changed_data = {"version": "2.2.6"} mock_msg.changed_data = {"version": "2.2.6", "releaseChannel": "release"}
mock_msg.new_obj = new_nvr mock_msg.new_obj = new_nvr
ufp.api.bootstrap.nvr = new_nvr ufp.api.bootstrap.nvr = new_nvr