예제 #1
0
class ApiV1zonesTest(ApiV1Test):
    def test_get_zone_schema(self):
        response = self.get('schemas/domain')
        self.assertIn('description', response.json)
        self.assertIn('links', response.json)
        self.assertIn('title', response.json)
        self.assertIn('id', response.json)
        self.assertIn('additionalProperties', response.json)
        self.assertIn('properties', response.json)
        self.assertIn('description', response.json['properties'])
        self.assertIn('created_at', response.json['properties'])
        self.assertIn('updated_at', response.json['properties'])
        self.assertIn('name', response.json['properties'])
        self.assertIn('email', response.json['properties'])
        self.assertIn('ttl', response.json['properties'])
        self.assertIn('serial', response.json['properties'])

    def test_get_zones_schema(self):
        response = self.get('schemas/domains')
        self.assertIn('description', response.json)
        self.assertIn('additionalProperties', response.json)
        self.assertIn('properties', response.json)
        self.assertIn('title', response.json)
        self.assertIn('id', response.json)

    def test_create_zone(self):
        # Create a zone
        fixture = self.get_zone_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_zone_junk(self):
        # Create a zone
        fixture = self.get_zone_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_zone',
                  side_effect=messaging.MessagingTimeout())
    def test_create_zone_timeout(self, _):
        # Create a zone
        fixture = self.get_zone_fixture(0)

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

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

    @patch.object(central_service.Service, 'create_zone',
                  side_effect=exceptions.DuplicateZone())
    def test_create_zone_duplicate(self, _):
        # Create a zone
        fixture = self.get_zone_fixture(0)

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

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

    def test_create_zone_null_ttl(self):
        # Create a zone
        fixture = self.get_zone_fixture(0)
        fixture['ttl'] = None
        self.post('domains', data=fixture, status_code=400)

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

    def test_create_zone_zero_ttl(self):
        # Create a zone
        fixture = self.get_zone_fixture(0)
        fixture['ttl'] = 0
        self.post('domains', data=fixture, status_code=400)

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

    def test_create_zone_ttl_greater_than_max(self):
        fixture = self.get_zone_fixture(0)
        fixture['ttl'] = 2147483648
        self.post('domains', data=fixture, status_code=400)

    def test_create_zone_utf_description(self):
        # Create a zone
        fixture = self.get_zone_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 zone, ensuring it succeeds, thus UTF-8 is supported
        self.post('domains', data=fixture)

    def test_create_zone_description_too_long(self):
        # Create a zone
        fixture = self.get_zone_fixture(0)
        fixture['description'] = "x" * 161

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

    def test_create_zone_with_unwanted_attributes(self):

        zone_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 zone
        fixture = self.get_zone_fixture(0)
        fixture['id'] = zone_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 zone
        fixture = self.get_zone_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_zone_name_too_long(self):
        fixture = self.get_zone_fixture(0)

        long_name = 'a' * 255 + ".org."
        fixture['name'] = long_name

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

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

    def test_create_zone_name_is_not_present(self):
        fixture = self.get_zone_fixture(0)
        del fixture['name']
        self.post('domains', data=fixture, status_code=400)

    def test_create_invalid_email(self):
        # Prepare a zone
        fixture = self.get_zone_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_create_zone_email_too_long(self):
        fixture = self.get_zone_fixture(0)

        long_email = 'a' * 255 + "@org.com"
        fixture['email'] = long_email

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

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

    def test_create_zone_email_not_present(self):
        fixture = self.get_zone_fixture(0)
        del fixture['email']
        self.post('domains', data=fixture, status_code=400)

    def test_create_zone_twice(self):
        self.create_zone()
        with testtools.ExpectedException(exceptions.DuplicateZone):
            self.create_zone()

    def test_create_zone_pending_deletion(self):
        zone = self.create_zone()
        self.delete('domains/%s' % zone['id'])
        with testtools.ExpectedException(exceptions.DuplicateZone):
            self.create_zone()

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

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

        # Create a zone
        self.create_zone()

        response = self.get('domains')

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

        # Create a second zone
        self.create_zone(fixture=1)

        response = self.get('domains')

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

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

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

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

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

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

    @patch.object(central_service.Service, 'find_zone',
                  side_effect=messaging.MessagingTimeout())
    def test_get_zone_timeout(self, _):
        # Create a zone
        zone = self.create_zone()

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

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

    def test_get_zone_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_zone(self):
        # Create a zone
        zone = self.create_zone()

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

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

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

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

    def test_update_zone_junk(self):
        # Create a zone
        zone = self.create_zone()

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

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

    def test_update_zone_name_fail(self):
        # Create a zone
        zone = self.create_zone()

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

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

    def test_update_zone_null_ttl(self):
        # Create a zone
        zone = self.create_zone()

        data = {'ttl': None}

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

    def test_update_zone_negative_ttl(self):
        # Create a zone
        zone = self.create_zone()

        data = {'ttl': -1}

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

    def test_update_zone_zero_ttl(self):
        # Create a zone
        zone = self.create_zone()

        data = {'ttl': 0}

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

    @patch.object(central_service.Service, 'update_zone',
                  side_effect=messaging.MessagingTimeout())
    def test_update_zone_timeout(self, _):
        # Create a zone
        zone = self.create_zone()

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

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

    @patch.object(central_service.Service, 'update_zone',
                  side_effect=exceptions.DuplicateZone())
    def test_update_zone_duplicate(self, _):
        # Create a zone
        zone = self.create_zone()

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

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

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

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

    def test_update_zone_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_update_zone_ttl_greter_than_max(self):
        # Create a zone
        zone = self.create_zone()

        data = {'ttl': 2147483648}

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

    def test_update_zone_invalid_email(self):
        # Create a zone
        zone = self.create_zone()

        invalid_emails = [
            'org',
            'example.org',
            'bla.example.org',
            'org.',
            'example.org.',
            'bla.example.org.',
            'bla.example.org.',
            'a' * 255 + "@com",
            ''
        ]

        for invalid_email in invalid_emails:
            data = {'email': invalid_email}
            self.put('domains/%s' % zone['id'], data=data, status_code=400)

    def test_update_zone_description_too_long(self):
        # Create a zone
        zone = self.create_zone()

        invalid_des = 'a' * 165

        data = {'description': invalid_des}
        self.put('domains/%s' % zone['id'], data=data, status_code=400)

    def test_update_zone_in_pending_deletion(self):
        zone = self.create_zone()
        self.delete('domains/%s' % zone['id'])
        self.put('domains/%s' % zone['id'], data={}, status_code=404)

    def test_delete_zone(self):
        # Create a zone
        zone = self.create_zone()

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

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

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

    def test_zone_in_pending_deletion(self):
        zone1 = self.create_zone()
        self.create_zone(fixture=1)
        response = self.get('domains')
        self.assertEqual(2, len(response.json['domains']))

        # Delete zone1
        self.delete('domains/%s' % zone1['id'])

        # Ensure we can no longer list nor fetch the deleted zone
        response = self.get('domains')
        self.assertEqual(1, len(response.json['domains']))

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

    @patch.object(central_service.Service, 'delete_zone',
                  side_effect=messaging.MessagingTimeout())
    def test_delete_zone_timeout(self, _):
        # Create a zone
        zone = self.create_zone()

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

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

    def test_delete_zone_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_zone_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        zone = self.create_zone(**fixture)

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

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

        zone = self.create_zone(**fixture)

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

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

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

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

        zone = self.create_zone(**fixture)
        self.get('domains/%s/servers' % zone.id, status_code=404)
예제 #2
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_zone_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_zone_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_zone_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_email_too_long(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture.update({'email': 'a' * 255 + '@abc.com'})
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_invalid_email(self):
        invalid_emails = [
            'org',
            'example.org',
            'bla.example.org',
            'org.',
            'example.org.',
            'bla.example.org.',
        ]
        fixture = self.get_zone_fixture(fixture=0)
        for email in invalid_emails:
            fixture.update({'email': email})
            body = fixture
            self._assert_exception('invalid_object', 400,
                                   self.client.post_json, '/zones', body)

    def test_create_zone_email_missing(self):
        fixture = self.get_zone_fixture(fixture=0)
        del fixture['email']
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_ttl_less_than_zero(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture['ttl'] = -1
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_ttl_is_zero(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture['ttl'] = 0
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_ttl_is_greater_than_max(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture['ttl'] = 2174483648
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_ttl_is_invalid(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture['ttl'] = "!@?>"
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_ttl_is_not_required_field(self):
        fixture = self.get_zone_fixture(fixture=0)
        body = fixture
        response = self.client.post_json('/zones', body)
        self.assertEqual(202, response.status_int)
        self.assertEqual('application/json', response.content_type)

    def test_create_zone_description_too_long(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture['description'] = "a" * 161
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_name_is_missing(self):
        fixture = self.get_zone_fixture(fixture=0)
        del fixture['name']
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_name_too_long(self):
        fixture = self.get_zone_fixture(fixture=0)
        fixture['name'] = 'x' * 255 + ".com"
        body = fixture
        self._assert_exception('invalid_object', 400, self.client.post_json,
                               '/zones', body)

    def test_create_zone_body_validation(self):
        fixture = self.get_zone_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_zone_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_zone_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_zone',
                  side_effect=messaging.MessagingTimeout())
    def test_create_zone_timeout(self, _):
        fixture = self.get_zone_fixture(fixture=0)

        body = fixture

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

    @patch.object(central_service.Service,
                  'create_zone',
                  side_effect=exceptions.DuplicateZone())
    def test_create_zone_duplicate(self, _):
        fixture = self.get_zone_fixture(fixture=0)

        body = fixture

        self._assert_exception('duplicate_zone', 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_zone(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_zones',
                  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_zone()

        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_zone',
                  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_zone',
                  side_effect=exceptions.ZoneNotFound())
    def test_get_zone_missing(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'
        self._assert_exception('zone_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_zone()

        # 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_zone()

        # 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_zone',
                  side_effect=exceptions.DuplicateZone())
    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_zone', 409, self.client.patch_json,
                               url, body)

    @patch.object(central_service.Service,
                  'get_zone',
                  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_zone',
                  side_effect=exceptions.ZoneNotFound())
    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('zone_not_found', 404, self.client.patch_json,
                               url, body)

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

        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'])

        # The deleted zone should still be listed
        zones = self.client.get('/zones/')
        self.assertEqual(1, len(zones.json['zones']))

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

    @patch.object(central_service.Service,
                  'delete_zone',
                  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_zone',
                  side_effect=exceptions.ZoneNotFound())
    def test_delete_zone_missing(self, _):
        url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980'

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

    def test_post_abandon_zone(self):
        zone = self.create_zone()
        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_zone': '@'})
        response = self.client.post_json(url)
        self.assertEqual(204, response.status_int)

    def test_get_abandon_zone(self):
        zone = self.create_zone()
        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_zone()
        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_zone_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_zone_fixture('SECONDARY', 0)

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

    def test_update_secondary(self):
        # Create a zone
        zone = objects.Zone(name='example.com.',
                            type='SECONDARY',
                            masters=objects.ZoneMasterList.from_list([{
                                'host':
                                '1.0.0.0',
                                'port':
                                69
                            }, {
                                'host':
                                '2.0.0.0',
                                'port':
                                69
                            }]))
        zone.email = cfg.CONF['service:central'].managed_resource_email

        # Create a zone
        zone = self.central_service.create_zone(self.admin_context, zone)

        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_zone_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email
        fixture['masters'] = [{"host": "10.0.0.10", "port": 53}]

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

        mdns = mock.Mock()
        with mock.patch.object(mdns_api.MdnsAPI, 'get_instance') as get_mdns:
            get_mdns.return_value = mdns
            mdns.get_serial_number.return_value = (
                'SUCCESS',
                10,
                1,
            )

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

        self.assertTrue(mdns.perform_zone_xfr.called)

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

    def test_invalid_xfr_request(self):
        # Create a zone
        zone = self.create_zone()

        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_zone_fixture('SECONDARY', 0)
        fixture['email'] = cfg.CONF['service:central'].managed_resource_email

        # Create a zone
        zone = self.create_zone(**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_zone_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_zone_fixture(fixture=0)
        response = self.client.post_json('/zones/', fixture)

        fixture = self.get_zone_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_zone()

        # 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_zone()

        # 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])

    def test_get_zones_filter(self):
        # Add zones for testing
        fixtures = [
            self.get_zone_fixture('PRIMARY',
                                  fixture=0,
                                  values={
                                      'ttl': 3600,
                                      'description': 'test1'
                                  }),
            self.get_zone_fixture('PRIMARY',
                                  fixture=1,
                                  values={
                                      'ttl': 4000,
                                      'description': 'test2'
                                  })
        ]

        for fixture in fixtures:
            response = self.client.post_json('/zones/', fixture)

        get_urls = [
            # Filter by Type
            '/zones?type=%s' % fixtures[0]['type'],

            # Filter by Name
            '/zones?name=%s' % fixtures[0]['name'],

            # Filter by Email
            '/zones?email=example*',
            '/zones?email=%s' % fixtures[1]['email'],

            # Filter by TTL
            '/zones?ttl=3600',

            # Filter by Description
            '/zones?description=test1',
            '/zones?description=test*'
        ]

        correct_results = [2, 1, 2, 1, 1, 1, 2]

        for get_url, correct_result in zip(get_urls, correct_results):

            response = self.client.get(get_url)

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

            # Check that the correct number of zones match
            self.assertEqual(correct_result, len(response.json['zones']))

    def test_invalid_zones_filter(self):
        invalid_url = '/zones?id=155477ef-e6c5-4b94-984d-8fc68c0c1a14'
        self._assert_exception('bad_request', 400, self.client.get,
                               invalid_url)
예제 #3
0
 def get_response(self, request):
     raise exceptions.DuplicateZone()