8000 Add namecheap DNS component by Munsio · Pull Request #9821 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add namecheap DNS component #9821

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 4 commits into from
Oct 13, 2017
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
76 changes: 76 additions & 0 deletions homeassistant/components/namecheapdns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""Integrate with NamecheapDNS."""
import asyncio
from datetime import timedelta
import logging

import voluptuous as vol

from homeassistant.const import CONF_HOST, CONF_ACCESS_TOKEN, CONF_DOMAIN
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.aiohttp_client import async_get_clientsession

DOMAIN = 'namecheapdns'
UPDATE_URL = 'https://dynamicdns.park-your-domain.com/update'
INTERVAL = timedelta(minutes=5)
_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
Copy link
Member

Choose a reason for hiding this comment

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

This should be optional (requiring a @ as a placeholder seems odd) and please rename it to subdomain.

Copy link
Member
@fabaff fabaff Oct 13, 2017

Choose a reason for hiding this comment

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

A little more context: @ is a sigil characters which was reserved in YAML for future usage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The @ is not a placeholder, its the char namecheap dyn dns is used to set the ip for the TLD domain itself in example "example.com" - should i put it in " ?

Copy link
Member

Choose a reason for hiding this comment

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

If you don't use a subdomain then it should be optional.

vol.Required(CONF_DOMAIN): cv.string,
vol.Required(CONF_ACCESS_TOKEN): cv.string,
})
}, extra=vol.ALLOW_EXTRA)


@asyncio.coroutine
def async_setup(hass, config):
"""Initialize the NamecheapDNS component."""
host = config[DOMAIN][CONF_HOST]
domain = config[DOMAIN][CONF_DOMAIN]
token = config[DOMAIN][CONF_ACCESS_TOKEN]
session = async_get_clientsession(hass)

result = yield from _update_namecheapdns(session, host, domain, token)

if not result:
return False

@asyncio.coroutine
def update_domain_interval(now):
"""Update the NamecheapDNS entry."""
yield from _update_namecheapdns(session, host, domain, token)

@asyncio.coroutine
def update_domain_service(call):
"""Update the NamecheapDNS entry."""
yield from _update_namecheapdns(session, host, domain, token)

async_track_time_interval(hass, update_domain_interval, INTERVAL)
hass.services.async_register(DOMAIN, 'update dns', update_domain_service)

return result


@asyncio.coroutine
def _update_namecheapdns(session, host, domain, token):
"""Update NamecheapDNS."""
import xml.etree.ElementTree as ET

params = {
'host': host,
'domain': domain,
'password': token,
}

resp = yield from session.get(UPDATE_URL, params=params)
xml_string = yield from resp.text()
root = ET.fromstring(xml_string)
err_count = root.find('ErrCount').text

if int(err_count) != 0:
_LOGGER.warning('Updating Namecheap domain %s failed', domain)
return False

return True
78 changes: 78 additions & 0 deletions tests/components/test_namecheapdns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Test the NamecheapDNS component."""
import asyncio
from datetime import timedelta

import pytest

from homeassistant.setup import async_setup_component
from homeassistant.components import namecheapdns
from homeassistant.util.dt import utcnow

from tests.common import async_fire_time_changed

HOST = 'test'
DOMAIN = 'bla'
TOKEN = 'abcdefgh'


@pytest.fixture
def setup_namecheapdns(hass, aioclient_mock):
"""Fixture that sets up NamecheapDNS."""
aioclient_mock.get(namecheapdns.UPDATE_URL, params={
'host': HOST,
'domain': DOMAIN,
'password': TOKEN
}, text='<interface-response><ErrCount>0</ErrCount></interface-response>')

hass.loop.run_until_complete(async_setup_component(
hass, namecheapdns.DOMAIN, {
'namecheapdns': {
'host': HOST,
'domain': DOMAIN,
'access_token': TOKEN
}
}))


@asyncio.coroutine
def test_setup(hass, aioclient_mock):
"""Test setup works if update passes."""
aioclient_mock.get(namecheapdns.UPDATE_URL, params={
'host': HOST,
'domain': DOMAIN,
'password': TOKEN
}, text='<interface-response><ErrCount>0</ErrCount></interface-response>')

result = yield from async_setup_component(hass, namecheapdns.DOMAIN, {
'namecheapdns': {
'host': HOST,
'domain': DOMAIN,
'access_token': TOKEN
}
})
assert result
assert aioclient_mock.call_count == 1

async_fire_time_changed(hass, utcnow() + timedelta(minutes=5))
yield from hass.async_block_till_done()
assert aioclient_mock.call_count == 2


@asyncio.coroutine
def test_setup_fails_if_update_fails(hass, aioclient_mock):
"""Test setup fails if first update fails."""
aioclient_mock.get(namecheapdns.UPDATE_URL, params={
'host': HOST,
'domain': DOMAIN,
'password': TOKEN
}, text='<interface-response><ErrCount>1</ErrCount></interface-response>')

result = yield from async_setup_component(hass, namecheapdns.DOMAIN, {
'namecheapdns': {
'host': HOST,
'domain': DOMAIN,
'access_token': TOKEN
}
})
assert not result
assert aioclient_mock.call_count == 1
0