Add diagnostics file export to generic camera (#71492)
This commit is contained in:
parent
9bd508c0bf
commit
807df530bc
3 changed files with 108 additions and 0 deletions
49
homeassistant/components/generic/diagnostics.py
Normal file
49
homeassistant/components/generic/diagnostics.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
"""Diagnostics support for generic (IP camera)."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import yarl
|
||||||
|
|
||||||
|
from homeassistant.components.diagnostics import async_redact_data
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .const import CONF_STILL_IMAGE_URL, CONF_STREAM_SOURCE
|
||||||
|
|
||||||
|
TO_REDACT = {
|
||||||
|
CONF_PASSWORD,
|
||||||
|
CONF_USERNAME,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# A very similar redact function is in components.sql. Possible to be made common.
|
||||||
|
def redact_url(data: str) -> str:
|
||||||
|
"""Redact credentials from string url."""
|
||||||
|
url_in = yarl.URL(data)
|
||||||
|
if url_in.user:
|
||||||
|
url = url_in.with_user("****")
|
||||||
|
if url_in.password:
|
||||||
|
url = url.with_password("****")
|
||||||
|
if url_in.path:
|
||||||
|
url = url.with_path("****")
|
||||||
|
if url_in.query_string:
|
||||||
|
url = url.with_query("****=****")
|
||||||
|
return str(url)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_config_entry_diagnostics(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Return diagnostics for a config entry."""
|
||||||
|
options = async_redact_data(entry.options, TO_REDACT)
|
||||||
|
for key in (CONF_STREAM_SOURCE, CONF_STILL_IMAGE_URL):
|
||||||
|
if (value := options.get(key)) is not None:
|
||||||
|
options[key] = redact_url(value)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"title": entry.title,
|
||||||
|
"data": async_redact_data(entry.data, TO_REDACT),
|
||||||
|
"options": options,
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ import respx
|
||||||
from homeassistant import config_entries, setup
|
from homeassistant import config_entries, setup
|
||||||
from homeassistant.components.generic.const import DOMAIN
|
from homeassistant.components.generic.const import DOMAIN
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="package")
|
@pytest.fixture(scope="package")
|
||||||
def fakeimgbytes_png():
|
def fakeimgbytes_png():
|
||||||
|
@ -79,3 +81,36 @@ async def user_flow(hass):
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="config_entry")
|
||||||
|
def config_entry_fixture(hass):
|
||||||
|
"""Define a config entry fixture."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="Test Camera",
|
||||||
|
unique_id="abc123",
|
||||||
|
data={},
|
||||||
|
options={
|
||||||
|
"still_image_url": "http://joebloggs:letmein1@example.com/secret1/file.jpg?pw=qwerty",
|
||||||
|
"stream_source": "http://janebloggs:letmein2@example.com/stream",
|
||||||
|
"username": "johnbloggs",
|
||||||
|
"password": "letmein123",
|
||||||
|
"limit_refetch_to_url_change": False,
|
||||||
|
"authentication": "basic",
|
||||||
|
"framerate": 2.0,
|
||||||
|
"verify_ssl": True,
|
||||||
|
"content_type": "image/jpeg",
|
||||||
|
},
|
||||||
|
version=1,
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
return entry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def setup_entry(hass, config_entry):
|
||||||
|
"""Set up a config entry ready to be used in tests."""
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
return config_entry
|
||||||
|
|
24
tests/components/generic/test_diagnostics.py
Normal file
24
tests/components/generic/test_diagnostics.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
"""Test generic (IP camera) diagnostics."""
|
||||||
|
from homeassistant.components.diagnostics import REDACTED
|
||||||
|
|
||||||
|
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entry_diagnostics(hass, hass_client, setup_entry):
|
||||||
|
"""Test config entry diagnostics."""
|
||||||
|
|
||||||
|
assert await get_diagnostics_for_config_entry(hass, hass_client, setup_entry) == {
|
||||||
|
"title": "Test Camera",
|
||||||
|
"data": {},
|
||||||
|
"options": {
|
||||||
|
"still_image_url": "http://****:****@example.com/****?****=****",
|
||||||
|
"stream_source": "http://****:****@example.com/****",
|
||||||
|
"username": REDACTED,
|
||||||
|
"password": REDACTED,
|
||||||
|
"limit_refetch_to_url_change": False,
|
||||||
|
"authentication": "basic",
|
||||||
|
"framerate": 2.0,
|
||||||
|
"verify_ssl": True,
|
||||||
|
"content_type": "image/jpeg",
|
||||||
|
},
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue