Do not allow config dependency (#6036)
* Do not allow config dependency * Prevent config in discovery * Migrate to blacklist
This commit is contained in:
parent
b277fd55f9
commit
f29ee24b72
5 changed files with 67 additions and 0 deletions
|
@ -299,6 +299,10 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
||||||
|
|
||||||
# Load dependencies
|
# Load dependencies
|
||||||
for component in getattr(platform, 'DEPENDENCIES', []):
|
for component in getattr(platform, 'DEPENDENCIES', []):
|
||||||
|
if component in loader.DEPENDENCY_BLACKLIST:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
'{} is not allowed to be a dependency.'.format(component))
|
||||||
|
|
||||||
res = yield from async_setup_component(hass, component, config)
|
res = yield from async_setup_component(hass, component, config)
|
||||||
if not res:
|
if not res:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
|
@ -430,7 +434,13 @@ def async_from_config_dict(config: Dict[str, Any],
|
||||||
service.HASS = hass
|
service.HASS = hass
|
||||||
|
|
||||||
# Setup the components
|
# Setup the components
|
||||||
|
dependency_blacklist = loader.DEPENDENCY_BLACKLIST - set(components)
|
||||||
|
|
||||||
for domain in loader.load_order_components(components):
|
for domain in loader.load_order_components(components):
|
||||||
|
if domain in dependency_blacklist:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
'{} is not allowed to be a dependency'.format(domain))
|
||||||
|
|
||||||
yield from _async_setup_component(hass, domain, config)
|
yield from _async_setup_component(hass, domain, config)
|
||||||
|
|
||||||
setup_lock.release()
|
setup_lock.release()
|
||||||
|
|
|
@ -10,6 +10,8 @@ import asyncio
|
||||||
from homeassistant import bootstrap, core
|
from homeassistant import bootstrap, core
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_DISCOVERED, ATTR_SERVICE, EVENT_PLATFORM_DISCOVERED)
|
ATTR_DISCOVERED, ATTR_SERVICE, EVENT_PLATFORM_DISCOVERED)
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.loader import DEPENDENCY_BLACKLIST
|
||||||
from homeassistant.util.async import run_callback_threadsafe
|
from homeassistant.util.async import run_callback_threadsafe
|
||||||
|
|
||||||
EVENT_LOAD_PLATFORM = 'load_platform.{}'
|
EVENT_LOAD_PLATFORM = 'load_platform.{}'
|
||||||
|
@ -56,6 +58,10 @@ def discover(hass, service, discovered=None, component=None, hass_config=None):
|
||||||
def async_discover(hass, service, discovered=None, component=None,
|
def async_discover(hass, service, discovered=None, component=None,
|
||||||
hass_config=None):
|
hass_config=None):
|
||||||
"""Fire discovery event. Can ensure a component is loaded."""
|
"""Fire discovery event. Can ensure a component is loaded."""
|
||||||
|
if component in DEPENDENCY_BLACKLIST:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
'Cannot discover the {} component.'.format(component))
|
||||||
|
|
||||||
if component is not None and component not in hass.config.components:
|
if component is not None and component not in hass.config.components:
|
||||||
did_lock = False
|
did_lock = False
|
||||||
setup_lock = hass.data.get('setup_lock')
|
setup_lock = hass.data.get('setup_lock')
|
||||||
|
@ -150,6 +156,10 @@ def async_load_platform(hass, component, platform, discovered=None,
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
|
if component in DEPENDENCY_BLACKLIST:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
'Cannot discover the {} component.'.format(component))
|
||||||
|
|
||||||
did_lock = False
|
did_lock = False
|
||||||
setup_lock = hass.data.get('setup_lock')
|
setup_lock = hass.data.get('setup_lock')
|
||||||
if setup_lock and setup_lock.locked():
|
if setup_lock and setup_lock.locked():
|
||||||
|
|
|
@ -30,6 +30,8 @@ if False:
|
||||||
|
|
||||||
PREPARED = False
|
PREPARED = False
|
||||||
|
|
||||||
|
DEPENDENCY_BLACKLIST = set(('config',))
|
||||||
|
|
||||||
# List of available components
|
# List of available components
|
||||||
AVAILABLE_COMPONENTS = [] # type: List[str]
|
AVAILABLE_COMPONENTS = [] # type: List[str]
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
"""Test discovery helpers."""
|
"""Test discovery helpers."""
|
||||||
|
import asyncio
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from homeassistant import loader, bootstrap
|
from homeassistant import loader, bootstrap
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.util.async import run_coroutine_threadsafe
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
|
|
||||||
|
@ -197,3 +201,17 @@ class TestHelpersDiscovery:
|
||||||
|
|
||||||
# test_component will only be setup once
|
# test_component will only be setup once
|
||||||
assert len(component_calls) == 1
|
assert len(component_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_load_platform_forbids_config():
|
||||||
|
"""Test you cannot setup config component with load_platform."""
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
yield from discovery.async_load_platform(None, 'config', 'zwave')
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_discover_forbids_config():
|
||||||
|
"""Test you cannot setup config component with load_platform."""
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
yield from discovery.async_discover(None, None, None, 'config')
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
"""Test the bootstrapping."""
|
"""Test the bootstrapping."""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
|
import asyncio
|
||||||
import os
|
import os
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
import pytest
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||||
import homeassistant.config as config_util
|
import homeassistant.config as config_util
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant import bootstrap, loader
|
from homeassistant import bootstrap, loader
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
|
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
|
||||||
|
@ -440,3 +443,27 @@ class TestBootstrap:
|
||||||
self.hass.start()
|
self.hass.start()
|
||||||
|
|
||||||
assert call_order == [1, 1, 2]
|
assert call_order == [1, 1, 2]
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_component_cannot_depend_config(hass):
|
||||||
|
"""Test config is not allowed to be a dependency."""
|
||||||
|
loader.set_component(
|
||||||
|
'test_component1',
|
||||||
|
MockModule('test_component1', dependencies=['config']))
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
yield from bootstrap.async_from_config_dict(
|
||||||
|
{'test_component1': None}, hass)
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_platform_cannot_depend_config():
|
||||||
|
"""Test config is not allowed to be a dependency."""
|
||||||
|
loader.set_component(
|
||||||
|
'test_component1.test',
|
||||||
|
MockPlatform('whatever', dependencies=['config']))
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
yield from bootstrap.async_prepare_setup_platform(
|
||||||
|
mock.MagicMock(), {}, 'test_component1', 'test')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue