mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Add OVH as octodns provider
This commit is contained in:
@@ -154,6 +154,7 @@ The above command pulled the existing data out of Route53 and placed the results
|
||||
| [DnsimpleProvider](/octodns/provider/dnsimple.py) | All | No | CAA tags restricted |
|
||||
| [DynProvider](/octodns/provider/dyn.py) | All | Yes | |
|
||||
| [Ns1Provider](/octodns/provider/ns1.py) | All | No | |
|
||||
| [OVH](/octodns/provider/ovh.py) | A, AAAA, CNAME, MX, NAPTR, NS, PTR, SPF, SRV, SSHFP, TXT | No | |
|
||||
| [PowerDnsProvider](/octodns/provider/powerdns.py) | All | No | |
|
||||
| [Route53](/octodns/provider/route53.py) | A, AAAA, CAA, CNAME, MX, NAPTR, NS, PTR, SPF, SRV, TXT | Yes | |
|
||||
| [TinyDNSSource](/octodns/source/tinydns.py) | A, CNAME, MX, NS, PTR | No | read-only |
|
||||
|
||||
322
octodns/provider/ovh.py
Normal file
322
octodns/provider/ovh.py
Normal file
@@ -0,0 +1,322 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import absolute_import, division, print_function, \
|
||||
unicode_literals
|
||||
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
|
||||
import ovh
|
||||
|
||||
from octodns.record import Record
|
||||
from .base import BaseProvider
|
||||
|
||||
|
||||
class OvhProvider(BaseProvider):
|
||||
"""
|
||||
OVH provider using API v6
|
||||
|
||||
ovh:
|
||||
class: octodns.provider.ovh.OvhProvider
|
||||
# OVH api v6 endpoint
|
||||
endpoint: ovh-eu
|
||||
# API application key
|
||||
application_key: 1234
|
||||
# API application secret
|
||||
application_secret: 1234
|
||||
# API consumer key
|
||||
consumer_key: 1234
|
||||
"""
|
||||
|
||||
SUPPORTS_GEO = False
|
||||
|
||||
SUPPORTS = set(('A', 'AAAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF',
|
||||
'SRV', 'SSHFP', 'TXT'))
|
||||
|
||||
def __init__(self, id, endpoint, application_key, application_secret,
|
||||
consumer_key, *args, **kwargs):
|
||||
self.log = logging.getLogger('OvhProvider[{}]'.format(id))
|
||||
self.log.debug('__init__: id=%s, endpoint=%s, application_key=%s, '
|
||||
'application_secret=***, consumer_key=%s', id, endpoint,
|
||||
application_key, consumer_key)
|
||||
super(OvhProvider, self).__init__(id, *args, **kwargs)
|
||||
self._client = ovh.Client(
|
||||
endpoint=endpoint,
|
||||
application_key=application_key,
|
||||
application_secret=application_secret,
|
||||
consumer_key=consumer_key,
|
||||
)
|
||||
|
||||
def populate(self, zone, target=False, lenient=False):
|
||||
self.log.debug('populate: name=%s, target=%s, lenient=%s', zone.name,
|
||||
target, lenient)
|
||||
zone_name = zone.name[:-1]
|
||||
records = self.get_records(zone_name=zone_name)
|
||||
|
||||
values = defaultdict(lambda: defaultdict(list))
|
||||
for record in records:
|
||||
values[record['subDomain']][record['fieldType']].append(record)
|
||||
|
||||
before = len(zone.records)
|
||||
for name, types in values.items():
|
||||
for _type, records in types.items():
|
||||
data_for = getattr(self, '_data_for_{}'.format(_type))
|
||||
record = Record.new(zone, name, data_for(_type, records),
|
||||
source=self, lenient=lenient)
|
||||
zone.add_record(record)
|
||||
|
||||
self.log.info('populate: found %s records',
|
||||
len(zone.records) - before)
|
||||
|
||||
def _apply(self, plan):
|
||||
desired = plan.desired
|
||||
changes = plan.changes
|
||||
zone_name = desired.name[:-1]
|
||||
self.log.info('_apply: zone=%s, len(changes)=%d', desired.name,
|
||||
len(changes))
|
||||
for change in changes:
|
||||
class_name = change.__class__.__name__
|
||||
getattr(self, '_apply_{}'.format(class_name).lower())(zone_name,
|
||||
change)
|
||||
|
||||
# We need to refresh the zone to really apply the changes
|
||||
self._client.post('/domain/zone/{}/refresh'.format(zone_name))
|
||||
|
||||
def _apply_create(self, zone_name, change):
|
||||
new = change.new
|
||||
params_for = getattr(self, '_params_for_{}'.format(new._type))
|
||||
for params in params_for(new):
|
||||
self.create_record(zone_name, params)
|
||||
|
||||
def _apply_update(self, zone_name, change):
|
||||
self._apply_delete(zone_name, change)
|
||||
self._apply_create(zone_name, change)
|
||||
|
||||
def _apply_delete(self, zone_name, change):
|
||||
existing = change.existing
|
||||
self.delete_records(zone_name, existing._type, existing.name)
|
||||
|
||||
@staticmethod
|
||||
def _data_for_multiple(_type, records):
|
||||
return {
|
||||
'ttl': records[0]['ttl'],
|
||||
'type': _type,
|
||||
'values': [record['target'] for record in records]
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _data_for_single(_type, records):
|
||||
record = records[0]
|
||||
return {
|
||||
'ttl': record['ttl'],
|
||||
'type': _type,
|
||||
'value': record['target']
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _data_for_MX(_type, records):
|
||||
values = []
|
||||
for record in records:
|
||||
preference, exchange = record['target'].split(' ', 1)
|
||||
values.append({
|
||||
'preference': preference,
|
||||
'exchange': exchange,
|
||||
})
|
||||
return {
|
||||
'ttl': records[0]['ttl'],
|
||||
'type': _type,
|
||||
'values': values,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _data_for_NAPTR(_type, records):
|
||||
values = []
|
||||
for record in records:
|
||||
order, preference, flags, service, regexp, replacement = record[
|
||||
'target'].split(' ', 5)
|
||||
values.append({
|
||||
'flags': flags[1:-1],
|
||||
'order': order,
|
||||
'preference': preference,
|
||||
'regexp': regexp[1:-1],
|
||||
'replacement': replacement,
|
||||
'service': service[1:-1],
|
||||
})
|
||||
return {
|
||||
'type': _type,
|
||||
'ttl': records[0]['ttl'],
|
||||
'values': values
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _data_for_SRV(_type, records):
|
||||
values = []
|
||||
for record in records:
|
||||
priority, weight, port, target = record['target'].split(' ', 3)
|
||||
values.append({
|
||||
'port': port,
|
||||
'priority': priority,
|
||||
'target': '{}.'.format(target),
|
||||
'weight': weight
|
||||
})
|
||||
return {
|
||||
'type': _type,
|
||||
'ttl': records[0]['ttl'],
|
||||
'values': values
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _data_for_SSHFP(_type, records):
|
||||
values = []
|
||||
for record in records:
|
||||
algorithm, fingerprint_type, fingerprint = record['target'].split(
|
||||
' ', 2)
|
||||
values.append({
|
||||
'algorithm': algorithm,
|
||||
'fingerprint': fingerprint,
|
||||
'fingerprint_type': fingerprint_type
|
||||
})
|
||||
return {
|
||||
'type': _type,
|
||||
'ttl': records[0]['ttl'],
|
||||
'values': values
|
||||
}
|
||||
|
||||
_data_for_A = _data_for_multiple
|
||||
_data_for_AAAA = _data_for_multiple
|
||||
_data_for_NS = _data_for_multiple
|
||||
_data_for_TXT = _data_for_multiple
|
||||
_data_for_SPF = _data_for_multiple
|
||||
_data_for_PTR = _data_for_single
|
||||
_data_for_CNAME = _data_for_single
|
||||
|
||||
@staticmethod
|
||||
def _params_for_multiple(record):
|
||||
for value in record.values:
|
||||
yield {
|
||||
'target': value,
|
||||
'subDomain': record.name,
|
||||
'ttl': record.ttl,
|
||||
'fieldType': record._type,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _params_for_single(record):
|
||||
yield {
|
||||
'target': record.value,
|
||||
'subDomain': record.name,
|
||||
'ttl': record.ttl,
|
||||
'fieldType': record._type
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _params_for_MX(record):
|
||||
for value in record.values:
|
||||
yield {
|
||||
'target': '%d %s' % (value.preference, value.exchange),
|
||||
'subDomain': record.name,
|
||||
'ttl': record.ttl,
|
||||
'fieldType': record._type
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _params_for_NAPTR(record):
|
||||
for value in record.values:
|
||||
content = '{} {} "{}" "{}" "{}" {}' \
|
||||
.format(value.order, value.preference, value.flags,
|
||||
value.service, value.regexp, value.replacement)
|
||||
yield {
|
||||
'target': content,
|
||||
'subDomain': record.name,
|
||||
'ttl': record.ttl,
|
||||
'fieldType': record._type
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _params_for_SRV(record):
|
||||
for value in record.values:
|
||||
yield {
|
||||
'subDomain': '{} {} {} {}'.format(value.priority,
|
||||
value.weight, value.port,
|
||||
value.target),
|
||||
'target': record.name,
|
||||
'ttl': record.ttl,
|
||||
'fieldType': record._type
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _params_for_SSHFP(record):
|
||||
for value in record.values:
|
||||
yield {
|
||||
'subDomain': '{} {} {}'.format(value.algorithm,
|
||||
value.fingerprint_type,
|
||||
value.fingerprint),
|
||||
'target': record.name,
|
||||
'ttl': record.ttl,
|
||||
'fieldType': record._type
|
||||
}
|
||||
|
||||
_params_for_A = _params_for_multiple
|
||||
_params_for_AAAA = _params_for_multiple
|
||||
_params_for_NS = _params_for_multiple
|
||||
_params_for_SPF = _params_for_multiple
|
||||
_params_for_TXT = _params_for_multiple
|
||||
|
||||
_params_for_CNAME = _params_for_single
|
||||
_params_for_PTR = _params_for_single
|
||||
|
||||
def get_records(self, zone_name):
|
||||
"""
|
||||
List all records of a DNS zone
|
||||
:param zone_name: Name of zone
|
||||
:return: list of id's records
|
||||
"""
|
||||
records = self._client.get('/domain/zone/{}/record'.format(zone_name))
|
||||
return [self.get_record(zone_name, record_id) for record_id in records]
|
||||
|
||||
def get_record(self, zone_name, record_id):
|
||||
"""
|
||||
Get record with given id
|
||||
:param zone_name: Name of the zone
|
||||
:param record_id: Id of the record
|
||||
:return: Value of the record
|
||||
"""
|
||||
return self._client.get(
|
||||
'/domain/zone/{}/record/{}'.format(zone_name, record_id))
|
||||
|
||||
def delete_records(self, zone_name, record_type, subdomain):
|
||||
"""
|
||||
Delete record from have fieldType=type and subDomain=subdomain
|
||||
:param zone_name: Name of the zone
|
||||
:param record_type: fieldType
|
||||
:param subdomain: subDomain
|
||||
"""
|
||||
records = self._client.get('/domain/zone/{}/record'.format(zone_name),
|
||||
fieldType=record_type, subDomain=subdomain)
|
||||
for record in records:
|
||||
self.delete_record(zone_name, record)
|
||||
|
||||
def delete_record(self, zone_name, record_id):
|
||||
"""
|
||||
Delete record with a given id
|
||||
:param zone_name: Name of the zone
|
||||
:param record_id: Id of the record
|
||||
"""
|
||||
self.log.debug('Delete record: zone: %s, id %s', zone_name,
|
||||
record_id)
|
||||
self._client.delete(
|
||||
'/domain/zone/{}/record/{}'.format(zone_name, record_id))
|
||||
|
||||
def create_record(self, zone_name, params):
|
||||
"""
|
||||
Create a record
|
||||
:param zone_name: Name of the zone
|
||||
:param params: {'fieldType': 'A', 'ttl': 60, 'subDomain': 'www',
|
||||
'target': '1.2.3.4'
|
||||
"""
|
||||
self.log.debug('Create record: zone: %s, id %s', zone_name,
|
||||
params)
|
||||
return self._client.post('/domain/zone/{}/record'.format(zone_name),
|
||||
**params)
|
||||
@@ -15,6 +15,7 @@ jmespath==0.9.3
|
||||
msrestazure==0.4.10
|
||||
natsort==5.0.3
|
||||
nsone==0.9.14
|
||||
ovh==0.4.7
|
||||
python-dateutil==2.6.1
|
||||
requests==2.13.0
|
||||
s3transfer==0.1.10
|
||||
|
||||
359
tests/test_octodns_provider_ovh.py
Normal file
359
tests/test_octodns_provider_ovh.py
Normal file
@@ -0,0 +1,359 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import absolute_import, division, print_function, \
|
||||
unicode_literals
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from mock import patch, call
|
||||
from ovh import APIError
|
||||
|
||||
from octodns.provider.ovh import OvhProvider
|
||||
from octodns.record import Record
|
||||
from octodns.zone import Zone
|
||||
|
||||
|
||||
class TestOvhProvider(TestCase):
|
||||
api_record = []
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
expected = set()
|
||||
|
||||
# A, subdomain=''
|
||||
api_record.append({
|
||||
'fieldType': 'A',
|
||||
'ttl': 100,
|
||||
'target': '1.2.3.4',
|
||||
'subDomain': '',
|
||||
'id': 1
|
||||
})
|
||||
expected.add(Record.new(zone, '', {
|
||||
'ttl': 100,
|
||||
'type': 'A',
|
||||
'value': '1.2.3.4',
|
||||
}))
|
||||
|
||||
# A, subdomain='sub
|
||||
api_record.append({
|
||||
'fieldType': 'A',
|
||||
'ttl': 200,
|
||||
'target': '1.2.3.4',
|
||||
'subDomain': 'sub',
|
||||
'id': 2
|
||||
})
|
||||
expected.add(Record.new(zone, 'sub', {
|
||||
'ttl': 200,
|
||||
'type': 'A',
|
||||
'value': '1.2.3.4',
|
||||
}))
|
||||
|
||||
# CNAME
|
||||
api_record.append({
|
||||
'fieldType': 'CNAME',
|
||||
'ttl': 300,
|
||||
'target': 'unit.tests.',
|
||||
'subDomain': 'www2',
|
||||
'id': 3
|
||||
})
|
||||
expected.add(Record.new(zone, 'www2', {
|
||||
'ttl': 300,
|
||||
'type': 'CNAME',
|
||||
'value': 'unit.tests.',
|
||||
}))
|
||||
|
||||
# MX
|
||||
api_record.append({
|
||||
'fieldType': 'MX',
|
||||
'ttl': 400,
|
||||
'target': '10 mx1.unit.tests.',
|
||||
'subDomain': '',
|
||||
'id': 4
|
||||
})
|
||||
expected.add(Record.new(zone, '', {
|
||||
'ttl': 400,
|
||||
'type': 'MX',
|
||||
'values': [{
|
||||
'preference': 10,
|
||||
'exchange': 'mx1.unit.tests.',
|
||||
}]
|
||||
}))
|
||||
|
||||
# NAPTR
|
||||
api_record.append({
|
||||
'fieldType': 'NAPTR',
|
||||
'ttl': 500,
|
||||
'target': '10 100 "S" "SIP+D2U" "!^.*$!sip:info@bar.example.com!" .',
|
||||
'subDomain': 'naptr',
|
||||
'id': 5
|
||||
})
|
||||
expected.add(Record.new(zone, 'naptr', {
|
||||
'ttl': 500,
|
||||
'type': 'NAPTR',
|
||||
'values': [{
|
||||
'flags': 'S',
|
||||
'order': 10,
|
||||
'preference': 100,
|
||||
'regexp': '!^.*$!sip:info@bar.example.com!',
|
||||
'replacement': '.',
|
||||
'service': 'SIP+D2U',
|
||||
}]
|
||||
}))
|
||||
|
||||
# NS
|
||||
api_record.append({
|
||||
'fieldType': 'NS',
|
||||
'ttl': 600,
|
||||
'target': 'ns1.unit.tests.',
|
||||
'subDomain': '',
|
||||
'id': 6
|
||||
})
|
||||
api_record.append({
|
||||
'fieldType': 'NS',
|
||||
'ttl': 600,
|
||||
'target': 'ns2.unit.tests.',
|
||||
'subDomain': '',
|
||||
'id': 7
|
||||
})
|
||||
expected.add(Record.new(zone, '', {
|
||||
'ttl': 600,
|
||||
'type': 'NS',
|
||||
'values': ['ns1.unit.tests.', 'ns2.unit.tests.'],
|
||||
}))
|
||||
|
||||
# NS with sub
|
||||
api_record.append({
|
||||
'fieldType': 'NS',
|
||||
'ttl': 700,
|
||||
'target': 'ns3.unit.tests.',
|
||||
'subDomain': 'www3',
|
||||
'id': 8
|
||||
})
|
||||
api_record.append({
|
||||
'fieldType': 'NS',
|
||||
'ttl': 700,
|
||||
'target': 'ns4.unit.tests.',
|
||||
'subDomain': 'www3',
|
||||
'id': 9
|
||||
})
|
||||
expected.add(Record.new(zone, 'www3', {
|
||||
'ttl': 700,
|
||||
'type': 'NS',
|
||||
'values': ['ns3.unit.tests.', 'ns4.unit.tests.'],
|
||||
}))
|
||||
|
||||
api_record.append({
|
||||
'fieldType': 'SRV',
|
||||
'ttl': 800,
|
||||
'target': '10 20 30 foo-1.unit.tests.',
|
||||
'subDomain': '_srv._tcp',
|
||||
'id': 10
|
||||
})
|
||||
api_record.append({
|
||||
'fieldType': 'SRV',
|
||||
'ttl': 800,
|
||||
'target': '40 50 60 foo-2.unit.tests.',
|
||||
'subDomain': '_srv._tcp',
|
||||
'id': 11
|
||||
})
|
||||
expected.add(Record.new(zone, '_srv._tcp', {
|
||||
'ttl': 800,
|
||||
'type': 'SRV',
|
||||
'values': [{
|
||||
'priority': 10,
|
||||
'weight': 20,
|
||||
'port': 30,
|
||||
'target': 'foo-1.unit.tests.',
|
||||
}, {
|
||||
'priority': 40,
|
||||
'weight': 50,
|
||||
'port': 60,
|
||||
'target': 'foo-2.unit.tests.',
|
||||
}]
|
||||
}))
|
||||
|
||||
# PTR
|
||||
api_record.append({
|
||||
'fieldType': 'PTR',
|
||||
'ttl': 900,
|
||||
'target': 'unit.tests.',
|
||||
'subDomain': '4',
|
||||
'id': 12
|
||||
})
|
||||
expected.add(Record.new(zone, '4', {
|
||||
'ttl': 900,
|
||||
'type': 'PTR',
|
||||
'value': 'unit.tests.'
|
||||
}))
|
||||
|
||||
# SPF
|
||||
api_record.append({
|
||||
'fieldType': 'SPF',
|
||||
'ttl': 1000,
|
||||
'target': 'v=spf1 include:unit.texts.rerirect ~all',
|
||||
'subDomain': '',
|
||||
'id': 13
|
||||
})
|
||||
expected.add(Record.new(zone, '', {
|
||||
'ttl': 1000,
|
||||
'type': 'SPF',
|
||||
'value': 'v=spf1 include:unit.texts.rerirect ~all'
|
||||
}))
|
||||
|
||||
# SSHFP
|
||||
api_record.append({
|
||||
'fieldType': 'SSHFP',
|
||||
'ttl': 1100,
|
||||
'target': '1 1 bf6b6825d2977c511a475bbefb88aad54a92ac73 ',
|
||||
'subDomain': '',
|
||||
'id': 14
|
||||
})
|
||||
expected.add(Record.new(zone, '', {
|
||||
'ttl': 1100,
|
||||
'type': 'SSHFP',
|
||||
'value': {
|
||||
'algorithm': 1,
|
||||
'fingerprint': 'bf6b6825d2977c511a475bbefb88aad54a92ac73',
|
||||
'fingerprint_type': 1
|
||||
}
|
||||
}))
|
||||
|
||||
# AAAA
|
||||
api_record.append({
|
||||
'fieldType': 'AAAA',
|
||||
'ttl': 1200,
|
||||
'target': '1:1ec:1::1',
|
||||
'subDomain': '',
|
||||
'id': 15
|
||||
})
|
||||
expected.add(Record.new(zone, '', {
|
||||
'ttl': 200,
|
||||
'type': 'AAAA',
|
||||
'value': '1:1ec:1::1',
|
||||
}))
|
||||
|
||||
@patch('ovh.Client')
|
||||
def test_populate(self, client_mock):
|
||||
provider = OvhProvider('test', 'endpoint', 'application_key',
|
||||
'application_secret', 'consumer_key')
|
||||
|
||||
with patch.object(provider._client, 'get') as get_mock:
|
||||
zone = Zone('unit.tests.', [])
|
||||
get_mock.side_effect = APIError('boom')
|
||||
with self.assertRaises(APIError) as ctx:
|
||||
provider.populate(zone)
|
||||
self.assertEquals(get_mock.side_effect, ctx.exception)
|
||||
|
||||
with patch.object(provider._client, 'get') as get_mock:
|
||||
zone = Zone('unit.tests.', [])
|
||||
get_returns = [[record['id'] for record in self.api_record]]
|
||||
get_returns += self.api_record
|
||||
get_mock.side_effect = get_returns
|
||||
provider.populate(zone)
|
||||
self.assertEquals(self.expected, zone.records)
|
||||
|
||||
@patch('ovh.Client')
|
||||
def test_apply(self, client_mock):
|
||||
provider = OvhProvider('test', 'endpoint', 'application_key',
|
||||
'application_secret', 'consumer_key')
|
||||
|
||||
desired = Zone('unit.tests.', [])
|
||||
|
||||
for r in self.expected:
|
||||
desired.add_record(r)
|
||||
|
||||
with patch.object(provider._client, 'post') as get_mock:
|
||||
plan = provider.plan(desired)
|
||||
get_mock.side_effect = APIError('boom')
|
||||
with self.assertRaises(APIError) as ctx:
|
||||
provider.apply(plan)
|
||||
self.assertEquals(get_mock.side_effect, ctx.exception)
|
||||
|
||||
with patch.object(provider._client, 'get') as get_mock:
|
||||
get_returns = [[1, 2], {
|
||||
'fieldType': 'A',
|
||||
'ttl': 600,
|
||||
'target': '5.6.7.8',
|
||||
'subDomain': '',
|
||||
'id': 100
|
||||
}, {'fieldType': 'A',
|
||||
'ttl': 600,
|
||||
'target': '5.6.7.8',
|
||||
'subDomain': 'fake',
|
||||
'id': 101
|
||||
}]
|
||||
get_mock.side_effect = get_returns
|
||||
|
||||
plan = provider.plan(desired)
|
||||
|
||||
with patch.object(provider._client, 'post') as post_mock:
|
||||
with patch.object(provider._client, 'delete') as delete_mock:
|
||||
with patch.object(provider._client, 'get') as get_mock:
|
||||
get_mock.side_effect = [[100], [101]]
|
||||
provider.apply(plan)
|
||||
wanted_calls = [
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'A',
|
||||
subDomain=u'', target=u'1.2.3.4', ttl=100),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'SRV',
|
||||
subDomain=u'10 20 30 foo-1.unit.tests.',
|
||||
target='_srv._tcp', ttl=800),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'SRV',
|
||||
subDomain=u'40 50 60 foo-2.unit.tests.',
|
||||
target='_srv._tcp', ttl=800),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'PTR', subDomain='4',
|
||||
target=u'unit.tests.', ttl=900),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'NS', subDomain='www3',
|
||||
target=u'ns3.unit.tests.', ttl=700),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'NS', subDomain='www3',
|
||||
target=u'ns4.unit.tests.', ttl=700),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'SSHFP',
|
||||
subDomain=u'1 1 bf6b6825d2977c511a475bbefb88a'
|
||||
u'ad54'
|
||||
u'a92ac73',
|
||||
target=u'', ttl=1100),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'AAAA', subDomain=u'',
|
||||
target=u'1:1ec:1::1', ttl=200),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'MX', subDomain=u'',
|
||||
target=u'10 mx1.unit.tests.', ttl=400),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'CNAME', subDomain='www2',
|
||||
target=u'unit.tests.', ttl=300),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'SPF', subDomain=u'',
|
||||
target=u'v=spf1 include:unit.texts.'
|
||||
u'rerirect ~all',
|
||||
ttl=1000),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'A',
|
||||
subDomain='sub', target=u'1.2.3.4', ttl=200),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'NAPTR', subDomain='naptr',
|
||||
target=u'10 100 "S" "SIP+D2U" "!^.*$!sip:'
|
||||
u'info@bar'
|
||||
u'.example.com!" .',
|
||||
ttl=500),
|
||||
call(u'/domain/zone/unit.tests/refresh')]
|
||||
|
||||
post_mock.assert_has_calls(wanted_calls)
|
||||
|
||||
# Get for delete calls
|
||||
get_mock.assert_has_calls(
|
||||
[call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'A', subDomain=u''),
|
||||
call(u'/domain/zone/unit.tests/record',
|
||||
fieldType=u'A', subDomain='fake')]
|
||||
)
|
||||
# 2 delete calls, one for update + one for delete
|
||||
delete_mock.assert_has_calls(
|
||||
[call(u'/domain/zone/unit.tests/record/100'),
|
||||
call(u'/domain/zone/unit.tests/record/101')])
|
||||
Reference in New Issue
Block a user