Do not allow config dependency (#6036)

* Do not allow config dependency

* Prevent config in discovery

* Migrate to blacklist
This commit is contained in:
Paulus Schoutsen 2017-02-18 11:31:37 -08:00 committed by GitHub
parent b277fd55f9
commit f29ee24b72
5 changed files with 67 additions and 0 deletions

View file

@ -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()

View file

@ -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():

View file

@ -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]

View file

@ -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')

View file

@ -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')