Ejemplo n.º 1
0
    def create_domain(self, context, values):
        domain = models.Domain()

        domain.update(values)

        try:
            domain.save(self.session)
        except exceptions.Duplicate:
            raise exceptions.DuplicateDomain()

        return dict(domain)
Ejemplo n.º 2
0
    def update_domain(self, context, domain_id, values):
        domain = self._find_domains(context, {'id': domain_id}, one=True)

        domain.update(values)

        try:
            domain.save(self.session)
        except exceptions.Duplicate:
            raise exceptions.DuplicateDomain()

        return dict(domain)
Ejemplo n.º 3
0
    def create_domain(self, context, domain):
        storage_domain = models.Domain()

        storage_domain.update(domain)

        try:
            storage_domain.save(self.session)
        except exceptions.Duplicate:
            raise exceptions.DuplicateDomain()

        return objects.Domain.from_sqla(storage_domain)
Ejemplo n.º 4
0
class ApiV2ZonesTest(ApiV2TestCase):
    __test__ = True

    def setUp(self):
        super(ApiV2ZonesTest, self).setUp()

        # Create a server
        self.create_server()

    def test_missing_accept(self):
        self.client.get('/zones/123', status=400)

    def test_bad_accept(self):
        self.client.get('/zones/123',
                        headers={'Accept': 'test/goat'},
                        status=406)

    def test_missing_content_type(self):
        self.client.post('/zones', status=415)

    def test_bad_content_type(self):
        self.client.post('/zones',
                         headers={'Content-type': 'test/goat'},
                         status=415)

    def test_create_zone(self):
        # Create a zone
        fixture = self.get_domain_fixture(0)
        response = self.client.post_json('/zones/', {'zone': fixture})

        # Check the headers are what we expect
        self.assertEqual(201, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zone', response.json)
        self.assertIn('links', response.json['zone'])
        self.assertIn('self', response.json['zone']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['zone'])
        self.assertIn('created_at', response.json['zone'])
        self.assertEqual('ACTIVE', response.json['zone']['status'])
        self.assertIsNone(response.json['zone']['updated_at'])

        for k in fixture:
            self.assertEqual(fixture[k], response.json['zone'][k])

    def test_create_zone_validation(self):
        # NOTE: The schemas should be tested separatly to the API. So we
        #       don't need to test every variation via the API itself.
        # Fetch a fixture
        fixture = self.get_domain_fixture(0)

        # Add a junk field to the wrapper
        body = {'zone': fixture, 'junk': 'Junk Field'}

        # Ensure it fails with a 400
        response = self.client.post_json('/zones/', body, status=400)
        self.assertEqual(400, response.status_int)

        # Add a junk field to the body
        fixture['junk'] = 'Junk Field'

        # Ensure it fails with a 400
        body = {'zone': fixture}
        self.client.post_json('/zones/', body, status=400)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=rpc_common.Timeout())
    def test_create_zone_timeout(self, _):
        fixture = self.get_domain_fixture(0)

        body = {'zone': fixture}
        self.client.post_json('/zones/', body, status=504)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_create_zone_duplicate(self, _):
        fixture = self.get_domain_fixture(0)

        body = {'zone': fixture}
        self.client.post_json('/zones/', body, status=409)

    def test_get_zones(self):
        response = self.client.get('/zones/')

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zones', response.json)
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # We should start with 0 zones
        self.assertEqual(0, len(response.json['zones']))

        # Test with 1 zone
        self.create_domain()

        response = self.client.get('/zones/')

        self.assertIn('zones', response.json)
        self.assertEqual(1, len(response.json['zones']))

        # test with 2 zones
        self.create_domain(fixture=1)

        response = self.client.get('/zones/')

        self.assertIn('zones', response.json)
        self.assertEqual(2, len(response.json['zones']))

    @patch.object(central_service.Service,
                  'find_domains',
                  side_effect=rpc_common.Timeout())
    def test_get_zones_timeout(self, _):
        self.client.get('/zones/', status=504)

    def test_get_zone(self):
        # Create a zone
        zone = self.create_domain()

        response = self.client.get('/zones/%s' % zone['id'],
                                   headers=[('Accept', 'application/json')])

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zone', response.json)
        self.assertIn('links', response.json['zone'])
        self.assertIn('self', response.json['zone']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['zone'])
        self.assertIn('created_at', response.json['zone'])
        self.assertEqual('ACTIVE', response.json['zone']['status'])
        self.assertIsNone(response.json['zone']['updated_at'])
        self.assertEqual(zone['name'], response.json['zone']['name'])
        self.assertEqual(zone['email'], response.json['zone']['email'])

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=rpc_common.Timeout())
    def test_get_zone_timeout(self, _):
        self.client.get('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                        headers={'Accept': 'application/json'},
                        status=504)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_get_zone_missing(self, _):
        self.client.get('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                        headers={'Accept': 'application/json'},
                        status=404)

    def test_get_zone_invalid_id(self):
        self.skip('We don\'t guard against this in APIv2 yet')

        # The letter "G" is not valid in a UUID
        self.client.get('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                        headers={'Accept': 'application/json'},
                        status=404)

        # Badly formed UUID
        self.client.get('/zones/2fdadfb1cf964259ac6bbb7b6d2ff9GG',
                        headers={'Accept': 'application/json'},
                        status=404)

        # Integer
        self.client.get('/zones/12345',
                        headers={'Accept': 'application/json'},
                        status=404)

    def test_update_zone(self):
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body
        body = {'zone': {'email': 'prefix-%s' % zone['email']}}

        response = self.client.patch_json('/zones/%s' % zone['id'],
                                          body,
                                          status=200)

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zone', response.json)
        self.assertIn('links', response.json['zone'])
        self.assertIn('self', response.json['zone']['links'])
        self.assertIn('status', response.json['zone'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['zone'])
        self.assertIsNotNone(response.json['zone']['updated_at'])
        self.assertEqual('prefix-%s' % zone['email'],
                         response.json['zone']['email'])

    def test_update_zone_validation(self):
        # NOTE: The schemas should be tested separatly to the API. So we
        #       don't need to test every variation via the API itself.
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body with junk in the wrapper
        body = {
            'zone': {
                'email': 'prefix-%s' % zone['email']
            },
            'junk': 'Junk Field'
        }

        # Ensure it fails with a 400
        self.client.patch_json('/zones/%s' % zone['id'], body, status=400)

        # Prepare an update body with junk in the body
        body = {
            'zone': {
                'email': 'prefix-%s' % zone['email'],
                'junk': 'Junk Field'
            }
        }

        # Ensure it fails with a 400
        self.client.patch_json('/zones/%s' % zone['id'], body, status=400)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_update_zone_duplicate(self, _):
        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        # Ensure it fails with a 409
        self.client.patch_json('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                               body,
                               status=409)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=rpc_common.Timeout())
    def test_update_zone_timeout(self, _):
        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        # Ensure it fails with a 504
        self.client.patch_json('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                               body,
                               status=504)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_update_zone_missing(self, _):
        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        # Ensure it fails with a 404
        self.client.patch_json('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                               body,
                               status=404)

    def test_update_zone_invalid_id(self):
        self.skip('We don\'t guard against this in APIv2 yet')

        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        # The letter "G" is not valid in a UUID
        self.client.patch_json('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                               body,
                               status=404)

        # Badly formed UUID
        self.client.patch_json('/zones/2fdadfb1cf964259ac6bbb7b6d2ff980',
                               body,
                               status=404)

        # Integer
        self.client.patch_json('/zones/12345', body, status=404)

    def test_delete_zone(self):
        zone = self.create_domain()

        self.client.delete('/zones/%s' % zone['id'], status=204)

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=rpc_common.Timeout())
    def test_delete_zone_timeout(self, _):
        self.client.delete('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                           status=504)

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_delete_zone_missing(self, _):
        self.client.delete('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                           status=404)

    def test_delete_zone_invalid_id(self):
        self.skip('We don\'t guard against this in APIv2 yet')

        # The letter "G" is not valid in a UUID
        self.client.delete('/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                           status=404)

        # Badly formed UUID
        self.client.delete('/zones/2fdadfb1cf964259ac6bbb7b6d2ff980',
                           status=404)

        # Integer
        self.client.delete('/zones/12345', status=404)

    # Zone import/export
    def test_missing_origin(self):
        self.client.post('/zones',
                         self.get_zonefile_fixture(variant='noorigin'),
                         headers={'Content-type': 'text/dns'},
                         status=400)

    def test_missing_soa(self):
        self.client.post('/zones',
                         self.get_zonefile_fixture(variant='nosoa'),
                         headers={'Content-type': 'text/dns'},
                         status=400)

    def test_malformed_zonefile(self):
        self.client.post('/zones',
                         self.get_zonefile_fixture(variant='malformed'),
                         headers={'Content-type': 'text/dns'},
                         status=400)

    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)
Ejemplo n.º 5
0
class ApiV2ZonesTest(ApiV2TestCase):
    def setUp(self):
        super(ApiV2ZonesTest, self).setUp()

        # Create the default TLDs
        self.create_default_tlds()

    def test_create_zone(self):
        # Create a zone
        fixture = self.get_domain_fixture(fixture=0)

        response = self.client.post_json('/zones/', fixture)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json)
        self.assertIn('created_at', response.json)
        self.assertEqual('PENDING', response.json['status'])
        self.assertEqual('PRIMARY', response.json['type'])
        self.assertEqual([], response.json['masters'])
        self.assertIsNone(response.json['updated_at'])

        for k in fixture:
            self.assertEqual(fixture[k], response.json[k])

    def test_create_zone_no_type(self):
        # Create a zone
        fixture = self.get_domain_fixture(fixture=0)
        del fixture['type']

        response = self.client.post_json('/zones/', fixture)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json)
        self.assertIn('created_at', response.json)
        self.assertEqual('PENDING', response.json['status'])
        self.assertEqual('PRIMARY', response.json['type'])
        self.assertEqual([], response.json['masters'])
        self.assertIsNone(response.json['updated_at'])

        for k in fixture:
            self.assertEqual(fixture[k], response.json[k])

    def test_create_zone_validation(self):
        # NOTE: The schemas should be tested separately to the API. So we
        #       don't need to test every variation via the API itself.
        # Fetch a fixture
        fixture = self.get_domain_fixture(fixture=0)

        # Add a junk field to the body
        fixture['junk'] = 'Junk Field'

        # Ensure it fails with a 400
        body = fixture

        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_body_validation(self):
        fixture = self.get_domain_fixture(fixture=0)
        # Add id to the body
        fixture['id'] = '2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        # Ensure it fails with a 400
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

        fixture = self.get_domain_fixture(fixture=0)
        # Add created_at to the body
        fixture['created_at'] = '2014-03-12T19:07:53.000000'
        # Ensure it fails with a 400
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_invalid_name(self):
        # Try to create a zone with an invalid name
        fixture = self.get_domain_fixture(fixture=-1)

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', fixture)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_create_zone_timeout(self, _):
        fixture = self.get_domain_fixture(fixture=0)

        body = fixture

        self._assert_exception('timeout', 504, self.client.post_json,
                               '/zones/', body)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_create_zone_duplicate(self, _):
        fixture = self.get_domain_fixture(fixture=0)

        body = fixture

        self._assert_exception('duplicate_domain', 409, self.client.post_json,
                               '/zones/', body)

    def test_create_zone_missing_content_type(self):
        self._assert_exception('unsupported_content_type', 415,
                               self.client.post, '/zones')

    def test_create_zone_bad_content_type(self):
        self._assert_exception('unsupported_content_type',
                               415,
                               self.client.post,
                               '/zones',
                               headers={'Content-type': 'test/goat'})

    def test_zone_invalid_url(self):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980/invalid'
        self._assert_exception('not_found',
                               404,
                               self.client.get,
                               url,
                               headers={'Accept': 'application/json'})
        self._assert_exception('not_found', 404, self.client.patch_json, url)
        self._assert_exception('not_found', 404, self.client.delete, url)

        # Pecan returns a 405 for post
        response = self.client.post(url, status=405)
        self.assertEqual(405, response.status_int)

    def test_get_zones(self):
        response = self.client.get('/zones/')

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zones', response.json)
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # We should start with 0 zones
        self.assertEqual(0, len(response.json['zones']))

        # We should start with 0 zones
        self.assertEqual(0, len(response.json['zones']))

        data = [self.create_domain(name='x-%s.com.' % i) for i in 'abcdefghij']
        self._assert_paging(data, '/zones', key='zones')

        self._assert_invalid_paging(data, '/zones', key='zones')

    @patch.object(central_service.Service,
                  'find_domains',
                  side_effect=messaging.MessagingTimeout())
    def test_get_zones_timeout(self, _):
        self._assert_exception('timeout', 504, self.client.get, '/zones/')

    def test_get_zone(self):
        # Create a zone
        zone = self.create_domain()

        response = self.client.get('/zones/%s' % zone['id'],
                                   headers=[('Accept', 'application/json')])

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json)
        self.assertIn('created_at', response.json)
        self.assertEqual('PENDING', response.json['status'])
        self.assertIsNone(response.json['updated_at'])
        self.assertEqual(zone['name'], response.json['name'])
        self.assertEqual(zone['email'], response.json['email'])

    def test_get_zone_invalid_id(self):
        self._assert_invalid_uuid(self.client.get, '/zones/%s')

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_get_zone_timeout(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        self._assert_exception('timeout',
                               504,
                               self.client.get,
                               url,
                               headers={'Accept': 'application/json'})

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_get_zone_missing(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        self._assert_exception('domain_not_found',
                               404,
                               self.client.get,
                               url,
                               headers={'Accept': 'application/json'})

    def test_get_zone_bad_accept(self):
        url = '/zones/6e2146f3-87bc-4f47-adc5-4df0a5c78218'

        self.client.get(url, headers={'Accept': 'test/goat'}, status=406)

    def test_update_zone(self):
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body
        body = {'email': 'prefix-%s' % zone['email']}

        response = self.client.patch_json('/zones/%s' % zone['id'],
                                          body,
                                          status=202)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])
        self.assertIn('status', response.json)

        # Check the values returned are what we expect
        self.assertIn('id', response.json)
        self.assertIsNotNone(response.json['updated_at'])
        self.assertEqual('prefix-%s' % zone['email'], response.json['email'])

    def test_update_zone_invalid_id(self):
        self._assert_invalid_uuid(self.client.patch_json, '/zones/%s')

    def test_update_zone_validation(self):
        # NOTE: The schemas should be tested separatly to the API. So we
        #       don't need to test every variation via the API itself.
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body with junk in the body
        body = {'email': 'prefix-%s' % zone['email'], 'junk': 'Junk Field'}

        url = '/zones/%s' % zone['id']

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.patch_json,
                               url, body)

        # Prepare an update body with negative ttl in the body
        body = {'email': 'prefix-%s' % zone['email'], 'ttl': -20}

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.patch_json,
                               url, body)

        # Prepare an update body with ttl > maximum (2147483647) in the body
        body = {'email': 'prefix-%s' % zone['email'], 'ttl': 2147483648}

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.patch_json,
                               url, body)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_update_zone_duplicate(self, _):
        # Prepare an update body
        body = {'email': '*****@*****.**'}

        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        # Ensure it fails with a 409
        self._assert_exception('duplicate_domain', 409, self.client.patch_json,
                               url, body)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_update_zone_timeout(self, _):
        # Prepare an update body
        body = {'email': '*****@*****.**'}

        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        # Ensure it fails with a 504
        self._assert_exception('timeout', 504, self.client.patch_json, url,
                               body)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_update_zone_missing(self, _):
        # Prepare an update body
        body = {'email': '*****@*****.**'}

        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        # Ensure it fails with a 404
        self._assert_exception('domain_not_found', 404, self.client.patch_json,
                               url, body)

    def test_delete_zone(self):
        zone = self.create_domain()

        response = self.client.delete('/zones/%s' % zone['id'], status=202)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)
        self.assertEqual('DELETE', response.json['action'])
        self.assertEqual('PENDING', response.json['status'])

    def test_delete_zone_invalid_id(self):
        self._assert_invalid_uuid(self.client.delete, '/zones/%s')

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_delete_zone_timeout(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        self._assert_exception('timeout', 504, self.client.delete, url)

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_delete_zone_missing(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        self._assert_exception('domain_not_found', 404, self.client.delete,
                               url)

    def test_post_abandon_zone(self):
        zone = self.create_domain()
        url = '/zones/%s/tasks/abandon' % zone.id

        # Ensure that we get permission denied
        self._assert_exception('forbidden', 403, self.client.post_json, url)

        # Ensure that abandon zone succeeds with the right policy
        self.policy({'abandon_domain': '@'})
        response = self.client.post_json(url)
        self.assertEqual(204, response.status_int)

    def test_get_abandon_zone(self):
        zone = self.create_domain()
        url = '/zones/%s/tasks/abandon' % zone.id
        self._assert_exception('method_not_allowed', 405, self.client.get, url)

    def test_get_invalid_abandon(self):
        # This is an invalid endpoint - should return 404
        url = '/zones/tasks/abandon'
        self._assert_exception('not_found', 404, self.client.get, url)

    def test_get_zone_tasks(self):
        # This is an invalid endpoint - should return 404
        zone = self.create_domain()
        url = '/zones/%s/tasks' % zone.id
        self._assert_exception('not_found', 404, self.client.get, url)

    def test_create_secondary(self):
        # Create a zone
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['masters'] = ["10.0.0.1"]

        response = self.client.post_json('/zones/', fixture)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json)
        self.assertIn('created_at', response.json)
        self.assertEqual('PENDING', response.json['status'])
        self.assertEqual(cfg.CONF['service:central'].managed_resource_email,
                         response.json['email'])

        self.assertIsNone(response.json['updated_at'])
        # Zone is not transferred yet
        self.assertIsNone(response.json['transferred_at'])
        # Serial defaults to 1
        self.assertEqual(response.json['serial'], 1)

        for k in fixture:
            self.assertEqual(fixture[k], response.json[k])

    def test_create_secondary_no_masters(self):
        # Create a zone
        fixture = self.get_domain_fixture('SECONDARY', 0)

        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones/', fixture)

    def test_update_secondary(self):
        # Create a zone
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email
        fixture['attributes'] = [{"key": "master", "value": "10.0.0.10"}]

        # Create a zone
        zone = self.create_domain(**fixture)

        masters = ['10.0.0.1', '10.0.0.2']

        # Prepare an update body
        body = {'masters': masters}

        response = self.client.patch_json('/zones/%s' % zone['id'],
                                          body,
                                          status=202)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])
        self.assertIn('status', response.json)

        # Check the values returned are what we expect
        self.assertIn('id', response.json)
        self.assertIsNotNone(response.json['updated_at'])
        self.assertEqual(masters, response.json['masters'])
        self.assertEqual(1, response.json['serial'])

    def test_xfr_request(self):
        # Create a zone
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email
        fixture['attributes'] = [{"key": "master", "value": "10.0.0.10"}]

        # Create a zone
        zone = self.create_domain(**fixture)

        response = self.client.post_json('/zones/%s/tasks/xfr' % zone['id'],
                                         None,
                                         status=202)

        # Check the headers are what we expect
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

    def test_invalid_xfr_request(self):
        # Create a zone

        # Create a zone
        zone = self.create_domain()

        response = self.client.post_json('/zones/%s/tasks/xfr' % zone['id'],
                                         None,
                                         status=400)

        # Check the headers are what we expect
        self.assertEqual(400, response.status_int)
        self.assertEqual('application/json', response.content_type)

    def test_update_secondary_email_invalid_object(self):
        # Create a zone
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        # Create a zone
        zone = self.create_domain(**fixture)

        body = {'email': '*****@*****.**'}

        self._assert_exception('invalid_object', 400, self.client.patch_json,
                               '/zones/%s' % zone['id'], body)

    # Metadata tests
    def test_metadata_exists(self):
        response = self.client.get('/zones/')

        # Make sure the fields exist
        self.assertIn('metadata', response.json)
        self.assertIn('total_count', response.json['metadata'])

    def test_total_count(self):
        response = self.client.get('/zones/')

        # There are no zones by default
        self.assertEqual(0, response.json['metadata']['total_count'])

        # Create a zone
        fixture = self.get_domain_fixture(fixture=0)
        response = self.client.post_json('/zones/', fixture)

        response = self.client.get('/zones/')

        # Make sure total_count picked it up
        self.assertEqual(1, response.json['metadata']['total_count'])

    def test_total_count_pagination(self):
        # Create two zones
        fixture = self.get_domain_fixture(fixture=0)
        response = self.client.post_json('/zones/', fixture)

        fixture = self.get_domain_fixture(fixture=1)
        response = self.client.post_json('/zones/', fixture)

        # Paginate so that there is only one zone returned
        response = self.client.get('/zones?limit=1')

        self.assertEqual(1, len(response.json['zones']))

        # The total_count should know there are two
        self.assertEqual(2, response.json['metadata']['total_count'])

    def test_no_update_deleting(self):
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body
        body = {'zone': {'email': 'prefix-%s' % zone['email']}}

        self.client.delete('/zones/%s' % zone['id'], status=202)
        self._assert_exception('bad_request', 400, self.client.patch_json,
                               '/zones/%s' % zone['id'], body)

    def test_get_nameservers(self):
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body

        response = self.client.get('/zones/%s/nameservers' % zone['id'],
                                   headers=[('Accept', 'application/json')])

        self.assertIn('nameservers', response.json)
        self.assertEqual(1, len(response.json['nameservers']))
        self.assertIn('hostname', response.json['nameservers'][0])
        self.assertIn('priority', response.json['nameservers'][0])
Ejemplo n.º 6
0
class ApiV1DomainsTest(ApiV1Test):
    def test_create_domain(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        # V1 doesn't have these
        del fixture['type']

        response = self.post('domains', data=fixture)

        self.assertIn('id', response.json)
        self.assertIn('name', response.json)
        self.assertEqual(response.json['name'], fixture['name'])

    def test_create_domain_junk(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        # Add a junk property
        fixture['junk'] = 'Junk Field'

        # Ensure it fails with a 400
        self.post('domains', data=fixture, status_code=400)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_create_domain_timeout(self, _):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        # V1 doesn't have these
        del fixture['type']

        self.post('domains', data=fixture, status_code=504)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_create_domain_duplicate(self, _):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        # V1 doesn't have these
        del fixture['type']

        self.post('domains', data=fixture, status_code=409)

    def test_create_domain_null_ttl(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['ttl'] = None
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_negative_ttl(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['ttl'] = -1
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_invalid_ttl(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['ttl'] = "$?>&"
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_utf_description(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        # V1 doesn't have type
        del fixture['type']

        # Give it a UTF-8 filled description
        fixture['description'] = "utf-8:2H₂+O₂⇌2H₂O,R=4.7kΩ,⌀200mm∮E⋅da=Q,n" \
                                 ",∑f(i)=∏g(i),∀x∈ℝ:⌈x⌉"
        # Create the domain, ensuring it succeeds, thus UTF-8 is supported
        self.post('domains', data=fixture)

    def test_create_domain_description_too_long(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['description'] = "x" * 161

        # Create the domain, ensuring it fails with a 400
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_with_unwanted_attributes(self):

        domain_id = "2d1d1d1d-1324-4a80-aa32-1f69a91bf2c8"
        created_at = datetime.datetime(2014, 6, 22, 21, 50, 0)
        updated_at = datetime.datetime(2014, 6, 22, 21, 50, 0)
        serial = 1234567

        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['id'] = domain_id
        fixture['created_at'] = created_at
        fixture['updated_at'] = updated_at
        fixture['serial'] = serial

        self.post('domains', data=fixture, status_code=400)

    def test_create_invalid_name(self):
        # Prepare a domain
        fixture = self.get_domain_fixture(0)

        invalid_names = [
            'org',
            'example.org',
            'example.321',
        ]

        for invalid_name in invalid_names:
            fixture['name'] = invalid_name

            # Create a record
            response = self.post('domains', data=fixture, status_code=400)

            self.assertNotIn('id', response.json)

    def test_create_invalid_email(self):
        # Prepare a domain
        fixture = self.get_domain_fixture(0)

        invalid_emails = [
            'org',
            'example.org',
            'bla.example.org',
            'org.',
            'example.org.',
            'bla.example.org.',
            'bla.example.org.',
        ]

        for invalid_email in invalid_emails:
            fixture['email'] = invalid_email

            # Create a record
            response = self.post('domains', data=fixture, status_code=400)

            self.assertNotIn('id', response.json)

    def test_get_domains(self):
        response = self.get('domains')

        self.assertIn('domains', response.json)
        self.assertEqual(0, len(response.json['domains']))

        # Create a domain
        self.create_domain()

        response = self.get('domains')

        self.assertIn('domains', response.json)
        self.assertEqual(1, len(response.json['domains']))

        # Create a second domain
        self.create_domain(fixture=1)

        response = self.get('domains')

        self.assertIn('domains', response.json)
        self.assertEqual(2, len(response.json['domains']))

    def test_get_domain_servers(self):
        # Create a domain
        domain = self.create_domain()
        response = self.get('domains/%s/servers' % domain['id'])
        # Verify length of domain servers
        self.assertEqual(1, len(response.json['servers']))

    @patch.object(central_service.Service,
                  'find_domains',
                  side_effect=messaging.MessagingTimeout())
    def test_get_domains_timeout(self, _):
        self.get('domains', status_code=504)

    def test_get_domain(self):
        # Create a domain
        domain = self.create_domain()

        response = self.get('domains/%s' % domain['id'])

        self.assertIn('id', response.json)
        self.assertEqual(response.json['id'], domain['id'])

    @patch.object(central_service.Service,
                  'find_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_get_domain_timeout(self, _):
        # Create a domain
        domain = self.create_domain()

        self.get('domains/%s' % domain['id'], status_code=504)

    def test_get_domain_missing(self):
        self.get('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                 status_code=404)

    def test_get_domain_invalid_id(self):
        # The letter "G" is not valid in a UUID
        self.get('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                 status_code=404)

        self.get('domains/2fdadfb1cf964259ac6bbb7b6d2ff980', status_code=404)

    def test_update_domain(self):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        response = self.put('domains/%s' % domain['id'], data=data)

        self.assertIn('id', response.json)
        self.assertEqual(response.json['id'], domain['id'])

        self.assertIn('email', response.json)
        self.assertEqual(response.json['email'], 'prefix-%s' % domain['email'])

    def test_update_domain_junk(self):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email'], 'junk': 'Junk Field'}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    def test_update_domain_name_fail(self):
        # Create a domain
        domain = self.create_domain()

        data = {'name': 'renamed.com.'}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    def test_update_domain_null_ttl(self):
        # Create a domain
        domain = self.create_domain()

        data = {'ttl': None}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    def test_update_domain_negative_ttl(self):
        # Create a domain
        domain = self.create_domain()

        data = {'ttl': -1}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    @patch.object(central_service.Service,
                  'update_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_update_domain_timeout(self, _):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        self.put('domains/%s' % domain['id'], data=data, status_code=504)

    @patch.object(central_service.Service,
                  'update_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_update_domain_duplicate(self, _):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        self.put('domains/%s' % domain['id'], data=data, status_code=409)

    def test_update_domain_missing(self):
        data = {'email': '*****@*****.**'}

        self.put('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                 data=data,
                 status_code=404)

    def test_update_domain_invalid_id(self):
        data = {'email': '*****@*****.**'}

        # The letter "G" is not valid in a UUID
        self.put('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                 data=data,
                 status_code=404)

        self.put('domains/2fdadfb1cf964259ac6bbb7b6d2ff980',
                 data=data,
                 status_code=404)

    def test_delete_domain(self):
        # Create a domain
        domain = self.create_domain()

        self.delete('domains/%s' % domain['id'])

        # Simulate the domain having been deleted on the backend
        domain_serial = self.central_service.get_domain(
            self.admin_context, domain['id']).serial
        self.central_service.update_status(self.admin_context, domain['id'],
                                           "SUCCESS", domain_serial)

        # Ensure we can no longer fetch the domain
        self.get('domains/%s' % domain['id'], status_code=404)

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_delete_domain_timeout(self, _):
        # Create a domain
        domain = self.create_domain()

        self.delete('domains/%s' % domain['id'], status_code=504)

    def test_delete_domain_missing(self):
        self.delete('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                    status_code=404)

    def test_delete_domain_invalid_id(self):
        # The letter "G" is not valid in a UUID
        self.delete('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                    status_code=404)

        self.delete('domains/2fdadfb1cf964259ac6bbb7b6d2ff980',
                    status_code=404)

    def test_get_secondary_missing(self):
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        domain = self.create_domain(**fixture)

        self.get('domains/%s' % domain.id, status_code=404)

    def test_update_secondary_missing(self):
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        domain = self.create_domain(**fixture)

        self.put('domains/%s' % domain.id, {}, status_code=404)

    def test_delete_secondary_missing(self):
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        domain = self.create_domain(**fixture)
        self.delete('domains/%s' % domain.id, status_code=404)

    def test_get_domain_servers_from_secondary(self):
        fixture = self.get_domain_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        domain = self.create_domain(**fixture)
        self.get('domains/%s/servers' % domain.id, status_code=404)
Ejemplo n.º 7
0
class ApiV1DomainsTest(ApiV1Test):
    __test__ = True

    def test_create_domain(self):
        # Create a server
        self.create_server()

        # Create a domain
        fixture = self.get_domain_fixture(0)

        response = self.post('domains', data=fixture)

        self.assertIn('id', response.json)
        self.assertIn('name', response.json)
        self.assertEqual(response.json['name'], fixture['name'])

    @patch.object(central_service.Service, 'create_domain')
    def test_create_domain_trailing_slash(self, mock):
        # Create a server
        self.create_server()
        self.post('domains/', data=self.get_domain_fixture(0))

        # verify that the central service is called
        self.assertTrue(mock.called)

    def test_create_domain_junk(self):
        # Create a server
        self.create_server()

        # Create a domain
        fixture = self.get_domain_fixture(0)

        # Add a junk property
        fixture['junk'] = 'Junk Field'

        # Ensure it fails with a 400
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_no_servers(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        self.post('domains', data=fixture, status_code=500)

    @patch.object(central_service.Service, 'create_domain',
                  side_effect=rpc_common.Timeout())
    def test_create_domain_timeout(self, _):
        # Create a domain
        fixture = self.get_domain_fixture(0)

        self.post('domains', data=fixture, status_code=504)

    @patch.object(central_service.Service, 'create_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_create_domain_duplicate(self, _):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        self.post('domains', data=fixture, status_code=409)

    def test_create_domain_null_ttl(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['ttl'] = None
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_negative_ttl(self):
        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['ttl'] = -1
        self.post('domains', data=fixture, status_code=400)

    def test_create_domain_utf_description(self):
        # Create a server
        self.create_server()

        # Create a domain
        fixture = self.get_domain_fixture(0)

        #Give it a UTF-8 filled description
        fixture['description'] = "utf-8:2H₂+O₂⇌2H₂O,R=4.7kΩ,⌀200mm∮E⋅da=Q,n" \
                                 ",∑f(i)=∏g(i),∀x∈ℝ:⌈x⌉"
        #Create the domain, ensuring it suceeds, thus UTF-8 is supported
        self.post('domains', data=fixture)

    def test_create_domain_description_too_long(self):
        # Create a server
        self.create_server()

        # Create a domain
        fixture = self.get_domain_fixture(0)
        fixture['description'] = "x" * 161

        #Create the domain, ensuring it fails with a 400
        self.post('domains', data=fixture, status_code=400)

    def test_create_invalid_name(self):
        # Prepare a domain
        fixture = self.get_domain_fixture(0)

        invalid_names = [
            'org',
            'example.org',
            'example.321',
        ]

        for invalid_name in invalid_names:
            fixture['name'] = invalid_name

            # Create a record
            response = self.post('domains', data=fixture, status_code=400)

            self.assertNotIn('id', response.json)

    def test_create_invalid_email(self):
        # Prepare a domain
        fixture = self.get_domain_fixture(0)

        invalid_emails = [
            'org',
            'example.org',
            'bla.example.org',
            'org.',
            'example.org.',
            'bla.example.org.',
            'bla.example.org.',
        ]

        for invalid_email in invalid_emails:
            fixture['email'] = invalid_email

            # Create a record
            response = self.post('domains', data=fixture, status_code=400)

            self.assertNotIn('id', response.json)

    def test_get_domains(self):
        response = self.get('domains')

        self.assertIn('domains', response.json)
        self.assertEqual(0, len(response.json['domains']))

        # Create a domain
        self.create_domain()

        response = self.get('domains')

        self.assertIn('domains', response.json)
        self.assertEqual(1, len(response.json['domains']))

        # Create a second domain
        self.create_domain(fixture=1)

        response = self.get('domains')

        self.assertIn('domains', response.json)
        self.assertEqual(2, len(response.json['domains']))

    @patch.object(central_service.Service, 'find_domains')
    def test_get_domains_trailing_slash(self, mock):
        self.get('domains/')

        # verify that the central service is called
        self.assertTrue(mock.called)

    @patch.object(central_service.Service, 'find_domains',
                  side_effect=rpc_common.Timeout())
    def test_get_domains_timeout(self, _):
        self.get('domains', status_code=504)

    def test_get_domain(self):
        # Create a domain
        domain = self.create_domain()

        response = self.get('domains/%s' % domain['id'])

        self.assertIn('id', response.json)
        self.assertEqual(response.json['id'], domain['id'])

    @patch.object(central_service.Service, 'get_domain')
    def test_get_domain_trailing_slash(self, mock):
        # Create a domain
        domain = self.create_domain()

        self.get('domains/%s/' % domain['id'])

        # verify that the central service is called
        self.assertTrue(mock.called)

    @patch.object(central_service.Service, 'get_domain',
                  side_effect=rpc_common.Timeout())
    def test_get_domain_timeout(self, _):
        # Create a domain
        domain = self.create_domain()

        self.get('domains/%s' % domain['id'], status_code=504)

    def test_get_domain_missing(self):
        self.get('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                 status_code=404)

    def test_get_domain_invalid_id(self):
        # The letter "G" is not valid in a UUID
        self.get('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                 status_code=404)

        self.get('domains/2fdadfb1cf964259ac6bbb7b6d2ff980', status_code=404)

    def test_update_domain(self):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        response = self.put('domains/%s' % domain['id'], data=data)

        self.assertIn('id', response.json)
        self.assertEqual(response.json['id'], domain['id'])

        self.assertIn('email', response.json)
        self.assertEqual(response.json['email'], 'prefix-%s' % domain['email'])

    @patch.object(central_service.Service, 'update_domain')
    def test_update_domain_trailing_slash(self, mock):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        self.put('domains/%s/' % domain['id'], data=data)

        # verify that the central service is called
        self.assertTrue(mock.called)

    def test_update_domain_junk(self):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email'], 'junk': 'Junk Field'}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    def test_update_domain_name_fail(self):
        # Create a domain
        domain = self.create_domain()

        data = {'name': 'renamed.com.'}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    def test_update_domain_null_ttl(self):
        # Create a domain
        domain = self.create_domain()

        data = {'ttl': None}

        self.put('domains/%s' % domain['id'], data=data, status_code=400)

    @patch.object(central_service.Service, 'update_domain',
                  side_effect=rpc_common.Timeout())
    def test_update_domain_timeout(self, _):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        self.put('domains/%s' % domain['id'], data=data, status_code=504)

    @patch.object(central_service.Service, 'update_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_update_domain_duplicate(self, _):
        # Create a domain
        domain = self.create_domain()

        data = {'email': 'prefix-%s' % domain['email']}

        self.put('domains/%s' % domain['id'], data=data, status_code=409)

    def test_update_domain_missing(self):
        data = {'email': '*****@*****.**'}

        self.put('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980', data=data,
                 status_code=404)

    def test_update_domain_invalid_id(self):
        data = {'email': '*****@*****.**'}

        # The letter "G" is not valid in a UUID
        self.put('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG', data=data,
                 status_code=404)

        self.put('domains/2fdadfb1cf964259ac6bbb7b6d2ff980', data=data,
                 status_code=404)

    def test_delete_domain(self):
        # Create a domain
        domain = self.create_domain()

        self.delete('domains/%s' % domain['id'])

        # Esnure we can no longer fetch the domain
        self.get('domains/%s' % domain['id'], status_code=404)

    @patch.object(central_service.Service, 'delete_domain')
    def test_delete_domain_trailing_slash(self, mock):
        # Create a domain
        domain = self.create_domain()

        self.delete('domains/%s/' % domain['id'])

        # verify that the central service is called
        self.assertTrue(mock.called)

    @patch.object(central_service.Service, 'delete_domain',
                  side_effect=rpc_common.Timeout())
    def test_delete_domain_timeout(self, _):
        # Create a domain
        domain = self.create_domain()

        self.delete('domains/%s' % domain['id'], status_code=504)

    def test_delete_domain_missing(self):
        self.delete('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980',
                    status_code=404)

    def test_delete_domain_invalid_id(self):
        # The letter "G" is not valid in a UUID
        self.delete('domains/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff9GG',
                    status_code=404)

        self.delete('domains/2fdadfb1cf964259ac6bbb7b6d2ff980',
                    status_code=404)
Ejemplo n.º 8
0
 def get_response(self, request):
     raise exceptions.DuplicateDomain()
Ejemplo n.º 9
0
class ApiV2RecordSetsTest(ApiV2TestCase):
    def setUp(self):
        super(ApiV2RecordSetsTest, self).setUp()

        # Create a domain
        self.domain = self.create_domain()

    def test_create_recordset(self):
        # Create a zone
        fixture = self.get_recordset_fixture(self.domain['name'], fixture=0)
        response = self.client.post_json(
            '/zones/%s/recordsets' % self.domain['id'], {'recordset': fixture})

        # Check the headers are what we expect
        self.assertEqual(201, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('recordset', response.json)
        self.assertIn('links', response.json['recordset'])
        self.assertIn('self', response.json['recordset']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['recordset'])
        self.assertIn('created_at', response.json['recordset'])
        self.assertIsNone(response.json['recordset']['updated_at'])

        for k in fixture:
            self.assertEqual(fixture[k], response.json['recordset'][k])

    def test_create_recordset_validation(self):
        # NOTE: The schemas should be tested separatly to the API. So we
        #       don't need to test every variation via the API itself.
        # Fetch a fixture
        fixture = self.get_recordset_fixture(self.domain['name'], fixture=0)

        # Add a junk field to the wrapper
        body = {'recordset': fixture, 'junk': 'Junk Field'}

        # Ensure it fails with a 400
        response = self.client.post_json('/zones/%s/recordsets' %
                                         self.domain['id'],
                                         body,
                                         status=400)

        self.assertEqual(400, response.status_int)

        # Add a junk field to the body
        fixture['junk'] = 'Junk Field'
        body = {'recordset': fixture}

        # Ensure it fails with a 400
        response = self.client.post_json('/zones/%s/recordsets' %
                                         self.domain['id'],
                                         body,
                                         status=400)

    @patch.object(central_service.Service,
                  'create_recordset',
                  side_effect=rpc_common.Timeout())
    def test_create_recordset_timeout(self, _):
        fixture = self.get_recordset_fixture(self.domain['name'], fixture=0)

        body = {'recordset': fixture}
        self.client.post_json('/zones/%s/recordsets' % self.domain['id'],
                              body,
                              status=504)

    @patch.object(central_service.Service,
                  'create_recordset',
                  side_effect=exceptions.DuplicateDomain())
    def test_create_recordset_duplicate(self, _):
        fixture = self.get_recordset_fixture(self.domain['name'], fixture=0)

        body = {'recordset': fixture}
        self.client.post_json('/zones/%s/recordsets' % self.domain['id'],
                              body,
                              status=409)

    def test_create_recordset_invalid_domain(self):
        fixture = self.get_recordset_fixture(self.domain['name'], fixture=0)

        body = {'recordset': fixture}
        self.client.post_json(
            '/zones/ba751950-6193-11e3-949a-0800200c9a66/recordsets',
            body,
            status=404)

    def test_get_recordsets(self):
        response = self.client.get('/zones/%s/recordsets' % self.domain['id'])

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('recordsets', response.json)
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # We should start with 0 recordsets
        self.assertEqual(0, len(response.json['recordsets']))

        data = [
            self.create_recordset(self.domain,
                                  name='x-%s.%s' % (i, self.domain['name']))
            for i in xrange(0, 10)
        ]

        url = '/zones/%s/recordsets' % self.domain['id']
        self._assert_paging(data, url, key='recordsets')

    @patch.object(central_service.Service,
                  'find_recordsets',
                  side_effect=rpc_common.Timeout())
    def test_get_recordsets_timeout(self, _):
        self.client.get(
            '/zones/ba751950-6193-11e3-949a-0800200c9a66/recordsets',
            status=504)

    def test_get_recordset(self):
        # Create a recordset
        recordset = self.create_recordset(self.domain)

        url = '/zones/%s/recordsets/%s' % (self.domain['id'], recordset['id'])
        response = self.client.get(url)

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('recordset', response.json)
        self.assertIn('links', response.json['recordset'])
        self.assertIn('self', response.json['recordset']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['recordset'])
        self.assertIn('created_at', response.json['recordset'])
        self.assertIsNone(response.json['recordset']['updated_at'])
        self.assertEqual(recordset['name'], response.json['recordset']['name'])
        self.assertEqual(recordset['type'], response.json['recordset']['type'])

    @patch.object(central_service.Service,
                  'get_recordset',
                  side_effect=rpc_common.Timeout())
    def test_get_recordset_timeout(self, _):
        self.client.get('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c'
                        '9a66' % self.domain['id'],
                        headers={'Accept': 'application/json'},
                        status=504)

    @patch.object(central_service.Service,
                  'get_recordset',
                  side_effect=exceptions.RecordSetNotFound())
    def test_get_recordset_missing(self, _):
        self.client.get('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c'
                        '9a66' % self.domain['id'],
                        headers={'Accept': 'application/json'},
                        status=404)

    def test_get_recordset_invalid_id(self):
        self.skip('We don\'t guard against this in APIv2 yet')

    def test_update_recordset(self):
        # Create a recordset
        recordset = self.create_recordset(self.domain)

        # Prepare an update body
        body = {'recordset': {'description': 'Tester'}}

        url = '/zones/%s/recordsets/%s' % (recordset['domain_id'],
                                           recordset['id'])
        response = self.client.patch_json(url, body, status=200)

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('recordset', response.json)
        self.assertIn('links', response.json['recordset'])
        self.assertIn('self', response.json['recordset']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['recordset'])
        self.assertIsNotNone(response.json['recordset']['updated_at'])
        self.assertEqual('Tester', response.json['recordset']['description'])

    def test_update_recordset_validation(self):
        # NOTE: The schemas should be tested separatly to the API. So we
        #       don't need to test every variation via the API itself.
        # Create a zone
        recordset = self.create_recordset(self.domain)

        # Prepare an update body with junk in the wrapper
        body = {'recordset': {'description': 'Tester'}, 'junk': 'Junk Field'}

        # Ensure it fails with a 400
        url = '/zones/%s/recordsets/%s' % (recordset['domain_id'],
                                           recordset['id'])
        self.client.patch_json(url, body, status=400)

        # Prepare an update body with junk in the body
        body = {'recordset': {'description': 'Tester', 'junk': 'Junk Field'}}

        # Ensure it fails with a 400
        url = '/zones/%s/recordsets/%s' % (recordset['domain_id'],
                                           recordset['id'])
        self.client.patch_json(url, body, status=400)

    @patch.object(central_service.Service,
                  'get_recordset',
                  side_effect=exceptions.DuplicateRecordSet())
    def test_update_recordset_duplicate(self, _):
        # Prepare an update body
        body = {'recordset': {'description': 'Tester'}}

        # Ensure it fails with a 409
        url = ('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c9a66' %
               (self.domain['id']))
        self.client.patch_json(url, body, status=409)

    @patch.object(central_service.Service,
                  'get_recordset',
                  side_effect=rpc_common.Timeout())
    def test_update_recordset_timeout(self, _):
        # Prepare an update body
        body = {'recordset': {'description': 'Tester'}}

        # Ensure it fails with a 504
        url = ('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c9a66' %
               (self.domain['id']))
        self.client.patch_json(url, body, status=504)

    @patch.object(central_service.Service,
                  'get_recordset',
                  side_effect=exceptions.RecordSetNotFound())
    def test_update_recordset_missing(self, _):
        # Prepare an update body
        body = {'recordset': {'description': 'Tester'}}

        # Ensure it fails with a 404
        url = ('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c9a66' %
               (self.domain['id']))
        self.client.patch_json(url, body, status=404)

    def test_update_recordset_invalid_id(self):
        self.skip('We don\'t guard against this in APIv2 yet')

    def test_delete_recordset(self):
        recordset = self.create_recordset(self.domain)

        url = '/zones/%s/recordsets/%s' % (recordset['domain_id'],
                                           recordset['id'])
        self.client.delete(url, status=204)

    @patch.object(central_service.Service,
                  'delete_recordset',
                  side_effect=rpc_common.Timeout())
    def test_delete_recordset_timeout(self, _):
        url = ('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c9a66' %
               (self.domain['id']))

        self.client.delete(url, status=504)

    @patch.object(central_service.Service,
                  'delete_recordset',
                  side_effect=exceptions.RecordSetNotFound())
    def test_delete_recordset_missing(self, _):
        url = ('/zones/%s/recordsets/ba751950-6193-11e3-949a-0800200c9a66' %
               (self.domain['id']))
        self.client.delete(url, status=404)

    def test_delete_recordset_invalid_id(self):
        self.skip('We don\'t guard against this in APIv2 yet')
Ejemplo n.º 10
0
class ApiV2ZonesTest(ApiV2TestCase):
    def setUp(self):
        super(ApiV2ZonesTest, self).setUp()

        # Create a server
        self.create_server()

        # Create the default TLDs
        self.create_default_tlds()

    def test_create_zone(self):
        # Create a zone
        fixture = self.get_domain_fixture(0)
        response = self.client.post_json('/zones/', {'zone': fixture})

        # Check the headers are what we expect
        self.assertEqual(201, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zone', response.json)
        self.assertIn('links', response.json['zone'])
        self.assertIn('self', response.json['zone']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['zone'])
        self.assertIn('created_at', response.json['zone'])
        self.assertEqual('ACTIVE', response.json['zone']['status'])
        self.assertIsNone(response.json['zone']['updated_at'])

        for k in fixture:
            self.assertEqual(fixture[k], response.json['zone'][k])

    def test_create_zone_validation(self):
        # NOTE: The schemas should be tested separately to the API. So we
        #       don't need to test every variation via the API itself.
        # Fetch a fixture
        fixture = self.get_domain_fixture(0)

        # Add a junk field to the wrapper
        body = {'zone': fixture, 'junk': 'Junk Field'}

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

        # Add a junk field to the body
        fixture['junk'] = 'Junk Field'

        # Ensure it fails with a 400
        body = {'zone': fixture}

        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_body_validation(self):
        fixture = self.get_domain_fixture(0)
        # Add id to the body
        fixture['id'] = '2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        # Ensure it fails with a 400
        body = {'zone': fixture}
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

        fixture = self.get_domain_fixture(0)
        # Add created_at to the body
        fixture['created_at'] = '2014-03-12T19:07:53.000000'
        # Ensure it fails with a 400
        body = {'zone': fixture}
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_invalid_name(self):
        # Try to create a zone with an invalid name
        fixture = self.get_domain_fixture(-1)

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', {'zone': fixture})

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_create_zone_timeout(self, _):
        fixture = self.get_domain_fixture(0)

        body = {'zone': fixture}

        self._assert_exception('timeout', 504, self.client.post_json,
                               '/zones/', body)

    @patch.object(central_service.Service,
                  'create_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_create_zone_duplicate(self, _):
        fixture = self.get_domain_fixture(0)

        body = {'zone': fixture}

        self._assert_exception('duplicate_domain', 409, self.client.post_json,
                               '/zones/', body)

    def test_create_zone_missing_content_type(self):
        self._assert_exception('unsupported_content_type', 415,
                               self.client.post, '/zones')

    def test_create_zone_bad_content_type(self):
        self._assert_exception('unsupported_content_type',
                               415,
                               self.client.post,
                               '/zones',
                               headers={'Content-type': 'test/goat'})

    def test_zone_invalid_url(self):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980/invalid'
        self._assert_exception('not_found',
                               404,
                               self.client.get,
                               url,
                               headers={'Accept': 'application/json'})
        self._assert_exception('not_found', 404, self.client.patch_json, url)
        self._assert_exception('not_found', 404, self.client.delete, url)

        # Pecan returns a 405 for post
        response = self.client.post(url, status=405)
        self.assertEqual(405, response.status_int)

    def test_get_zones(self):
        response = self.client.get('/zones/')

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zones', response.json)
        self.assertIn('links', response.json)
        self.assertIn('self', response.json['links'])

        # We should start with 0 zones
        self.assertEqual(0, len(response.json['zones']))

        # We should start with 0 zones
        self.assertEqual(0, len(response.json['zones']))

        data = [self.create_domain(name='x-%s.com.' % i) for i in 'abcdefghij']
        self._assert_paging(data, '/zones', key='zones')

        self._assert_invalid_paging(data, '/zones', key='zones')

    @patch.object(central_service.Service,
                  'find_domains',
                  side_effect=messaging.MessagingTimeout())
    def test_get_zones_timeout(self, _):
        self._assert_exception('timeout', 504, self.client.get, '/zones/')

    def test_get_zone(self):
        # Create a zone
        zone = self.create_domain()

        response = self.client.get('/zones/%s' % zone['id'],
                                   headers=[('Accept', 'application/json')])

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zone', response.json)
        self.assertIn('links', response.json['zone'])
        self.assertIn('self', response.json['zone']['links'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['zone'])
        self.assertIn('created_at', response.json['zone'])
        self.assertEqual('ACTIVE', response.json['zone']['status'])
        self.assertIsNone(response.json['zone']['updated_at'])
        self.assertEqual(zone['name'], response.json['zone']['name'])
        self.assertEqual(zone['email'], response.json['zone']['email'])

    def test_get_zone_invalid_id(self):
        self._assert_invalid_uuid(self.client.get, '/zones/%s')

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_get_zone_timeout(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        self._assert_exception('timeout',
                               504,
                               self.client.get,
                               url,
                               headers={'Accept': 'application/json'})

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_get_zone_missing(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        self._assert_exception('domain_not_found',
                               404,
                               self.client.get,
                               url,
                               headers={'Accept': 'application/json'})

    def test_get_zone_missing_accept(self):
        url = '/zones/6e2146f3-87bc-4f47-adc5-4df0a5c78218'

        self._assert_exception('bad_request', 400, self.client.get, url)

    def test_get_zone_bad_accept(self):
        url = '/zones/6e2146f3-87bc-4f47-adc5-4df0a5c78218'

        self.client.get(url, headers={'Accept': 'test/goat'}, status=406)

    def test_update_zone(self):
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body
        body = {'zone': {'email': 'prefix-%s' % zone['email']}}

        response = self.client.patch_json('/zones/%s' % zone['id'],
                                          body,
                                          status=200)

        # Check the headers are what we expect
        self.assertEqual(200, response.status_int)
        self.assertEqual('application/json', response.content_type)

        # Check the body structure is what we expect
        self.assertIn('zone', response.json)
        self.assertIn('links', response.json['zone'])
        self.assertIn('self', response.json['zone']['links'])
        self.assertIn('status', response.json['zone'])

        # Check the values returned are what we expect
        self.assertIn('id', response.json['zone'])
        self.assertIsNotNone(response.json['zone']['updated_at'])
        self.assertEqual('prefix-%s' % zone['email'],
                         response.json['zone']['email'])

    def test_update_zone_invalid_id(self):
        self._assert_invalid_uuid(self.client.patch_json, '/zones/%s')

    def test_update_zone_validation(self):
        # NOTE: The schemas should be tested separatly to the API. So we
        #       don't need to test every variation via the API itself.
        # Create a zone
        zone = self.create_domain()

        # Prepare an update body with junk in the wrapper
        body = {
            'zone': {
                'email': 'prefix-%s' % zone['email']
            },
            'junk': 'Junk Field'
        }

        url = '/zones/%s' % zone['id']

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.patch_json,
                               url, body)

        # Prepare an update body with junk in the body
        body = {
            'zone': {
                'email': 'prefix-%s' % zone['email'],
                'junk': 'Junk Field'
            }
        }

        # Ensure it fails with a 400
        self._assert_exception('invalid_object', 400, self.client.patch_json,
                               url, body)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DuplicateDomain())
    def test_update_zone_duplicate(self, _):
        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        # Ensure it fails with a 409
        self._assert_exception('duplicate_domain', 409, self.client.patch_json,
                               url, body)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_update_zone_timeout(self, _):
        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        # Ensure it fails with a 504
        self._assert_exception('timeout', 504, self.client.patch_json, url,
                               body)

    @patch.object(central_service.Service,
                  'get_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_update_zone_missing(self, _):
        # Prepare an update body
        body = {'zone': {'email': '*****@*****.**'}}

        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        # Ensure it fails with a 404
        self._assert_exception('domain_not_found', 404, self.client.patch_json,
                               url, body)

    def test_delete_zone(self):
        zone = self.create_domain()

        self.client.delete('/zones/%s' % zone['id'], status=204)

    def test_delete_zone_invalid_id(self):
        self._assert_invalid_uuid(self.client.delete, '/zones/%s')

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=messaging.MessagingTimeout())
    def test_delete_zone_timeout(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        self._assert_exception('timeout', 504, self.client.delete, url)

    @patch.object(central_service.Service,
                  'delete_domain',
                  side_effect=exceptions.DomainNotFound())
    def test_delete_zone_missing(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

        self._assert_exception('domain_not_found', 404, self.client.delete,
                               url)

    # Zone import/export
    def test_missing_origin(self):
        fixture = self.get_zonefile_fixture(variant='noorigin')

        self._assert_exception('bad_request',
                               400,
                               self.client.post,
                               '/zones',
                               fixture,
                               headers={'Content-type': 'text/dns'})

    def test_missing_soa(self):
        fixture = self.get_zonefile_fixture(variant='nosoa')

        self._assert_exception('bad_request',
                               400,
                               self.client.post,
                               '/zones',
                               fixture,
                               headers={'Content-type': 'text/dns'})

    def test_malformed_zonefile(self):
        fixture = self.get_zonefile_fixture(variant='malformed')

        self._assert_exception('bad_request',
                               400,
                               self.client.post,
                               '/zones',
                               fixture,
                               headers={'Content-type': 'text/dns'})

    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)