Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check config script: various fixes #2967

Merged
merged 2 commits into from
Aug 25, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
check_config: --info all, --secrets & --files fixes
  • Loading branch information
kellerza committed Aug 24, 2016
commit 54072f7bd519811c5bfec6f25639e941754edfdf
9 changes: 6 additions & 3 deletions homeassistant/scripts/check_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
# pylint: disable=protected-access
MOCKS = {
'load': ("homeassistant.util.yaml.load_yaml", yaml.load_yaml),
'load*': ("homeassistant.config.load_yaml", yaml.load_yaml),
'get': ("homeassistant.loader.get_component", loader.get_component),
'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml),
'except': ("homeassistant.bootstrap.log_exception",
bootstrap.log_exception)
}
SILENCE = (
'homeassistant.util.yaml.clear_secret_cache',
'homeassistant.bootstrap.clear_secret_cache',
'homeassistant.core._LOGGER.info',
'homeassistant.loader._LOGGER.info',
'homeassistant.bootstrap._LOGGER.info',
Expand Down Expand Up @@ -114,7 +115,7 @@ def run(script_args: List) -> int:
if domain_info:
if 'all' in domain_info:
print(color('bold_white', 'Successful config (all)'))
for domain, config in res['components']:
for domain, config in res['components'].items():
print(color(C_HEAD, domain + ':'))
dump_dict(config, indent_count=3)
else:
Expand Down Expand Up @@ -207,7 +208,9 @@ def mock_except(ex, domain, config): # pylint: disable=unused-variable

# Patches with local mock functions
for key, val in MOCKS.items():
mock_function = locals()['mock_'+key]
# The * in the key is removed to find the mock_function (side_effect)
# This allows us to use one side_effect to patch multiple locations
mock_function = locals()['mock_' + key.replace('*', '')]
PATCHES[key] = patch(val[0], side_effect=mock_function)

# Start all patches
Expand Down
16 changes: 11 additions & 5 deletions homeassistant/util/yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,13 @@ def _env_var_yaml(loader: SafeLineLoader,

def _load_secret_yaml(secret_path: str) -> Dict:
"""Load the secrets yaml from path."""
_LOGGER.debug('Loading %s', os.path.join(secret_path, _SECRET_YAML))
secret_path = os.path.join(secret_path, _SECRET_YAML)
if secret_path in __SECRET_CACHE:
return __SECRET_CACHE[secret_path]

_LOGGER.debug('Loading %s', secret_path)
try:
secrets = load_yaml(os.path.join(secret_path, _SECRET_YAML))
secrets = load_yaml(secret_path)
if 'logger' in secrets:
logger = str(secrets['logger']).lower()
if logger == 'debug':
Expand All @@ -160,9 +164,11 @@ def _load_secret_yaml(secret_path: str) -> Dict:
_LOGGER.error("secrets.yaml: 'logger: debug' expected,"
" but 'logger: %s' found", logger)
del secrets['logger']
return secrets
except FileNotFoundError:
secrets = {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See line comment for 169

return {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unneeded return

__SECRET_CACHE[secret_path] = secrets
return secrets


# pylint: disable=protected-access
Expand All @@ -171,8 +177,8 @@ def _secret_yaml(loader: SafeLineLoader,
"""Load secrets and embed it into the configuration YAML."""
secret_path = os.path.dirname(loader.name)
while True:
secrets = __SECRET_CACHE.get(secret_path,
_load_secret_yaml(secret_path))
secrets = _load_secret_yaml(secret_path)

if node.value in secrets:
_LOGGER.debug('Secret %s retrieved from secrets.yaml in '
'folder %s', node.value, secret_path)
Expand Down
48 changes: 38 additions & 10 deletions tests/scripts/test_check_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@
)


def change_yaml_files(check_dict):
"""Change the ['yaml_files'] property and remove the config path.

Also removes other files like service.yaml that gets loaded
"""
root = get_test_config_dir()
keys = check_dict['yaml_files'].keys()
check_dict['yaml_files'] = []
for key in sorted(keys):
if not key.startswith('/'):
check_dict['yaml_files'].append(key)
if key.startswith(root):
check_dict['yaml_files'].append('...' + key[len(root):])


def tearDownModule(self): # pylint: disable=invalid-name
"""Clean files."""
# .HA_VERSION created during bootstrap's config update
Expand All @@ -39,12 +54,13 @@ def test_config_platform_valid(self):
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir('light.yaml'))
change_yaml_files(res)
self.assertDictEqual({
'components': {'light': [{'platform': 'hue'}]},
'except': {},
'secret_cache': {},
'secrets': {},
'yaml_files': {}
'yaml_files': ['.../light.yaml']
}, res)

def test_config_component_platform_fail_validation(self):
Expand All @@ -54,12 +70,13 @@ def test_config_component_platform_fail_validation(self):
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir('component.yaml'))
change_yaml_files(res)
self.assertDictEqual({
'components': {},
'except': {'http': {'password': 'err123'}},
'secret_cache': {},
'secrets': {},
'yaml_files': {}
'yaml_files': ['.../component.yaml']
}, res)

files = {
Expand All @@ -68,13 +85,14 @@ def test_config_component_platform_fail_validation(self):
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir('platform.yaml'))
change_yaml_files(res)
self.assertDictEqual({
'components': {'mqtt': {'keepalive': 60, 'port': 1883,
'protocol': '3.1.1'}},
'except': {'light.mqtt_json': {'platform': 'mqtt_json'}},
'secret_cache': {},
'secrets': {},
'yaml_files': {}
'yaml_files': ['.../platform.yaml']
}, res)

def test_component_platform_not_found(self):
Expand All @@ -85,42 +103,52 @@ def test_component_platform_not_found(self):
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir('badcomponent.yaml'))
change_yaml_files(res)
self.assertDictEqual({
'components': {},
'except': {check_config.ERROR_STR:
['Component not found: beer']},
'secret_cache': {},
'secrets': {},
'yaml_files': {}
'yaml_files': ['.../badcomponent.yaml']
}, res)

res = check_config.check(get_test_config_dir('badplatform.yaml'))
change_yaml_files(res)
self.assertDictEqual({
'components': {},
'except': {check_config.ERROR_STR:
['Platform not found: light.beer']},
'secret_cache': {},
'secrets': {},
'yaml_files': {}
'yaml_files': ['.../badplatform.yaml']
}, res)

def test_secrets(self):
"""Test secrets config checking method."""
files = {
'secret.yaml': (BASE_CONFIG +
'http:\n'
' api_password: !secret http_pw'),
get_test_config_dir('secret.yaml'): (
BASE_CONFIG +
'http:\n'
' api_password: !secret http_pw'),
'secrets.yaml': ('logger: debug\n'
'http_pw: abc123'),
}
self.maxDiff = None

with patch_yaml_files(files):
res = check_config.check(get_test_config_dir('secret.yaml'))
change_yaml_files(res)

# convert secrets OrderedDict to dict for assertequal
for key, val in res['secret_cache'].items():
res['secret_cache'][key] = dict(val)

self.assertDictEqual({
'components': {'http': {'api_password': 'abc123',
'server_port': 8123}},
'except': {},
'secret_cache': {},
'secret_cache': {'secrets.yaml': {'http_pw': 'abc123'}},
'secrets': {'http_pw': 'abc123'},
'yaml_files': {'secrets.yaml': True}
'yaml_files': ['.../secret.yaml', 'secrets.yaml']
}, res)