def test_import_export(self): # Since v2 doesn't support getting records, import and export the # fixture, making sure they're the same according to dnspython post_response = self.client.post('/zones', self.get_zonefile_fixture(), headers={'Content-type': 'text/dns'}) get_response = self.client.get('/zones/%s' % post_response.json['zone']['id'], headers={'Accept': 'text/dns'}) exported_zonefile = get_response.body imported = dnszone.from_text(self.get_zonefile_fixture()) exported = dnszone.from_text(exported_zonefile) # Compare SOA emails, since zone comparison takes care of origin imported_soa = imported.get_rdataset(imported.origin, 'SOA') imported_email = imported_soa[0].rname.to_text() exported_soa = exported.get_rdataset(exported.origin, 'SOA') exported_email = exported_soa[0].rname.to_text() self.assertEqual(imported_email, exported_email) # Delete SOAs since they have, at the very least, different serials, # and dnspython considers that to be not equal. imported.delete_rdataset(imported.origin, 'SOA') exported.delete_rdataset(exported.origin, 'SOA') # Delete non-delegation NS, since they won't be the same imported.delete_rdataset(imported.origin, 'NS') exported.delete_rdataset(exported.origin, 'NS') self.assertEqual(imported, exported)
def test_parse_zone(self): zone_file = self.get_zonefile_fixture() dnspython_zone = dnszone.from_text( zone_file, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) zone = dnsutils.from_dnspython_zone(dnspython_zone) for rrset in zone.recordsets: k = (rrset.name, rrset.type) self.assertIn(k, SAMPLES) sample_ttl = SAMPLES[k].get('ttl', None) if rrset.obj_attr_is_set('ttl') or sample_ttl is not None: self.assertEqual(rrset.ttl, sample_ttl) self.assertEqual(len(SAMPLES[k]['records']), len(rrset.records)) for r in rrset.records: self.assertIn(r.data, SAMPLES[k]['records']) self.assertEqual(len(SAMPLES), len(zone.recordsets)) self.assertEqual('example.com.', zone.name)
def test_parse_zone(self): zone_file = self.get_zonefile_fixture() dnspython_zone = dnszone.from_text( zone_file, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) zone = dnsutils.from_dnspython_zone(dnspython_zone) for rrset in zone.recordsets: k = (rrset.name, rrset.type) self.assertIn(k, SAMPLES) sample_ttl = SAMPLES[k].get('ttl', None) if rrset.obj_attr_is_set('ttl') or sample_ttl is not None: self.assertEqual(sample_ttl, rrset.ttl) self.assertEqual(len(rrset.records), len(SAMPLES[k]['records'])) for record in rrset.records: self.assertIn(record.data, SAMPLES[k]['records']) self.assertEqual(len(SAMPLES), len(zone.recordsets)) self.assertEqual('example.com.', zone.name)
def _post_zonefile(self, request, response, context): """Import Zone""" try: dnspython_zone = dnszone.from_text( request.body, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) domain = dnsutils.from_dnspython_zone(dnspython_zone) for rrset in domain.recordsets: if rrset.type in ('NS', 'SOA'): domain.recordsets.remove(rrset) except dnszone.UnknownOrigin: raise exceptions.BadRequest('The $ORIGIN statement is required and' ' must be the first statement in the' ' zonefile.') except dnsexception.SyntaxError: raise exceptions.BadRequest('Malformed zonefile.') zone = self.central_api.create_domain(context, domain) if zone['status'] == 'PENDING': response.status_int = 202 else: response.status_int = 201 response.headers['Location'] = self._view._get_resource_href(request, zone) return self._view.show(context, request, zone)
def _post_zonefile(self, request, response, context): """Import Zone""" try: dnspython_zone = dnszone.from_text( request.body, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) domain = dnsutils.from_dnspython_zone(dnspython_zone) domain.type = 'PRIMARY' for rrset in list(domain.recordsets): if rrset.type in ('NS', 'SOA'): domain.recordsets.remove(rrset) except dnszone.UnknownOrigin: raise exceptions.BadRequest('The $ORIGIN statement is required and' ' must be the first statement in the' ' zonefile.') except dnsexception.SyntaxError: raise exceptions.BadRequest('Malformed zonefile.') zone = self.central_api.create_domain(context, domain) if zone['status'] == 'PENDING': response.status_int = 202 else: response.status_int = 201 response.headers['Location'] = self._view._get_resource_href( request, zone) return self._view.show(context, request, zone)
def test_from_dnspython_zone(self): zone_file = self.get_zonefile_fixture() dnspython_zone = dnszone.from_text(zone_file, relativize=False, check_origin=False) zone = dnsutils.from_dnspython_zone(dnspython_zone) self.assertIsInstance(zone, objects.zone.Zone)
def test_from_dnspython_zone_no_soa(self): zone_file = self.get_zonefile_fixture(variant='nosoa') dnspython_zone = dnszone.from_text(zone_file, relativize=False, check_origin=False) self.assertRaisesRegex( exceptions.BadRequest, 'An SOA record is required', dnsutils.from_dnspython_zone, dnspython_zone, )
def test_import_export(self): # Since v2 doesn't support getting records, import and export the # fixture, making sure they're the same according to dnspython post_response = self.client.post('/zones/tasks/imports', self.get_zonefile_fixture(), headers={'Content-type': 'text/dns'}) import_id = post_response.json_body['id'] self.wait_for_import(import_id) url = '/zones/tasks/imports/%s' % import_id response = self.client.get(url) self.policy({'zone_export': '@'}) get_response = self.adminclient.get('/zones/export/%s' % response.json['zone_id'], headers={'Accept': 'text/dns'}) if six.PY2: exported_zonefile = get_response.body else: exported_zonefile = get_response.body.decode('utf-8') imported = dnszone.from_text(self.get_zonefile_fixture()) exported = dnszone.from_text(exported_zonefile) # Compare SOA emails, since zone comparison takes care of origin imported_soa = imported.get_rdataset(imported.origin, 'SOA') imported_email = imported_soa[0].rname.to_text() exported_soa = exported.get_rdataset(exported.origin, 'SOA') exported_email = exported_soa[0].rname.to_text() self.assertEqual(imported_email, exported_email) # Delete SOAs since they have, at the very least, different serials, # and dnspython considers that to be not equal. imported.delete_rdataset(imported.origin, 'SOA') exported.delete_rdataset(exported.origin, 'SOA') # Delete NS records, since they won't be the same imported.delete_rdataset(imported.origin, 'NS') exported.delete_rdataset(exported.origin, 'NS') imported.delete_rdataset('delegation', 'NS') self.assertEqual(imported, exported)
def post_all(self): request = pecan.request response = pecan.response context = pecan.request.environ['context'] policy.check('zone_import', context) if request.content_type != 'text/dns': raise exceptions.UnsupportedContentType( 'Content-type must be text/dns') try: dnspython_zone = dnszone.from_text( request.body, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) domain = dnsutils.from_dnspython_zone(dnspython_zone) domain.type = 'PRIMARY' for rrset in list(domain.recordsets): if rrset.type in ('NS', 'SOA'): domain.recordsets.remove(rrset) except dnszone.UnknownOrigin: raise exceptions.BadRequest('The $ORIGIN statement is required and' ' must be the first statement in the' ' zonefile.') except dnsexception.SyntaxError: raise exceptions.BadRequest('Malformed zonefile.') zone = self.central_api.create_domain(context, domain) if zone['status'] == 'PENDING': response.status_int = 202 else: response.status_int = 201 zone = DesignateAdapter.render('API_v2', zone, request=request) zone['links']['self'] = '%s/%s/%s' % (self.BASE_URI, 'v2/zones', zone['id']) response.headers['Location'] = zone['links']['self'] return zone
def post_all(self): request = pecan.request response = pecan.response context = pecan.request.environ['context'] policy.check('zone_import', context) if request.content_type != 'text/dns': raise exceptions.UnsupportedContentType( 'Content-type must be text/dns') try: dnspython_zone = dnszone.from_text( request.body, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) domain = dnsutils.from_dnspython_zone(dnspython_zone) domain.type = 'PRIMARY' for rrset in list(domain.recordsets): if rrset.type in ('NS', 'SOA'): domain.recordsets.remove(rrset) except dnszone.UnknownOrigin: raise exceptions.BadRequest('The $ORIGIN statement is required and' ' must be the first statement in the' ' zonefile.') except dnsexception.SyntaxError: raise exceptions.BadRequest('Malformed zonefile.') zone = self.central_api.create_domain(context, domain) if zone['status'] == 'PENDING': response.status_int = 202 else: response.status_int = 201 zone = DesignateAdapter.render('API_v2', zone, request=request) zone['links']['self'] = '%s/%s/%s' % ( self.BASE_URI, 'v2/zones', zone['id']) response.headers['Location'] = zone['links']['self'] return zone
def _parse_zonefile(self, request): """ Parses a POSTed zonefile into a dnspython zone object """ try: dnspython_zone = dnszone.from_text( request.body, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) except dnszone.UnknownOrigin: raise exceptions.BadRequest('The $ORIGIN statement is required and' ' must be the first statement in the' ' zonefile.') except dnsexception.SyntaxError: raise exceptions.BadRequest('Malformed zonefile.') return dnspython_zone
def _parse_zonefile(self, request): """Parses a POSTed zonefile into a dnspython zone object""" try: dnspython_zone = dnszone.from_text( request.body, # Don't relativize, otherwise we end up with '@' record names. relativize=False, # Dont check origin, we allow missing NS records (missing SOA # records are taken care of in _create_zone). check_origin=False) except dnszone.UnknownOrigin: raise exceptions.BadRequest('The $ORIGIN statement is required and' ' must be the first statement in the' ' zonefile.') except dnsexception.SyntaxError: raise exceptions.BadRequest('Malformed zonefile.') return dnspython_zone