Fix zone transfer requests + add tempest tests
Change-Id: I904fa976b345135bbfa19aca8f39c97d063973fa Fixes-Bug: #1482270
This commit is contained in:
parent
d5c63b6ddb
commit
cad363aecd
@ -13,11 +13,11 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import six
|
||||
import pecan
|
||||
from oslo_log import log as logging
|
||||
|
||||
from designate import utils
|
||||
from designate import exceptions
|
||||
from designate.api.v2.controllers import rest
|
||||
from designate.objects import ZoneTransferRequest
|
||||
from designate.objects.adapters import DesignateAdapter
|
||||
@ -72,12 +72,8 @@ class TransferRequestsController(rest.RestController):
|
||||
context = request.environ['context']
|
||||
try:
|
||||
body = request.body_dict
|
||||
except Exception as e:
|
||||
if six.text_type(e) != 'TODO: Unsupported Content Type':
|
||||
raise
|
||||
else:
|
||||
# Got a blank body
|
||||
body = dict()
|
||||
except exceptions.EmptyRequestBody:
|
||||
body = dict()
|
||||
|
||||
body['zone_id'] = zone_id
|
||||
|
||||
|
@ -18,12 +18,13 @@ from inspect import getargspec
|
||||
|
||||
import six
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log as logging
|
||||
import pecan.core
|
||||
|
||||
from designate import exceptions
|
||||
|
||||
|
||||
JSON_TYPES = ('application/json', 'application/json-patch+json')
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Request(pecan.core.Request):
|
||||
@ -34,13 +35,16 @@ class Request(pecan.core.Request):
|
||||
Content-Type header.
|
||||
|
||||
We add this method to ease future XML support, so the main code
|
||||
is not hardcoded to call pecans "request.json()" method.
|
||||
is not hardcoded to call pecans "request.json" method.
|
||||
"""
|
||||
if self.content_type in JSON_TYPES:
|
||||
try:
|
||||
return jsonutils.load(self.body_file)
|
||||
except ValueError as valueError:
|
||||
raise exceptions.InvalidJson(six.text_type(valueError))
|
||||
if len(self.body) == 0:
|
||||
raise exceptions.EmptyRequestBody('Request Body is empty')
|
||||
else:
|
||||
raise exceptions.InvalidJson(six.text_type(valueError))
|
||||
else:
|
||||
raise exceptions.UnsupportedContentType(
|
||||
'Content-type must be application/json')
|
||||
|
@ -110,6 +110,11 @@ class BadRequest(Base):
|
||||
expected = True
|
||||
|
||||
|
||||
class EmptyRequestBody(BadRequest):
|
||||
error_type = 'empty_request_body'
|
||||
expected = True
|
||||
|
||||
|
||||
class InvalidUUID(BadRequest):
|
||||
error_type = 'invalid_uuid'
|
||||
|
||||
|
66
functionaltests/api/v2/clients/transfer_accepts_client.py
Normal file
66
functionaltests/api/v2/clients/transfer_accepts_client.py
Normal file
@ -0,0 +1,66 @@
|
||||
"""
|
||||
Copyright 2015 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from functionaltests.api.v2.models.transfer_accepts_model import \
|
||||
TransferAcceptsModel
|
||||
from functionaltests.api.v2.models.transfer_accepts_model import \
|
||||
TransferAcceptsListModel
|
||||
from functionaltests.common.client import ClientMixin
|
||||
|
||||
|
||||
class TransferAcceptClient(ClientMixin):
|
||||
|
||||
@classmethod
|
||||
def transfer_accepts_uri(cls, filters=None):
|
||||
url = "/v2/zones/tasks/transfer_accepts"
|
||||
if filters:
|
||||
url = cls.add_filters(url, filters)
|
||||
return url
|
||||
|
||||
@classmethod
|
||||
def transfer_accept_uri(cls, transfer_request_id):
|
||||
return "/v2/zones/tasks/transfer_accepts/{1}".format(
|
||||
transfer_request_id)
|
||||
|
||||
def list_transfer_accepts(self, zone_id, filters=None, **kwargs):
|
||||
resp, body = self.client.get(
|
||||
self.transfer_accepts_uri(filters), **kwargs)
|
||||
return self.deserialize(resp, body, TransferAcceptsListModel)
|
||||
|
||||
def get_transfer_accept(self, zone_id, transfer_request_id, **kwargs):
|
||||
resp, body = self.client.get(self.transfer_accept_uri(
|
||||
transfer_request_id),
|
||||
**kwargs)
|
||||
return self.deserialize(resp, body, TransferAcceptsModel)
|
||||
|
||||
def post_transfer_accept(self, transfer_request_model, **kwargs):
|
||||
resp, body = self.client.post(
|
||||
self.transfer_accepts_uri(),
|
||||
body=transfer_request_model.to_json(),
|
||||
**kwargs)
|
||||
return self.deserialize(resp, body, TransferAcceptsModel)
|
||||
|
||||
def put_transfer_accept(self, zone_id, transfer_request_id,
|
||||
transfer_request_model, **kwargs):
|
||||
resp, body = self.client.put(self.transfer_accept_uri(
|
||||
transfer_request_id),
|
||||
body=transfer_request_model.to_json(), **kwargs)
|
||||
return self.deserialize(resp, body, TransferAcceptsModel)
|
||||
|
||||
def delete_transfer_accept(self, zone_id, transfer_request_id, **kwargs):
|
||||
resp, body = self.client.delete(
|
||||
self.transfer_accept_uri(zone_id, transfer_request_id), **kwargs)
|
||||
return self.deserialize(resp, body, TransferAcceptsModel)
|
81
functionaltests/api/v2/clients/transfer_requests_client.py
Normal file
81
functionaltests/api/v2/clients/transfer_requests_client.py
Normal file
@ -0,0 +1,81 @@
|
||||
"""
|
||||
Copyright 2015 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from functionaltests.api.v2.models.transfer_requests_model import \
|
||||
TransferRequestsModel
|
||||
from functionaltests.api.v2.models.transfer_requests_model import \
|
||||
TransferRequestsListModel
|
||||
from functionaltests.common.client import ClientMixin
|
||||
|
||||
|
||||
class TransferRequestClient(ClientMixin):
|
||||
|
||||
@classmethod
|
||||
def create_transfer_requests_uri(cls, zone_id, filters=None):
|
||||
url = "/v2/zones/{0}/tasks/transfer_requests".format(zone_id)
|
||||
if filters:
|
||||
url = cls.add_filters(url, filters)
|
||||
return url
|
||||
|
||||
@classmethod
|
||||
def transfer_requests_uri(cls, filters=None):
|
||||
url = "/v2/zones/tasks/transfer_requests"
|
||||
if filters:
|
||||
url = cls.add_filters(url, filters)
|
||||
return url
|
||||
|
||||
@classmethod
|
||||
def transfer_request_uri(cls, transfer_request_id):
|
||||
return "/v2/zones/tasks/transfer_requests/{0}".format(
|
||||
transfer_request_id)
|
||||
|
||||
def list_transfer_requests(self, filters=None, **kwargs):
|
||||
resp, body = self.client.get(
|
||||
self.transfer_requests_uri(filters), **kwargs)
|
||||
return self.deserialize(resp, body, TransferRequestsListModel)
|
||||
|
||||
def get_transfer_request(self, transfer_request_id, **kwargs):
|
||||
resp, body = self.client.get(self.transfer_request_uri(
|
||||
transfer_request_id),
|
||||
**kwargs)
|
||||
return self.deserialize(resp, body, TransferRequestsModel)
|
||||
|
||||
def post_transfer_request(self, zone_id, transfer_request_model=None,
|
||||
**kwargs):
|
||||
resp, body = self.client.post(
|
||||
self.create_transfer_requests_uri(zone_id),
|
||||
body=transfer_request_model.to_json(),
|
||||
**kwargs)
|
||||
return self.deserialize(resp, body, TransferRequestsModel)
|
||||
|
||||
def post_transfer_request_empty_body(self, zone_id, **kwargs):
|
||||
resp, body = self.client.post(
|
||||
self.create_transfer_requests_uri(zone_id),
|
||||
body=None,
|
||||
**kwargs)
|
||||
return self.deserialize(resp, body, TransferRequestsModel)
|
||||
|
||||
def put_transfer_request(self, transfer_request_id,
|
||||
transfer_request_model, **kwargs):
|
||||
resp, body = self.client.put(self.transfer_request_uri(
|
||||
transfer_request_id),
|
||||
body=transfer_request_model.to_json(), **kwargs)
|
||||
return self.deserialize(resp, body, TransferRequestsModel)
|
||||
|
||||
def delete_transfer_request(self, transfer_request_id, **kwargs):
|
||||
resp, body = self.client.delete(
|
||||
self.transfer_request_uri(transfer_request_id), **kwargs)
|
||||
return self.deserialize(resp, body, TransferRequestsModel)
|
33
functionaltests/api/v2/models/transfer_accepts_model.py
Normal file
33
functionaltests/api/v2/models/transfer_accepts_model.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from functionaltests.common.models import BaseModel
|
||||
from functionaltests.common.models import CollectionModel
|
||||
from functionaltests.common.models import EntityModel
|
||||
|
||||
|
||||
class TransferAcceptsData(BaseModel):
|
||||
pass
|
||||
|
||||
|
||||
class TransferAcceptsModel(EntityModel):
|
||||
ENTITY_NAME = 'transfer_accept'
|
||||
MODEL_TYPE = TransferAcceptsData
|
||||
|
||||
|
||||
class TransferAcceptsListModel(CollectionModel):
|
||||
COLLECTION_NAME = 'transfer_accepts'
|
||||
MODEL_TYPE = TransferAcceptsData
|
33
functionaltests/api/v2/models/transfer_requests_model.py
Normal file
33
functionaltests/api/v2/models/transfer_requests_model.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@hp.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from functionaltests.common.models import BaseModel
|
||||
from functionaltests.common.models import CollectionModel
|
||||
from functionaltests.common.models import EntityModel
|
||||
|
||||
|
||||
class TransferRequestsData(BaseModel):
|
||||
pass
|
||||
|
||||
|
||||
class TransferRequestsModel(EntityModel):
|
||||
ENTITY_NAME = 'transfer_request'
|
||||
MODEL_TYPE = TransferRequestsData
|
||||
|
||||
|
||||
class TransferRequestsListModel(CollectionModel):
|
||||
COLLECTION_NAME = 'transfer_requests'
|
||||
MODEL_TYPE = TransferRequestsData
|
149
functionaltests/api/v2/test_zone_ownership_transfers.py
Normal file
149
functionaltests/api/v2/test_zone_ownership_transfers.py
Normal file
@ -0,0 +1,149 @@
|
||||
"""
|
||||
Copyright 2015 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from tempest_lib import exceptions
|
||||
|
||||
from functionaltests.common import datagen
|
||||
from functionaltests.common import utils
|
||||
from functionaltests.api.v2.base import DesignateV2Test
|
||||
from functionaltests.api.v2.clients.transfer_requests_client import \
|
||||
TransferRequestClient
|
||||
from functionaltests.api.v2.clients.transfer_accepts_client import \
|
||||
TransferAcceptClient
|
||||
from functionaltests.api.v2.clients.zone_client import ZoneClient
|
||||
|
||||
|
||||
@utils.parameterized_class
|
||||
class TransferZoneOwnerShipTest(DesignateV2Test):
|
||||
|
||||
def setUp(self):
|
||||
super(TransferZoneOwnerShipTest, self).setUp()
|
||||
self.increase_quotas(user='default')
|
||||
self.increase_quotas(user='alt')
|
||||
resp, self.zone = ZoneClient.as_user('default').post_zone(
|
||||
datagen.random_zone_data())
|
||||
ZoneClient.as_user('default').wait_for_zone(self.zone.id)
|
||||
|
||||
def test_list_transfer_requests(self):
|
||||
resp, model = TransferRequestClient.as_user('default') \
|
||||
.list_transfer_requests()
|
||||
self.assertEqual(resp.status, 200)
|
||||
|
||||
def test_create_zone_transfer_request(self):
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request(self.zone.id,
|
||||
datagen.random_transfer_request_data())
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
def test_view_zone_transfer_request(self):
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request(self.zone.id,
|
||||
datagen.random_transfer_request_data())
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
resp, transfer_request = TransferRequestClient.as_user('alt')\
|
||||
.get_transfer_request(transfer_request.id)
|
||||
|
||||
self.assertEqual(resp.status, 200)
|
||||
self.assertEqual(getattr(transfer_request, 'key', None), None)
|
||||
|
||||
def test_create_zone_transfer_request_scoped(self):
|
||||
|
||||
target_project_id = TransferRequestClient.as_user('alt').tenant_id
|
||||
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request(self.zone.id,
|
||||
datagen.random_transfer_request_data(
|
||||
target_project_id=target_project_id))
|
||||
self.assertEqual(resp.status, 201)
|
||||
self.assertEqual(transfer_request.target_project_id, target_project_id)
|
||||
|
||||
resp, transfer_request = TransferRequestClient.as_user('alt')\
|
||||
.get_transfer_request(transfer_request.id)
|
||||
|
||||
self.assertEqual(resp.status, 200)
|
||||
|
||||
def test_view_zone_transfer_request_scoped(self):
|
||||
target_project_id = TransferRequestClient.as_user('admin').tenant_id
|
||||
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request(self.zone.id,
|
||||
datagen.random_transfer_request_data(
|
||||
target_project_id=target_project_id))
|
||||
self.assertEqual(resp.status, 201)
|
||||
self.assertEqual(transfer_request.target_project_id, target_project_id)
|
||||
|
||||
self._assert_exception(
|
||||
exceptions.NotFound, 'zone_transfer_request_not_found', 404,
|
||||
TransferRequestClient.as_user('alt').get_transfer_request,
|
||||
self.zone.id)
|
||||
|
||||
resp, transfer_request = TransferRequestClient.as_user('admin')\
|
||||
.get_transfer_request(transfer_request.id)
|
||||
|
||||
self.assertEqual(resp.status, 200)
|
||||
|
||||
def test_create_zone_transfer_request_no_body(self):
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request_empty_body(self.zone.id)
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
def test_do_zone_transfer(self):
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request(self.zone.id,
|
||||
datagen.random_transfer_request_data())
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
resp, transfer_accept = TransferAcceptClient.as_user('alt')\
|
||||
.post_transfer_accept(
|
||||
datagen.random_transfer_accept_data(
|
||||
key=transfer_request.key,
|
||||
zone_transfer_request_id=transfer_request.id
|
||||
))
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
def test_do_zone_transfer_scoped(self):
|
||||
|
||||
target_project_id = TransferRequestClient.as_user('alt').tenant_id
|
||||
|
||||
resp, transfer_request = TransferRequestClient.as_user('default')\
|
||||
.post_transfer_request(self.zone.id,
|
||||
datagen.random_transfer_request_data(
|
||||
target_project_id=target_project_id))
|
||||
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
resp, retrived_transfer_request = TransferRequestClient.\
|
||||
as_user('alt').get_transfer_request(transfer_request.id)
|
||||
|
||||
self.assertEqual(resp.status, 200)
|
||||
|
||||
resp, transfer_accept = TransferAcceptClient.as_user('alt')\
|
||||
.post_transfer_accept(
|
||||
datagen.random_transfer_accept_data(
|
||||
key=transfer_request.key,
|
||||
zone_transfer_request_id=transfer_request.id
|
||||
))
|
||||
self.assertEqual(resp.status, 201)
|
||||
|
||||
client = ZoneClient.as_user('default')
|
||||
|
||||
self._assert_exception(
|
||||
exceptions.NotFound, 'domain_not_found', 404,
|
||||
client.get_zone, self.zone.id)
|
||||
|
||||
resp, zone = ZoneClient.as_user('alt').get_zone(self.zone.id)
|
||||
|
||||
self.assertEqual(resp.status, 200)
|
@ -13,11 +13,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import random
|
||||
|
||||
from functionaltests.api.v2.models.blacklist_model import BlacklistModel
|
||||
from functionaltests.api.v2.models.pool_model import PoolModel
|
||||
from functionaltests.api.v2.models.transfer_requests_model import \
|
||||
TransferRequestsModel
|
||||
from functionaltests.api.v2.models.transfer_accepts_model import \
|
||||
TransferAcceptsModel
|
||||
from functionaltests.api.v2.models.recordset_model import RecordsetModel
|
||||
from functionaltests.api.v2.models.zone_model import ZoneModel
|
||||
|
||||
@ -33,6 +37,10 @@ def random_ipv6():
|
||||
return result.replace("0000", "0")
|
||||
|
||||
|
||||
def random_uuid():
|
||||
return uuid.uuid4()
|
||||
|
||||
|
||||
def random_string(prefix='rand', n=8, suffix=''):
|
||||
"""Return a string containing random digits
|
||||
|
||||
@ -64,6 +72,37 @@ def random_zone_data(name=None, email=None, ttl=None, description=None):
|
||||
'description': description})
|
||||
|
||||
|
||||
def random_transfer_request_data(description=None, target_project_id=None):
|
||||
"""Generate random zone data, with optional overrides
|
||||
|
||||
:return: A TransferRequestModel
|
||||
"""
|
||||
|
||||
data = {}
|
||||
|
||||
if description is None:
|
||||
data['description'] = random_string(prefix='Description ')
|
||||
|
||||
if target_project_id:
|
||||
data['target_project_id'] = target_project_id
|
||||
|
||||
return TransferRequestsModel.from_dict(data)
|
||||
|
||||
|
||||
def random_transfer_accept_data(key=None, zone_transfer_request_id=None):
|
||||
"""Generate random zone data, with optional overrides
|
||||
|
||||
:return: A TransferRequestModel
|
||||
"""
|
||||
if key is None:
|
||||
key = random_string()
|
||||
if zone_transfer_request_id is None:
|
||||
zone_transfer_request_id = random_uuid()
|
||||
return TransferAcceptsModel.from_dict({
|
||||
'key': key,
|
||||
'zone_transfer_request_id': zone_transfer_request_id})
|
||||
|
||||
|
||||
def random_recordset_data(record_type, zone_name, name=None, records=None,
|
||||
ttl=None):
|
||||
"""Generate random recordset data, with optional overrides
|
||||
|
Loading…
Reference in New Issue
Block a user