Remove deprecated YAML configuration from MJPEG Camera (#68980)

This commit is contained in:
Franck Nijhof 2022-04-04 17:57:48 +02:00 committed by GitHub
parent 8222b783a3
commit b369616aad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 209 deletions

View file

@ -10,13 +10,11 @@ from aiohttp import web
import async_timeout import async_timeout
import requests import requests
from requests.auth import HTTPBasicAuth, HTTPDigestAuth from requests.auth import HTTPBasicAuth, HTTPDigestAuth
import voluptuous as vol
from homeassistant.components.camera import PLATFORM_SCHEMA, Camera from homeassistant.components.camera import Camera
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
CONF_AUTHENTICATION, CONF_AUTHENTICATION,
CONF_NAME,
CONF_PASSWORD, CONF_PASSWORD,
CONF_USERNAME, CONF_USERNAME,
CONF_VERIFY_SSL, CONF_VERIFY_SSL,
@ -24,62 +22,15 @@ from homeassistant.const import (
HTTP_DIGEST_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import ( from homeassistant.helpers.aiohttp_client import (
async_aiohttp_proxy_web, async_aiohttp_proxy_web,
async_get_clientsession, async_get_clientsession,
) )
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, DOMAIN, LOGGER from .const import CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, DOMAIN, LOGGER
CONTENT_TYPE_HEADER = "Content-Type"
DEFAULT_NAME = "Mjpeg Camera"
DEFAULT_VERIFY_SSL = True
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_MJPEG_URL): cv.url,
vol.Optional(CONF_STILL_IMAGE_URL): cv.url,
vol.Optional(CONF_AUTHENTICATION, default=HTTP_BASIC_AUTHENTICATION): vol.In(
[HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION]
),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PASSWORD, default=""): cv.string,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
}
)
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the MJPEG IP camera from platform."""
LOGGER.warning(
"Configuration of the MJPEG IP Camera platform in YAML is deprecated "
"and will be removed in Home Assistant 2022.5; Your existing "
"configuration has been imported into the UI automatically and can be "
"safely removed from your configuration.yaml file"
)
if discovery_info:
config = PLATFORM_SCHEMA(discovery_info)
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data=config,
)
)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,

View file

@ -174,22 +174,6 @@ class MJPEGFlowHandler(ConfigFlow, domain=DOMAIN):
errors=errors, errors=errors,
) )
async def async_step_import(self, config: dict[str, Any]) -> FlowResult:
"""Handle a flow initialized by importing a config."""
self._async_abort_entries_match({CONF_MJPEG_URL: config[CONF_MJPEG_URL]})
return self.async_create_entry(
title=config[CONF_NAME],
data={},
options={
CONF_AUTHENTICATION: config[CONF_AUTHENTICATION],
CONF_MJPEG_URL: config[CONF_MJPEG_URL],
CONF_PASSWORD: config[CONF_PASSWORD],
CONF_STILL_IMAGE_URL: config.get(CONF_STILL_IMAGE_URL),
CONF_USERNAME: config.get(CONF_USERNAME),
CONF_VERIFY_SSL: config[CONF_VERIFY_SSL],
},
)
class MJPEGOptionsFlowHandler(OptionsFlow): class MJPEGOptionsFlowHandler(OptionsFlow):
"""Handle MJPEG IP Camera options.""" """Handle MJPEG IP Camera options."""

View file

@ -10,7 +10,7 @@ from homeassistant.components.mjpeg.const import (
CONF_STILL_IMAGE_URL, CONF_STILL_IMAGE_URL,
DOMAIN, DOMAIN,
) )
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import ( from homeassistant.const import (
CONF_AUTHENTICATION, CONF_AUTHENTICATION,
CONF_NAME, CONF_NAME,
@ -18,7 +18,6 @@ from homeassistant.const import (
CONF_USERNAME, CONF_USERNAME,
CONF_VERIFY_SSL, CONF_VERIFY_SSL,
HTTP_BASIC_AUTHENTICATION, HTTP_BASIC_AUTHENTICATION,
HTTP_DIGEST_AUTHENTICATION,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import ( from homeassistant.data_entry_flow import (
@ -252,70 +251,6 @@ async def test_already_configured(
assert result2.get("reason") == "already_configured" assert result2.get("reason") == "already_configured"
async def test_import_flow(
hass: HomeAssistant,
mock_mjpeg_requests: Mocker,
mock_setup_entry: AsyncMock,
) -> None:
"""Test the import configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_AUTHENTICATION: HTTP_DIGEST_AUTHENTICATION,
CONF_MJPEG_URL: "http://example.com/mjpeg",
CONF_NAME: "Imported Camera",
CONF_PASSWORD: "omgpuppies",
CONF_STILL_IMAGE_URL: "http://example.com/still",
CONF_USERNAME: "frenck",
CONF_VERIFY_SSL: False,
},
)
assert result.get("type") == RESULT_TYPE_CREATE_ENTRY
assert result.get("title") == "Imported Camera"
assert result.get("data") == {}
assert result.get("options") == {
CONF_AUTHENTICATION: HTTP_DIGEST_AUTHENTICATION,
CONF_MJPEG_URL: "http://example.com/mjpeg",
CONF_PASSWORD: "omgpuppies",
CONF_STILL_IMAGE_URL: "http://example.com/still",
CONF_USERNAME: "frenck",
CONF_VERIFY_SSL: False,
}
assert len(mock_setup_entry.mock_calls) == 1
assert mock_mjpeg_requests.call_count == 0
async def test_import_flow_already_configured(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_setup_entry: AsyncMock,
) -> None:
"""Test the import configuration flow for an already configured entry."""
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_AUTHENTICATION: HTTP_DIGEST_AUTHENTICATION,
CONF_MJPEG_URL: "https://example.com/mjpeg",
CONF_NAME: "Imported Camera",
CONF_PASSWORD: "omgpuppies",
CONF_STILL_IMAGE_URL: "https://example.com/still",
CONF_USERNAME: "frenck",
CONF_VERIFY_SSL: False,
},
)
assert result.get("type") == RESULT_TYPE_ABORT
assert result.get("reason") == "already_configured"
assert len(mock_setup_entry.mock_calls) == 0
async def test_options_flow( async def test_options_flow(
hass: HomeAssistant, hass: HomeAssistant,
mock_mjpeg_requests: Mocker, mock_mjpeg_requests: Mocker,

View file

@ -1,25 +1,9 @@
"""Tests for the MJPEG IP Camera integration.""" """Tests for the MJPEG IP Camera integration."""
from unittest.mock import AsyncMock, MagicMock from unittest.mock import AsyncMock, MagicMock
import pytest from homeassistant.components.mjpeg.const import DOMAIN
from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN
from homeassistant.components.mjpeg.const import (
CONF_MJPEG_URL,
CONF_STILL_IMAGE_URL,
DOMAIN,
)
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
CONF_AUTHENTICATION,
CONF_NAME,
CONF_PASSWORD,
CONF_USERNAME,
CONF_VERIFY_SSL,
HTTP_BASIC_AUTHENTICATION,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -54,46 +38,3 @@ async def test_reload_config_entry(
init_integration, options={"something": "else"} init_integration, options={"something": "else"}
) )
assert len(mock_reload_entry.mock_calls) == 1 assert len(mock_reload_entry.mock_calls) == 1
async def test_import_config(
hass: HomeAssistant,
mock_mjpeg_requests: MagicMock,
mock_setup_entry: AsyncMock,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test MJPEG IP Camera being set up from config via import."""
assert await async_setup_component(
hass,
CAMERA_DOMAIN,
{
CAMERA_DOMAIN: {
"platform": DOMAIN,
CONF_MJPEG_URL: "http://example.com/mjpeg",
CONF_NAME: "Random Camera",
CONF_PASSWORD: "supersecret",
CONF_STILL_IMAGE_URL: "http://example.com/still",
CONF_USERNAME: "frenck",
CONF_VERIFY_SSL: False,
}
},
)
await hass.async_block_till_done()
config_entries = hass.config_entries.async_entries(DOMAIN)
assert len(config_entries) == 1
assert "the MJPEG IP Camera platform in YAML is deprecated" in caplog.text
entry = config_entries[0]
assert entry.title == "Random Camera"
assert entry.unique_id is None
assert entry.data == {}
assert entry.options == {
CONF_AUTHENTICATION: HTTP_BASIC_AUTHENTICATION,
CONF_MJPEG_URL: "http://example.com/mjpeg",
CONF_PASSWORD: "supersecret",
CONF_STILL_IMAGE_URL: "http://example.com/still",
CONF_USERNAME: "frenck",
CONF_VERIFY_SSL: False,
}

View file

@ -5,26 +5,42 @@ from unittest.mock import Mock, patch
import aiohttp import aiohttp
import pytest import pytest
from homeassistant.components.mjpeg.const import (
CONF_MJPEG_URL,
CONF_STILL_IMAGE_URL,
DOMAIN as MJPEG_DOMAIN,
)
from homeassistant.const import (
CONF_AUTHENTICATION,
CONF_PASSWORD,
CONF_USERNAME,
CONF_VERIFY_SSL,
HTTP_BASIC_AUTHENTICATION,
)
from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE
import homeassistant.helpers.aiohttp_client as client import homeassistant.helpers.aiohttp_client as client
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
@pytest.fixture(name="camera_client") @pytest.fixture(name="camera_client")
def camera_client_fixture(hass, hass_client): def camera_client_fixture(hass, hass_client):
"""Fixture to fetch camera streams.""" """Fixture to fetch camera streams."""
assert hass.loop.run_until_complete( mock_config_entry = MockConfigEntry(
async_setup_component( title="MJPEG Camera",
hass, domain=MJPEG_DOMAIN,
"camera", options={
{ CONF_AUTHENTICATION: HTTP_BASIC_AUTHENTICATION,
"camera": { CONF_MJPEG_URL: "http://example.com/mjpeg_stream",
"name": "config_test", CONF_PASSWORD: None,
"platform": "mjpeg", CONF_STILL_IMAGE_URL: None,
"mjpeg_url": "http://example.com/mjpeg_stream", CONF_USERNAME: None,
} CONF_VERIFY_SSL: True,
}, },
) )
mock_config_entry.add_to_hass(hass)
hass.loop.run_until_complete(
hass.config_entries.async_setup(mock_config_entry.entry_id)
) )
hass.loop.run_until_complete(hass.async_block_till_done()) hass.loop.run_until_complete(hass.async_block_till_done())
@ -175,7 +191,7 @@ async def test_async_aiohttp_proxy_stream(aioclient_mock, camera_client):
"""Test that it fetches the given url.""" """Test that it fetches the given url."""
aioclient_mock.get("http://example.com/mjpeg_stream", content=b"Frame1Frame2Frame3") aioclient_mock.get("http://example.com/mjpeg_stream", content=b"Frame1Frame2Frame3")
resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test") resp = await camera_client.get("/api/camera_proxy_stream/camera.mjpeg_camera")
assert resp.status == 200 assert resp.status == 200
assert aioclient_mock.call_count == 1 assert aioclient_mock.call_count == 1
@ -187,7 +203,7 @@ async def test_async_aiohttp_proxy_stream_timeout(aioclient_mock, camera_client)
"""Test that it fetches the given url.""" """Test that it fetches the given url."""
aioclient_mock.get("http://example.com/mjpeg_stream", exc=asyncio.TimeoutError()) aioclient_mock.get("http://example.com/mjpeg_stream", exc=asyncio.TimeoutError())
resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test") resp = await camera_client.get("/api/camera_proxy_stream/camera.mjpeg_camera")
assert resp.status == 504 assert resp.status == 504
@ -195,7 +211,7 @@ async def test_async_aiohttp_proxy_stream_client_err(aioclient_mock, camera_clie
"""Test that it fetches the given url.""" """Test that it fetches the given url."""
aioclient_mock.get("http://example.com/mjpeg_stream", exc=aiohttp.ClientError()) aioclient_mock.get("http://example.com/mjpeg_stream", exc=aiohttp.ClientError())
resp = await camera_client.get("/api/camera_proxy_stream/camera.config_test") resp = await camera_client.get("/api/camera_proxy_stream/camera.mjpeg_camera")
assert resp.status == 502 assert resp.status == 502