8000 Voluptuous for AsusWRT by kellerza · Pull Request #2998 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Voluptuous for AsusWRT #2998

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

Merged
merged 3 commits into from
Aug 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
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
46 changes: 29 additions & 17 deletions homeassistant/components/device_tracker/asuswrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,36 @@
from collections import namedtuple
from datetime import timedelta

from homeassistant.components.device_tracker import DOMAIN
import voluptuous as vol

from homeassistant.components.device_tracker import DOMAIN, PLATFORM_SCHEMA
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import validate_config
from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv

# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)

CONF_PROTOCOL = 'protocol'
CONF_MODE = 'mode'
CONF_SSH_KEY = 'ssh_key'
CONF_PUB_KEY = 'pub_key'

PLATFORM_SCHEMA = vol.All(
cv.has_at_least_one_key(CONF_PASSWORD, CONF_PUB_KEY, CONF_SSH_KEY),
PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_PROTOCOL, default='ssh'):
vol.Schema(['ssh', 'telnet']),
vol.Optional(CONF_MODE, default='router'):
vol.Schema(['router', 'ap']),
vol.Optional(CONF_SSH_KEY): cv.isfile,
vol.Optional(CONF_PUB_KEY): cv.isfile
}))


_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pexpect==4.0.1']

Expand Down Expand Up @@ -57,16 +79,6 @@
# pylint: disable=unused-argument
def get_scanner(hass, config):
"""Validate the configuration and return an ASUS-WRT scanner."""
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME]},
_LOGGER):
return None
elif CONF_PASSWORD not in config[DOMAIN] and \
'ssh_key' not in config[DOMAIN] and \
'pub_key' not in config[DOMAIN]:
_LOGGER.error('Either a private key or password must be provided')
return None

scanner = AsusWrtDeviceScanner(config[DOMAIN])

return scanner if scanner.success_init else None
Expand All @@ -83,11 +95,11 @@ class AsusWrtDeviceScanner(object):
def __init__(self, config):
"""Initialize the scanner."""
self.host = config[CONF_HOST]
self.username = str(config[CONF_USERNAME])
self.password = str(config.get(CONF_PASSWORD, ''))
self.ssh_key = str(config.get('ssh_key', config.get('pub_key', '')))
self.protocol = config.get('protocol')
self.mode = config.get('mode')
self.username = config[CONF_USERNAME]
self.password = config.get(CONF_PASSWORD, '')
self.ssh_key = config.get('ssh_key', config.get('pub_key', ''))
self.protocol = config[CONF_PROTOCOL]
self.mode = config[CONF_MODE]

self.lock = threading.Lock()

Expand Down
108 changes: 71 additions & 37 deletions tests/components/device_tracker/test_asuswrt.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@
"""The tests for the ASUSWRT device tracker platform."""

import os
import unittest
from unittest import mock

import voluptuous as vol

from homeassistant.bootstrap import _setup_component
from homeassistant.components import device_tracker
from homeassistant.components.device_tracker.asuswrt import (
CONF_PROTOCOL, CONF_MODE, CONF_PUB_KEY, PLATFORM_SCHEMA, DOMAIN)
from homeassistant.const import (CONF_PLATFORM, CONF_PASSWORD, CONF_USERNAME,
CONF_HOST)

from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, get_test_config_dir

FAKEFILE = None


def setup_module():
"""Setup the test module."""
global FAKEFILE
FAKEFILE = get_test_config_dir('fake_file')
with open(FAKEFILE, 'w') as out:
out.write(' ')


def teardown_module():
"""Tear down the module."""
os.remove(FAKEFILE)


class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase):
"""Tests for the ASUSWRT device tracker platform."""
hass = None

def setUp(self): # pylint: disable=invalid-name
def setup_method(self, _):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = ['zone']

def tearDown(self): # pylint: disable=invalid-name
def teardown_method(self, _):
"""Stop everything that was started."""
try:
os.remove(self.hass.config.path(device_tracker.YAML_DEVICES))
except FileNotFoundError:
pass

def test_password_or_pub_key_required(self):
def test_password_or_pub_key_required(self): \
# pylint: disable=invalid-name
"""Test creating an AsusWRT scanner without a pass or pubkey."""
self.assertIsNone(device_tracker.asuswrt.get_scanner(
self.hass, {device_tracker.DOMAIN: {
self.assertFalse(_setup_component(
self.hass, DOMAIN, {DOMAIN: {
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user'
Expand All @@ -37,49 +59,55 @@ def test_password_or_pub_key_required(self):
@mock.patch(
'homeassistant.components.device_tracker.asuswrt.AsusWrtDeviceScanner',
return_value=mock.MagicMock())
def test_get_scanner_with_password_no_pubkey(self, asuswrt_mock):
def test_get_scanner_with_password_no_pubkey(self, asuswrt_mock): \
# pylint: disable=invalid-name
"""Test creating an AsusWRT scanner with a password and no pubkey."""
conf_dict = {
device_tracker.DOMAIN: {
DOMAIN: {
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
CONF_PASSWORD: 'fake_pass'
}
}
self.assertIsNotNone(device_tracker.asuswrt.get_scanner(
self.hass, conf_dict))
asuswrt_mock.assert_called_once_with(conf_dict[device_tracker.DOMAIN])
self.assertIsNotNone(_setup_component(self.hass, DOMAIN, conf_dict))
conf_dict[DOMAIN][CONF_MODE] = 'router'
conf_dict[DOMAIN][CONF_PROTOCOL] = 'ssh'
asuswrt_mock.assert_called_once_with(conf_dict[DOMAIN])

@mock.patch(
'homeassistant.components.device_tracker.asuswrt.AsusWrtDeviceScanner',
return_value=mock.MagicMock())
def test_get_scanner_with_pubkey_no_password(self, asuswrt_mock):
def test_get_scanner_with_pubkey_no_password(self, asuswrt_mock): \
# pylint: disable=invalid-name
"""Test creating an AsusWRT scanner with a pubkey and no password."""
conf_dict = {
device_tracker.DOMAIN: {
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
'pub_key': '/fake_path'
CONF_PUB_KEY: FAKEFILE
}
}
self.assertIsNotNone(device_tracker.asuswrt.get_scanner(
self.hass, conf_dict))
asuswrt_mock.assert_called_once_with(conf_dict[device_tracker.DOMAIN])

self.assertIsNotNone(_setup_component(self.hass, DOMAIN, conf_dict))

conf_dict[DOMAIN][CONF_MODE] = 'router'
conf_dict[DOMAIN][CONF_PROTOCOL] = 'ssh'
asuswrt_mock.assert_called_once_with(conf_dict[DOMAIN])

def test_ssh_login_with_pub_key(self):
"""Test that login is done with pub_key when configured to."""
ssh = mock.MagicMock()
ssh_mock = mock.patch('pexpect.pxssh.pxssh', return_value=ssh)
ssh_mock.start()
self.addCleanup(ssh_mock.stop)
conf_dict = {
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
'pub_key': '/fake_path'
}
conf_dict = PLATFORM_SCHEMA({
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
CONF_PUB_KEY: FAKEFILE
})
update_mock = mock.patch(
'homeassistant.components.device_tracker.asuswrt.'
'AsusWrtDeviceScanner.get_asuswrt_data')
Expand All @@ -88,20 +116,20 @@ def test_ssh_login_with_pub_key(self):
asuswrt = device_tracker.asuswrt.AsusWrtDeviceScanner(conf_dict)
asuswrt.ssh_connection()
ssh.login.assert_called_once_with('fake_host', 'fake_user',
ssh_key='/fake_path')
ssh_key=FAKEFILE)

def test_ssh_login_with_password(self):
"""Test that login is done with password when configured to."""
ssh = mock.MagicMock()
ssh_mock = mock.patch('pexpect.pxssh.pxssh', return_value=ssh)
ssh_mock.start()
self.addCleanup(ssh_mock.stop)
conf_dict = {
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
CONF_PASSWORD: 'fake_pass'
}
conf_dict = PLATFORM_SCHEMA({
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
CONF_PASSWORD: 'fake_pass'
})
update_mock = mock.patch(
'homeassistant.components.device_tracker.asuswrt.'
'AsusWrtDeviceScanner.get_asuswrt_data')
Expand All @@ -112,23 +140,29 @@ def test_ssh_login_with_password(self):
ssh.login.assert_called_once_with('fake_host', 'fake_user',
'fake_pass')

def test_ssh_login_without_password_or_pubkey(self):
def test_ssh_login_without_password_or_pubkey(self): \
# pylint: disable=invalid-name
"""Test that login is not called without password or pub_key."""
ssh = mock.MagicMock()
ssh_mock = mock.patch('pexpect.pxssh.pxssh', return_value=ssh)
ssh_mock.start()
self.addCleanup(ssh_mock.stop)

conf_dict = {
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
CONF_PLATFORM: 'asuswrt',
CONF_HOST: 'fake_host',
CONF_USERNAME: 'fake_user',
}

with self.assertRaises(vol.Invalid):
conf_dict = PLATFORM_SCHEMA(conf_dict)

update_mock = mock.patch(
'homeassistant.components.device_tracker.asuswrt.'
'AsusWrtDeviceScanner.get_asuswrt_data')
update_mock.start()
self.addCleanup(update_mock.stop)
asuswrt = device_tracker.asuswrt.AsusWrtDeviceScanner(conf_dict)
result = asuswrt.ssh_connection()

self.assertFalse(_setup_component(self.hass, DOMAIN,
{DOMAIN: conf_dict}))
ssh.login.assert_not_called()
self.assertIsNone(result)
0