def setUp(self): GandiLiveDNSDriver.connectionCls.conn_class = GandiLiveMockHttp GandiLiveMockHttp.type = None self.driver = GandiLiveDNSDriver(*DNS_GANDI_LIVE) self.test_zone = Zone(id='example.com', type='master', ttl=None, domain='example.com', extra={'zone_uuid': 'a53re'}, driver=self) self.test_bad_zone = Zone(id='badexample.com', type='master', ttl=None, domain='badexample.com', extra={'zone_uuid': 'a53rf'}, driver=self) self.test_record = Record(id='A:bob', type=RecordType.A, name='bob', zone=self.test_zone, data='127.0.0.1', driver=self, extra={}) self.test_bad_record = Record(id='A:jane', type=RecordType.A, name='jane', zone=self.test_bad_zone, data='127.0.0.1', driver=self, extra={})
def test_dns_update_record_zone_does_not_exist(dns_conn): name = "example.com" data = "ns10.vscale.io" zone = Zone("123", name, "master", ttl=None, driver=dns_conn) record = Record("111", name, RecordType.A, data, zone, dns_conn) with pytest.raises(ZoneDoesNotExistError, match="domain_not_found"): record.update(name=data)
def setUp(self): NFSNDNSDriver.connectionCls.conn_classes = (None, NFSNMockHttp) NFSNMockHttp.type = None self.driver = NFSNDNSDriver('testid', 'testsecret') self.test_zone = Zone(id='example.com', domain='example.com', driver=self.driver, type='master', ttl=None, extra={}) self.test_record = Record(id=None, name='', data='192.0.2.1', type=RecordType.A, zone=self.test_zone, driver=self.driver, extra={})
def _to_record(self, elem, zone): id = findtext(element=elem, xpath='id') name = findtext(element=elem, xpath='hostname') type = findtext(element=elem, xpath='host-type') type = self._string_to_record_type(type) data = findtext(element=elem, xpath='data') notes = findtext(element=elem, xpath='notes', no_text_value=None) state = findtext(element=elem, xpath='state', no_text_value=None) fqdn = findtext(element=elem, xpath='fqdn', no_text_value=None) priority = findtext(element=elem, xpath='priority', no_text_value=None) ttl = findtext(element=elem, xpath='ttl', no_text_value=None) if not name: name = None if ttl: ttl = int(ttl) extra = { 'notes': notes, 'state': state, 'fqdn': fqdn, 'priority': priority, 'ttl': ttl } record = Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, extra=extra) return record
def create_record(self, name, zone, type, data, extra=None): params = { "name": name, "type": self.RECORD_TYPE_MAP[type], "domain_id": zone.id, "content": data, } merged = merge_valid_keys(params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) self.connection.set_context({"resource": "zone", "id": zone.id}) result = self.connection.request(API_ROOT + "/dns/record/", data=json.dumps(params), method="POST").object record = Record( id=result["id"], name=name, type=type, data=data, extra=merged, zone=zone, ttl=merged.get("ttl", None), driver=self, ) return record
def _to_record(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) record = data.get("record") id = record.get("id") name = record.get("name") type = record.get("record_type") data = record.get("content") extra = { "ttl": record.get("ttl"), "created_at": record.get("created_at"), "updated_at": record.get("updated_at"), "domain_id": record.get("domain_id"), "priority": record.get("prio"), } return Record( id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=record.get("ttl", None), extra=extra, )
def _to_record(self, data, zone=None): extra = {'port': data['port'], 'priority': data['priority'], 'weight': data['weight']} return Record(id=data['id'], name=data['name'], type=self._string_to_record_type(data['type']), data=data['data'], zone=zone, ttl=data.get('ttl', None), driver=self, extra=extra)
def test_handles_missing_record(self): action = DeleteMxRecords('my-user', 'my-key', provider='CLOUDFLARE') with patch.object(action, '_driver', new_callable=PropertyMock) as mock_driver: zones = [ Zone(id='2', domain='my-zone', type='master', ttl=1, driver=mock_driver), ] records = [ Record(id='1', name='bar', type=RecordType.A, data='', zone=zones[0], ttl=1, driver=mock_driver), ] mock_driver.iterate_zones.return_value = zones mock_driver.iterate_records.return_value = records action('my-domain.my-zone') self.assertEqual(mock_driver.iterate_zones.call_count, 1) self.assertEqual(mock_driver.iterate_records.call_count, 1) self.assertEqual(mock_driver.delete_record.call_count, 0)
def _to_record(self, item, zone): """Converts a DNSMadeEasy record response item to a ``Record`` instance. :param dict item: The response item. :param libcloud.dns.base.Zone zone: The zone to which the record belongs. :return: a record :rtype: libcloud.dns.base.Record """ extra = { key: value for key, value in item.items() if not key in ('id', 'name', 'type', 'value') } extra['fqdn'] = self._to_full_record_name(zone.domain, item['name']) return Record(id=str(item['id']), name=self._to_partial_record_name(item['name']), type=item['type'].upper(), data=item['value'], zone=zone, driver=self, extra=extra)
def get_record(self, zone_id: str, record_id: str): response = self.connection.request( f"v1/domains/{zone_id}/records/{record_id}") result = response.object result_id = str(result.pop("id")) name = result.pop("name") result_type = result.pop("type") data = result.pop("content") ttl = result.pop("ttl", None) extra = result zone = self.get_zone(zone_id) record = Record( id=result_id, name=name, type=result_type, data=data, zone=zone, driver=self, ttl=ttl, extra=extra, ) return record
def list_records(self, zone: Zone) -> List[Record]: response = self.connection.request(f"v1/domains/{zone.id}/records/") result = response.object records = [] for r in result: zone_id = r.pop("id") name = r.pop("name") record_type = r.pop("type") data = r.pop("content") ttl = r.pop("ttl", None) extra = r record = Record( id=zone_id, name=name, type=record_type, data=data, zone=zone, driver=self, ttl=ttl, extra=extra, ) records.append(record) return records
def test_update_record_validation_error(self): zone_data = self.get_zones()[0] url = self.url_tmpl % ('/'.join( ['zones', str(zone_data['id']), 'records'])) record_resp = self.client.get(url, headers=self.headers) record_data = json.loads(record_resp.data)[0] zone = Zone(zone_data['id'], zone_data['domain'], zone_data['type'], zone_data['ttl'], None) record = Record(record_data['id'], record_data['name'], record_data['type'], record_data['data'], zone, None) url = self.url_tmpl % ('/'.join( ['zones', str(zone_data['id']), 'records', str(record.id)])) with patch.object(RackspaceUSDNSDriver, 'get_record', mocksignature=True) as get_record_mock: get_record_mock.return_value = record resp = self.client.put(url, headers=self.headers, data='{"record_type": "127.3.3.3"}', content_type='application/json') resp_data = json.loads(resp.data) self.assertEqual(resp.status_code, httplib.BAD_REQUEST) self.assertEqual(resp_data['error']['code'], ValidationError.code)
def create_record(self, name, zone, type, data, extra=None): """ Create a new record. API docs: http://www.linode.com/api/dns/domain.resource.create """ params = { "api_action": "domain.resource.create", "DomainID": zone.id, "Name": name, "Target": data, "Type": self.RECORD_TYPE_MAP[type], } merged = merge_valid_keys(params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) result = self.connection.request(API_ROOT, params=params).objects[0] record = Record( id=result["ResourceID"], name=name, type=type, data=data, extra=merged, zone=zone, driver=self, ttl=merged.get("TTL_sec", None), ) return record
def _to_record(self, zone, item): name = self._get_record_name(item=item) type = item['type'] data = item['content'] if item.get('ttl', None): ttl = int(item['ttl']) else: ttl = None extra = {} extra['ttl'] = ttl extra['props'] = item.get('props', {}) for attribute in RECORD_EXTRA_ATTRIBUTES: value = item.get(attribute, None) extra[attribute] = value record = Record(id=str(item['rec_id']), name=name, type=type, data=data, zone=zone, driver=self, ttl=ttl, extra=extra) return record
def test_list_records(self): z_extra = { 'ns': 'ns1.durabledns.com.', 'mbox': 'mail.myzone.com', 'refresh': '13000', 'retry': 7200, 'expire': 1300, 'minimum': 13, 'xfer': '127.0.0.1', 'update_acl': '127.0.0.1' } zone = Zone(id='myzone.com.', domain='myzone.com.', type='master', ttl=1300, driver=self.driver, extra=z_extra) extra = {'aux': 1, 'ttl': 3600} record = Record(id='353286987', type='A', zone=zone, name='record1', data='192.168.0.1', driver=self, extra=extra) self.driver.get_record = MagicMock(return_value=record) records = self.driver.list_records(zone=zone) self.assertEqual(len(records), 2) self.assertEqual(record.id, '353286987') self.assertEqual(record.name, 'record1') self.assertEqual(record.type, 'A') self.assertEqual(record.data, '192.168.0.1') self.assertEqual(record.zone, zone) self.assertEqual(record.extra['aux'], 1) self.assertEqual(record.extra['ttl'], 3600)
def create_record(self, name, zone, type, data, extra=None): """ >>> driver = DummyDNSDriver('key', 'secret') >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) >>> record = driver.create_record(name='libcloud', zone=zone, ... type=RecordType.A, data='127.0.0.1') >>> record #doctest: +ELLIPSIS <Record: zone=id-apache.org, name=libcloud, type=A, data=127.0.0.1...> >>> record = driver.create_record(name='libcloud', zone=zone, ... type=RecordType.A, data='127.0.0.1') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): RecordAlreadyExistsError: @inherits: L{DNSDriver.create_record} """ id = 'id-%s' % (name) zone = self.get_zone(zone_id=zone.id) if id in self._zones[zone.id]['records']: raise RecordAlreadyExistsError(record_id=id, value=None, driver=self) record = Record(id=id, name=name, type=type, data=data, extra=extra, zone=zone, driver=self) self._zones[zone.id]['records'][id] = record return record
def _to_record(self, elem, zone): id = findtext(element=elem, xpath='id') name = findtext(element=elem, xpath='hostname') type = findtext(element=elem, xpath='host-type') type = self._string_to_record_type(type) data = findtext(element=elem, xpath='data') notes = findtext(element=elem, xpath='notes') state = findtext(element=elem, xpath='state') fqdn = findtext(element=elem, xpath='fqdn') priority = findtext(element=elem, xpath='priority') extra = { 'notes': notes, 'state': state, 'fqdn': fqdn, 'priority': priority } record = Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, extra=extra) return record
def _to_record(self, elem, zone, index=0): name = findtext(element=elem, xpath='Name', namespace=NAMESPACE) name = name[:-len(zone.domain) - 1] type = self._string_to_record_type(findtext(element=elem, xpath='Type', namespace=NAMESPACE)) ttl = int(findtext(element=elem, xpath='TTL', namespace=NAMESPACE)) value_elem = elem.findall( fixxpath(xpath='ResourceRecords/ResourceRecord', namespace=NAMESPACE))[index] data = findtext(element=(value_elem), xpath='Value', namespace=NAMESPACE) extra = {'ttl': ttl} if type == 'MX': split = data.split() priority, data = split extra['priority'] = int(priority) elif type == 'SRV': split = data.split() priority, weight, port, data = split extra['priority'] = int(priority) extra['weight'] = int(weight) extra['port'] = int(port) id = ':'.join((self.RECORD_TYPE_MAP[type], name)) record = Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, extra=extra) return record
def create_record(self, name, zone, type, data, extra=None): extra = extra or {} batch = [('CREATE', name, type, data, extra)] self._post_changeset(zone, batch) id = ':'.join((self.RECORD_TYPE_MAP[type], name)) return Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, extra=extra)
def test_delete_record(self): z_extra = { "ns": "ns1.durabledns.com.", "mbox": "mail.myzone.com", "refresh": "13000", "retry": 7200, "expire": 1300, "minimum": 13, "xfer": "127.0.0.1", "update_acl": "127.0.0.1", } zone = Zone( id="myzone.com.", domain="myzone.com.", type="master", ttl=1300, driver=self.driver, extra=z_extra, ) extra = {"aux": 1, "ttl": 3600} record = Record( id="353286987", type="A", zone=zone, name="record1", data="192.168.0.1", driver=self, extra=extra, ) status = self.driver.delete_record(record=record) self.assertTrue(status)
def _to_record(self, _id, subdomain, type, data, zone): return Record(id=_id, name=subdomain, type=type, data=data, zone=zone, driver=zone.driver)
def _to_record(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) id = data.get('id') name = data.get('name') type = data.get('type') content = data.get('content') extra = { "zone_id": data.get("zone_id"), "parent_id": data.get("parent_id"), "ttl": data.get("ttl"), "priority": data.get("priority"), "regions": data.get("regions"), "system_record": data.get("system_record"), "created_at": data.get("created_at"), "updated_at": data.get("updated_at"), } return Record(id=id, name=name, type=type, data=content, zone=zone, driver=self, ttl=data.get('ttl', None), extra=extra)
def test_delete_record(self): z_extra = { 'ns': 'ns1.durabledns.com.', 'mbox': 'mail.myzone.com', 'refresh': '13000', 'retry': 7200, 'expire': 1300, 'minimum': 13, 'xfer': '127.0.0.1', 'update_acl': '127.0.0.1' } zone = Zone(id='myzone.com.', domain='myzone.com.', type='master', ttl=1300, driver=self.driver, extra=z_extra) extra = {'aux': 1, 'ttl': 3600} record = Record(id='353286987', type='A', zone=zone, name='record1', data='192.168.0.1', driver=self, extra=extra) status = self.driver.delete_record(record=record) self.assertTrue(status)
def test_delete_record_record_does_not_exist(self): z_extra = { 'ns': 'ns1.durabledns.com.', 'mbox': 'mail.myzone.com', 'refresh': '13000', 'retry': 7200, 'expire': 1300, 'minimum': 13, 'xfer': '127.0.0.1', 'update_acl': '127.0.0.1' } zone = Zone(id='myzone.com.', domain='myzone.com.', type='master', ttl=1300, driver=self.driver, extra=z_extra) extra = {'aux': 1, 'ttl': 3600} record = Record(id='353286987', type='A', zone=zone, name='record1', data='192.168.0.1', driver=self, extra=extra) DurableDNSMockHttp.type = 'RECORD_DOES_NOT_EXIST' try: self.driver.delete_record(record=record) except RecordDoesNotExistError: pass else: self.fail('Exception was not thrown')
def update_record(self, record, name=None, type=None, data=None, extra=None): name = name or record.name type = type or record.type extra = extra or record.extra if not extra: extra = record.extra # Multiple value records need to be handled specially - we need to # pass values for other records as well multiple_value_record = record.extra.get("_multi_value", False) other_records = record.extra.get("_other_records", []) if multiple_value_record and other_records: self._update_multi_value_record( record=record, name=name, type=type, data=data, extra=extra ) else: self._update_single_value_record( record=record, name=name, type=type, data=data, extra=extra ) id = ":".join((self.RECORD_TYPE_MAP[type], name)) return Record( id=id, name=name, type=type, data=data, zone=record.zone, driver=self, ttl=extra.get("ttl", None), extra=extra, )
def _to_record(self, item, zone=None): extra = {'aux': int(item.get('aux')), 'ttl': int(item.get('ttl'))} record = Record(id=item.get('id'), type=item.get('type'), zone=zone, name=item.get('name'), data=item.get('data'), driver=self, extra=extra) return record
def create_record(self, name, zone, type, data, extra=None): """ Create a new record. API docs: http://www.linode.com/api/dns/domain.resource.create """ params = { 'api_action': 'domain.resource.create', 'DomainID': zone.id, 'Name': name, 'Target': data, 'Type': self.RECORD_TYPE_MAP[type] } merged = merge_valid_keys(params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) result = self.connection.request(API_ROOT, params=params).objects[0] record = Record(id=result['ResourceID'], name=name, type=type, data=data, extra=merged, zone=zone, driver=self) return record
def _to_record(self, item, zone=None): extra = {'ttl': item['ttl']} type = self._string_to_record_type(item['type']) record = Record(id=item['id'], name=item['name'], type=type, data=item['content'], zone=zone, driver=self, extra=extra) return record
def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ new_record = self._format_record(name, type, data, extra) self.connection.request( '/v1/domains/%s/records' % (zone.domain), method='PATCH', data=json.dumps([new_record])) id = self._get_id_of_record(name, type) return Record( id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=new_record['ttl'], extra=extra)
def test_update_record_success(self): zone_data = self.get_zones()[0] url = self.url_tmpl % ('/'.join( ['zones', str(zone_data['id']), 'records'])) record_resp = self.client.get(url, headers=self.headers) record_data = json.loads(record_resp.data)[0] zone = Zone(zone_data['id'], zone_data['domain'], zone_data['type'], zone_data['ttl'], None) record = Record(record_data['id'], record_data['name'], record_data['type'], record_data['data'], zone, None) url = self.url_tmpl % ('/'.join( ['zones', str(zone_data['id']), 'records', str(record.id)])) with patch.object(RackspaceUSDNSDriver, 'get_record', mocksignature=True) as get_record_mock: get_record_mock.return_value = record resp = self.client.put(url, headers=self.headers, data='{"data": "127.3.3.3"}', content_type='application/json') updated_record = json.loads(resp.data) self.assertEqual(resp.status_code, httplib.OK) self.assertEqual(record.name, 'test3') self.assertEqual(record.data, '127.7.7.7') self.assertEqual(updated_record['id'], record.id) self.assertEqual(updated_record['name'], record.name) self.assertEqual(updated_record['type'], record.type) self.assertEqual(updated_record['data'], '127.3.3.3')
def setUp(self): NFSNDNSDriver.connectionCls.conn_class = NFSNMockHttp NFSNMockHttp.type = None self.driver = NFSNDNSDriver('testid', 'testsecret') self.test_zone = Zone(id='example.com', domain='example.com', driver=self.driver, type='master', ttl=None, extra={}) self.test_record = Record(id=None, name='', data='192.0.2.1', type=RecordType.A, zone=self.test_zone, driver=self.driver, extra={})
class NFSNTestCase(LibcloudTestCase): def setUp(self): NFSNDNSDriver.connectionCls.conn_class = NFSNMockHttp NFSNMockHttp.type = None self.driver = NFSNDNSDriver('testid', 'testsecret') self.test_zone = Zone(id='example.com', domain='example.com', driver=self.driver, type='master', ttl=None, extra={}) self.test_record = Record(id=None, name='', data='192.0.2.1', type=RecordType.A, zone=self.test_zone, driver=self.driver, extra={}) def test_list_zones(self): with self.assertRaises(NotImplementedError): self.driver.list_zones() def test_create_zone(self): with self.assertRaises(NotImplementedError): self.driver.create_zone('example.com') def test_get_zone(self): zone = self.driver.get_zone('example.com') self.assertEquals(zone.id, None) self.assertEquals(zone.domain, 'example.com') def test_delete_zone(self): with self.assertRaises(NotImplementedError): self.driver.delete_zone(self.test_zone) def test_create_record(self): NFSNMockHttp.type = 'CREATED' record = self.test_zone.create_record(name='newrecord', type=RecordType.A, data='127.0.0.1', extra={'ttl': 900}) self.assertEquals(record.id, None) self.assertEquals(record.name, 'newrecord') self.assertEquals(record.data, '127.0.0.1') self.assertEquals(record.type, RecordType.A) self.assertEquals(record.ttl, 900) def test_get_record(self): with self.assertRaises(NotImplementedError): self.driver.get_record('example.com', '12345') def test_delete_record(self): self.assertTrue(self.test_record.delete()) def test_list_records(self): records = self.driver.list_records(self.test_zone) self.assertEqual(len(records), 2) def test_ex_get_records_by(self): NFSNMockHttp.type = 'ONE_RECORD' records = self.driver.ex_get_records_by(self.test_zone, type=RecordType.A) self.assertEqual(len(records), 1) record = records[0] self.assertEquals(record.name, '') self.assertEquals(record.data, '192.0.2.1') self.assertEquals(record.type, RecordType.A) self.assertEquals(record.ttl, 3600) def test_get_zone_not_found(self): NFSNMockHttp.type = 'NOT_FOUND' with self.assertRaises(ZoneDoesNotExistError): self.driver.get_zone('example.com') def test_delete_record_not_found(self): NFSNMockHttp.type = 'NOT_FOUND' with self.assertRaises(RecordDoesNotExistError): self.assertTrue(self.test_record.delete())