Remove discovery config validation from supervisor (#4937)

* Remove discovery config validation from supervisor

* Remove invalid test

* Change validation to require a dictionary for compatibility
This commit is contained in:
Mike Degatano 2024-03-05 10:25:15 -05:00 committed by GitHub
parent 202ebf6d4e
commit 74a5899626
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 67 additions and 641 deletions

View File

@ -99,7 +99,6 @@ from ..const import (
AddonStartup, AddonStartup,
AddonState, AddonState,
) )
from ..discovery.validate import valid_discovery_service
from ..docker.const import Capabilities from ..docker.const import Capabilities
from ..validate import ( from ..validate import (
docker_image, docker_image,
@ -190,20 +189,6 @@ def _warn_addon_config(config: dict[str, Any]):
name, name,
) )
invalid_services: list[str] = []
for service in config.get(ATTR_DISCOVERY, []):
try:
valid_discovery_service(service)
except vol.Invalid:
invalid_services.append(service)
if invalid_services:
_LOGGER.warning(
"Add-on lists the following unknown services for discovery: %s. Please report this to the maintainer of %s",
", ".join(invalid_services),
name,
)
return config return config

View File

@ -15,7 +15,6 @@ from ..const import (
AddonState, AddonState,
) )
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..discovery.validate import valid_discovery_service
from ..exceptions import APIError, APIForbidden from ..exceptions import APIError, APIForbidden
from .utils import api_process, api_validate, require_home_assistant from .utils import api_process, api_validate, require_home_assistant
@ -24,7 +23,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_DISCOVERY = vol.Schema( SCHEMA_DISCOVERY = vol.Schema(
{ {
vol.Required(ATTR_SERVICE): str, vol.Required(ATTR_SERVICE): str,
vol.Optional(ATTR_CONFIG): vol.Maybe(dict), vol.Required(ATTR_CONFIG): dict,
} }
) )
@ -71,15 +70,6 @@ class APIDiscovery(CoreSysAttributes):
addon: Addon = request[REQUEST_FROM] addon: Addon = request[REQUEST_FROM]
service = body[ATTR_SERVICE] service = body[ATTR_SERVICE]
try:
valid_discovery_service(service)
except vol.Invalid:
_LOGGER.warning(
"Received discovery message for unknown service %s from addon %s. Please report this to the maintainer of the add-on",
service,
addon.name,
)
# Access? # Access?
if body[ATTR_SERVICE] not in addon.discovery: if body[ATTR_SERVICE] not in addon.discovery:
_LOGGER.error( _LOGGER.error(

View File

@ -7,14 +7,12 @@ from typing import TYPE_CHECKING, Any
from uuid import UUID, uuid4 from uuid import UUID, uuid4
import attr import attr
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..const import ATTR_CONFIG, ATTR_DISCOVERY, FILE_HASSIO_DISCOVERY from ..const import ATTR_CONFIG, ATTR_DISCOVERY, FILE_HASSIO_DISCOVERY
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import DiscoveryError, HomeAssistantAPIError from ..exceptions import HomeAssistantAPIError
from ..utils.common import FileConfiguration from ..utils.common import FileConfiguration
from .validate import SCHEMA_DISCOVERY_CONFIG, valid_discovery_config from .validate import SCHEMA_DISCOVERY_CONFIG
if TYPE_CHECKING: if TYPE_CHECKING:
from ..addons.addon import Addon from ..addons.addon import Addon
@ -75,12 +73,6 @@ class Discovery(CoreSysAttributes, FileConfiguration):
def send(self, addon: Addon, service: str, config: dict[str, Any]) -> Message: def send(self, addon: Addon, service: str, config: dict[str, Any]) -> Message:
"""Send a discovery message to Home Assistant.""" """Send a discovery message to Home Assistant."""
try:
config = valid_discovery_config(service, config)
except vol.Invalid as err:
_LOGGER.error("Invalid discovery %s config", humanize_error(config, err))
raise DiscoveryError() from err
# Create message # Create message
message = Message(addon.slug, service, config) message = Message(addon.slug, service, config)

View File

@ -1 +0,0 @@
"""Discovery service modules."""

View File

@ -1,9 +0,0 @@
"""Discovery service for AdGuard."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
SCHEMA = vol.Schema(
{vol.Required(ATTR_HOST): str, vol.Required(ATTR_PORT): network_port}
)

View File

@ -1,9 +0,0 @@
"""Discovery service for Almond."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
SCHEMA = vol.Schema(
{vol.Required(ATTR_HOST): str, vol.Required(ATTR_PORT): network_port}
)

View File

@ -1,14 +0,0 @@
"""Discovery service for MQTT."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_API_KEY, ATTR_HOST, ATTR_PORT, ATTR_SERIAL
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
vol.Required(ATTR_SERIAL): str,
vol.Required(ATTR_API_KEY): str,
}
)

View File

@ -1,9 +0,0 @@
"""Discovery service for the ESPHome Dashboard."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
SCHEMA = vol.Schema(
{vol.Required(ATTR_HOST): str, vol.Required(ATTR_PORT): network_port}
)

View File

@ -1,16 +0,0 @@
"""Discovery service for HomeMatic."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
SCHEMA = vol.Schema(
{
str: vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
}
)
}
)

View File

@ -1,13 +0,0 @@
"""Discovery service for Matter Server."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
# pylint: disable=no-value-for-parameter
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
}
)

View File

@ -1,6 +0,0 @@
"""Discovery service for motionEye."""
import voluptuous as vol
from ..const import ATTR_URL
SCHEMA = vol.Schema({vol.Required(ATTR_URL): str})

View File

@ -1,26 +0,0 @@
"""Discovery service for MQTT."""
import voluptuous as vol
from ...validate import network_port
from ..const import (
ATTR_HOST,
ATTR_PASSWORD,
ATTR_PORT,
ATTR_PROTOCOL,
ATTR_SSL,
ATTR_USERNAME,
)
# pylint: disable=no-value-for-parameter
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
vol.Optional(ATTR_USERNAME): str,
vol.Optional(ATTR_PASSWORD): str,
vol.Optional(ATTR_SSL, default=False): vol.Boolean(),
vol.Optional(ATTR_PROTOCOL, default="3.1.1"): vol.All(
str, vol.In(["3.1", "3.1.1"])
),
}
)

View File

@ -1,13 +0,0 @@
"""Discovery service for OpenThread Border Router."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
# pylint: disable=no-value-for-parameter
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
}
)

View File

@ -1,15 +0,0 @@
"""Discovery service for OpenZwave MQTT."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PASSWORD, ATTR_PORT, ATTR_USERNAME
# pylint: disable=no-value-for-parameter
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
vol.Required(ATTR_USERNAME): str,
vol.Required(ATTR_PASSWORD): str,
}
)

View File

@ -1,9 +0,0 @@
"""Discovery service for RTSPtoWebRTC."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
SCHEMA = vol.Schema(
{vol.Required(ATTR_HOST): str, vol.Required(ATTR_PORT): network_port}
)

View File

@ -1,9 +0,0 @@
"""Discovery service for UniFi."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
SCHEMA = vol.Schema(
{vol.Required(ATTR_HOST): str, vol.Required(ATTR_PORT): network_port}
)

View File

@ -1,14 +0,0 @@
"""Discovery service for VLC Telnet."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PASSWORD, ATTR_PORT
# pylint: disable=no-value-for-parameter
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
vol.Required(ATTR_PASSWORD): str,
}
)

View File

@ -1,25 +0,0 @@
"""Discovery service for the Wyoming Protocol integration."""
from typing import Any, cast
from urllib.parse import urlparse
import voluptuous as vol
from ..const import ATTR_URI
def validate_uri(value: Any) -> str:
"""Validate an Wyoming URI.
Currently accepts TCP URIs, can extended
to accept UNIX sockets in the future.
"""
uri_value = str(value)
if urlparse(uri_value).scheme == "tcp":
# pylint: disable-next=no-value-for-parameter
return cast(str, vol.Schema(vol.Url())(uri_value))
raise vol.Invalid("invalid Wyoming Protocol URI")
SCHEMA = vol.Schema({vol.Required(ATTR_URI): validate_uri})

View File

@ -1,13 +0,0 @@
"""Discovery service for Zwave JS."""
import voluptuous as vol
from ...validate import network_port
from ..const import ATTR_HOST, ATTR_PORT
# pylint: disable=no-value-for-parameter
SCHEMA = vol.Schema(
{
vol.Required(ATTR_HOST): str,
vol.Required(ATTR_PORT): network_port,
}
)

View File

@ -1,6 +1,4 @@
"""Validate services schema.""" """Validate services schema."""
from importlib import import_module
from pathlib import Path
import voluptuous as vol import voluptuous as vol
@ -8,25 +6,6 @@ from ..const import ATTR_ADDON, ATTR_CONFIG, ATTR_DISCOVERY, ATTR_SERVICE, ATTR_
from ..utils.validate import schema_or from ..utils.validate import schema_or
from ..validate import uuid_match from ..validate import uuid_match
def valid_discovery_service(service):
"""Validate service name."""
service_file = Path(__file__).parent.joinpath(f"services/{service}.py")
if not service_file.exists():
raise vol.Invalid(f"Service {service} not found") from None
return service
def valid_discovery_config(service, config):
"""Validate service name."""
try:
service_mod = import_module(f".services.{service}", "supervisor.discovery")
except ImportError:
raise vol.Invalid(f"Service {service} not found") from None
return service_mod.SCHEMA(config)
SCHEMA_DISCOVERY = vol.Schema( SCHEMA_DISCOVERY = vol.Schema(
[ [
vol.Schema( vol.Schema(

View File

@ -1,7 +1,5 @@
"""Validate Add-on configs.""" """Validate Add-on configs."""
import logging
from unittest.mock import Mock
import pytest import pytest
import voluptuous as vol import voluptuous as vol
@ -288,14 +286,3 @@ def test_valid_slug():
config["slug"] = "complemento telefónico" config["slug"] = "complemento telefónico"
with pytest.raises(vol.Invalid): with pytest.raises(vol.Invalid):
assert vd.SCHEMA_ADDON_CONFIG(config) assert vd.SCHEMA_ADDON_CONFIG(config)
def test_invalid_discovery(capture_event: Mock, caplog: pytest.LogCaptureFixture):
"""Test invalid discovery."""
config = load_json_fixture("basic-addon-config.json")
config["discovery"] = ["mqtt", "junk", "junk2"]
assert vd.SCHEMA_ADDON_CONFIG(config)
with caplog.at_level(logging.WARNING):
assert "unknown services for discovery: junk, junk2" in caplog.text

View File

@ -1,8 +1,7 @@
"""Test discovery API.""" """Test discovery API."""
import logging import logging
from unittest.mock import ANY, MagicMock, patch from unittest.mock import ANY, AsyncMock, MagicMock, patch
from uuid import uuid4
from aiohttp.test_utils import TestClient from aiohttp.test_utils import TestClient
import pytest import pytest
@ -10,9 +9,10 @@ import pytest
from supervisor.addons.addon import Addon from supervisor.addons.addon import Addon
from supervisor.const import AddonState from supervisor.const import AddonState
from supervisor.coresys import CoreSys from supervisor.coresys import CoreSys
from supervisor.discovery import Discovery, Message from supervisor.discovery import Message
from tests.common import load_json_fixture from tests.common import load_json_fixture
from tests.const import TEST_ADDON_SLUG
@pytest.mark.parametrize("api_client", ["local_ssh"], indirect=True) @pytest.mark.parametrize("api_client", ["local_ssh"], indirect=True)
@ -23,7 +23,9 @@ async def test_api_discovery_forbidden(
caplog.clear() caplog.clear()
with caplog.at_level(logging.ERROR): with caplog.at_level(logging.ERROR):
resp = await api_client.post("/discovery", json={"service": "mqtt"}) resp = await api_client.post(
"/discovery", json={"service": "mqtt", "config": {}}
)
assert resp.status == 403 assert resp.status == 403
result = await resp.json() result = await resp.json()
@ -35,28 +37,6 @@ async def test_api_discovery_forbidden(
assert "Please report this to the maintainer of the add-on" in caplog.text assert "Please report this to the maintainer of the add-on" in caplog.text
@pytest.mark.parametrize("api_client", ["local_ssh"], indirect=True)
async def test_api_discovery_unknown_service(
api_client: TestClient, caplog: pytest.LogCaptureFixture, install_addon_ssh: Addon
):
"""Test addon sending discovery message for an unkown service."""
caplog.clear()
install_addon_ssh.data["discovery"] = ["junk"]
message = MagicMock()
message.uuid = uuid4().hex
with caplog.at_level(logging.WARNING), patch.object(
Discovery, "send", return_value=message
):
resp = await api_client.post("/discovery", json={"service": "junk"})
assert resp.status == 200
result = await resp.json()
assert result["data"]["uuid"] == message.uuid
assert "Please report this to the maintainer of the add-on" in caplog.text
@pytest.mark.parametrize( @pytest.mark.parametrize(
"skip_state", [AddonState.ERROR, AddonState.STOPPED, AddonState.STARTUP] "skip_state", [AddonState.ERROR, AddonState.STOPPED, AddonState.STARTUP]
) )
@ -97,3 +77,61 @@ async def test_api_list_discovery(
assert resp.status == 200 assert resp.status == 200
result = await resp.json() result = await resp.json()
assert result["data"]["discovery"] == [] assert result["data"]["discovery"] == []
@pytest.mark.parametrize("api_client", [TEST_ADDON_SLUG], indirect=True)
async def test_api_send_del_discovery(
api_client: TestClient, coresys: CoreSys, install_addon_ssh: Addon
):
"""Test adding and removing discovery."""
install_addon_ssh.data["discovery"] = ["test"]
coresys.homeassistant.api.ensure_access_token = AsyncMock()
coresys.websession.post = MagicMock()
resp = await api_client.post("/discovery", json={"service": "test", "config": {}})
assert resp.status == 200
result = await resp.json()
uuid = result["data"]["uuid"]
coresys.websession.post.assert_called_once()
assert (
coresys.websession.post.call_args.args[0]
== f"http://172.30.32.1:8123/api/hassio_push/discovery/{uuid}"
)
assert coresys.websession.post.call_args.kwargs["json"] == {
"addon": TEST_ADDON_SLUG,
"service": "test",
"uuid": uuid,
}
message = coresys.discovery.get(uuid)
assert message.addon == TEST_ADDON_SLUG
assert message.service == "test"
assert message.config == {}
coresys.websession.delete = MagicMock()
resp = await api_client.delete(f"/discovery/{uuid}")
assert resp.status == 200
coresys.websession.delete.assert_called_once()
assert (
coresys.websession.delete.call_args.args[0]
== f"http://172.30.32.1:8123/api/hassio_push/discovery/{uuid}"
)
assert coresys.websession.delete.call_args.kwargs["json"] == {
"addon": TEST_ADDON_SLUG,
"service": "test",
"uuid": uuid,
}
assert coresys.discovery.get(uuid) is None
@pytest.mark.parametrize("api_client", [TEST_ADDON_SLUG], indirect=True)
async def test_api_invalid_discovery(api_client: TestClient, install_addon_ssh: Addon):
"""Test invalid discovery messages."""
install_addon_ssh.data["discovery"] = ["test"]
resp = await api_client.post("/discovery", json={"service": "test"})
assert resp.status == 400
resp = await api_client.post("/discovery", json={"service": "test", "config": None})
assert resp.status == 400

View File

@ -1 +0,0 @@
"""Tests for discovery."""

View File

@ -1,19 +0,0 @@
"""Test adguard discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good adguard config."""
valid_discovery_config("adguard", {"host": "test", "port": 3812})
def test_bad_config():
"""Test bad adguard config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("adguard", {"host": "test"})

View File

@ -1,19 +0,0 @@
"""Test almond discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good almond config."""
valid_discovery_config("almond", {"host": "test", "port": 3812})
def test_bad_config():
"""Test bad almond config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("almond", {"host": "test"})

View File

@ -1,22 +0,0 @@
"""Test DeConz discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good deconz config."""
valid_discovery_config(
"deconz",
{"host": "test", "port": 3812, "api_key": "MY_api_KEY99", "serial": "xyz"},
)
def test_bad_config():
"""Test bad deconz config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("deconz", {"host": "test", "port": 8080})

View File

@ -1,25 +0,0 @@
"""Test ESPHome Dashboard discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good ESPHome config."""
valid_discovery_config("esphome", {"host": "test", "port": 6052})
def test_bad_config():
"""Test bad ESPHome config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("esphome", {"host": "test"})
with pytest.raises(vol.Invalid):
valid_discovery_config("esphome", {"port": 6052})
with pytest.raises(vol.Invalid):
valid_discovery_config("esphome", {"port": -1})

View File

@ -1,22 +0,0 @@
"""Test HomeMatic discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good homematic config."""
valid_discovery_config(
"homematic",
{"ip": {"host": "test", "port": 3812}, "rf": {"host": "test", "port": 3712}},
)
def test_bad_config():
"""Test bad homematic config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("homematic", {"test": {"bla": "test", "port": 8080}})

View File

@ -1,22 +0,0 @@
"""Test Matter Server discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good Matter Server config."""
valid_discovery_config(
"matter",
{"host": "test", "port": 3812},
)
def test_bad_config():
"""Test bad Matter Server config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("matter", {"host": "test"})

View File

@ -1,17 +0,0 @@
"""Test motionEye discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config() -> None:
"""Test good motionEye config."""
valid_discovery_config("motioneye", {"url": "http://example.com:1234"})
def test_bad_config() -> None:
"""Test bad motionEye config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("motioneye", {})

View File

@ -1,21 +0,0 @@
"""Test MQTT discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good mqtt config."""
valid_discovery_config(
"mqtt", {"host": "test", "port": 3812, "username": "bla", "ssl": True}
)
def test_bad_config():
"""Test bad mqtt config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("mqtt", {"host": "test", "username": "bla", "ssl": True})

View File

@ -1,22 +0,0 @@
"""Test OTBR discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good OTBR config."""
valid_discovery_config(
"otbr",
{"host": "test", "port": 3812},
)
def test_bad_config():
"""Test bad OTBR config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("otbr", {"host": "test"})

View File

@ -1,22 +0,0 @@
"""Test OpenZwave MQTT discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good zwave mqtt config."""
valid_discovery_config(
"ozw",
{"host": "test", "port": 3812, "username": "bla", "password": "test"},
)
def test_bad_config():
"""Test bad zwave mqtt config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("ozw", {"host": "test", "username": "bla", "ssl": True})

View File

@ -1,21 +0,0 @@
"""Test rtsp_to_webrtc discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
SERVICE = "rtsp_to_webrtc"
def test_good_config():
"""Test good config."""
valid_discovery_config(SERVICE, {"host": "test", "port": 3812})
def test_bad_config():
"""Test bad config."""
with pytest.raises(vol.Invalid):
valid_discovery_config(SERVICE, {"host": "test"})

View File

@ -1,19 +0,0 @@
"""Test unifi discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good unifi config."""
valid_discovery_config("unifi", {"host": "test", "port": 3812})
def test_bad_config():
"""Test bad unifi config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("unifi", {"host": "test"})

View File

@ -1,21 +0,0 @@
"""Test validate of discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery import validate
def test_valid_services():
"""Validate that service is valid."""
for service in ("mqtt", "deconz"):
validate.valid_discovery_service(service)
def test_invalid_services():
"""Test that validate is invalid for a service."""
for service in ("fadsfasd", "203432"):
with pytest.raises(vol.Invalid):
validate.valid_discovery_service(service)

View File

@ -1,22 +0,0 @@
"""Test VLC Telnet discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good vlc telnet config."""
valid_discovery_config(
"vlc_telnet",
{"host": "test", "port": 3812, "password": "darksideofthemoon"},
)
def test_bad_config():
"""Test bad vlc telnet config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("vlc_telnet", {"host": "test", "port": 8283})

View File

@ -1,27 +0,0 @@
"""Test wyoming discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good wyoming config."""
valid_discovery_config("wyoming", {"uri": "tcp://core-wyoming"})
valid_discovery_config("wyoming", {"uri": "tcp://core-wyoming:1234"})
def test_bad_config():
"""Test bad wyoming config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("wyoming", {"host": "test"})
with pytest.raises(vol.Invalid):
valid_discovery_config("wyoming", {"uri": "https://also.an.uri.com"})
with pytest.raises(vol.Invalid):
valid_discovery_config("wyoming", {"uri": "unix://not/supported/yet.socket"})

View File

@ -1,22 +0,0 @@
"""Test Zwave JS discovery."""
import pytest
import voluptuous as vol
from supervisor.discovery.validate import valid_discovery_config
def test_good_config():
"""Test good zwave js config."""
valid_discovery_config(
"zwave_js",
{"host": "test", "port": 3812},
)
def test_bad_config():
"""Test bad zwave js config."""
with pytest.raises(vol.Invalid):
valid_discovery_config("zwave_js", {"host": "test"})