Add Designate (DNS) zone share API
This patch adds support for the zone share API. Change-Id: I4cabb6444f90ffaf110ec0d0f16015b93bbd07f8
This commit is contained in:
parent
74f8869fd9
commit
a745604328
|
@ -60,3 +60,11 @@ Zone Transfer Operations
|
||||||
create_zone_transfer_request, update_zone_transfer_request,
|
create_zone_transfer_request, update_zone_transfer_request,
|
||||||
delete_zone_transfer_request, zone_transfer_accepts,
|
delete_zone_transfer_request, zone_transfer_accepts,
|
||||||
get_zone_transfer_accept, create_zone_transfer_accept
|
get_zone_transfer_accept, create_zone_transfer_accept
|
||||||
|
|
||||||
|
Zone Share Operations
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. autoclass:: openstack.dns.v2._proxy.Proxy
|
||||||
|
:noindex:
|
||||||
|
:members: create_zone_share, delete_zone_share, get_zone_share,
|
||||||
|
find_zone_share, zone_shares
|
||||||
|
|
|
@ -8,5 +8,6 @@ DNS Resources
|
||||||
v2/zone_transfer
|
v2/zone_transfer
|
||||||
v2/zone_export
|
v2/zone_export
|
||||||
v2/zone_import
|
v2/zone_import
|
||||||
|
v2/zone_share
|
||||||
v2/floating_ip
|
v2/floating_ip
|
||||||
v2/recordset
|
v2/recordset
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
openstack.dns.v2.zone_share
|
||||||
|
===========================
|
||||||
|
|
||||||
|
.. automodule:: openstack.dns.v2.zone_share
|
||||||
|
|
||||||
|
The ZoneShare Class
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The ``DNS`` class inherits from :class:`~openstack.resource.Resource`.
|
||||||
|
|
||||||
|
.. autoclass:: openstack.dns.v2.zone_share.ZoneShare
|
||||||
|
:members:
|
|
@ -15,6 +15,7 @@ from openstack.dns.v2 import recordset as _rs
|
||||||
from openstack.dns.v2 import zone as _zone
|
from openstack.dns.v2 import zone as _zone
|
||||||
from openstack.dns.v2 import zone_export as _zone_export
|
from openstack.dns.v2 import zone_export as _zone_export
|
||||||
from openstack.dns.v2 import zone_import as _zone_import
|
from openstack.dns.v2 import zone_import as _zone_import
|
||||||
|
from openstack.dns.v2 import zone_share as _zone_share
|
||||||
from openstack.dns.v2 import zone_transfer as _zone_transfer
|
from openstack.dns.v2 import zone_transfer as _zone_transfer
|
||||||
from openstack import proxy
|
from openstack import proxy
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ class Proxy(proxy.Proxy):
|
||||||
"zone": _zone.Zone,
|
"zone": _zone.Zone,
|
||||||
"zone_export": _zone_export.ZoneExport,
|
"zone_export": _zone_export.ZoneExport,
|
||||||
"zone_import": _zone_import.ZoneImport,
|
"zone_import": _zone_import.ZoneImport,
|
||||||
|
"zone_share": _zone_share.ZoneShare,
|
||||||
"zone_transfer_request": _zone_transfer.ZoneTransferRequest,
|
"zone_transfer_request": _zone_transfer.ZoneTransferRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +71,7 @@ class Proxy(proxy.Proxy):
|
||||||
"""
|
"""
|
||||||
return self._get(_zone.Zone, zone)
|
return self._get(_zone.Zone, zone)
|
||||||
|
|
||||||
def delete_zone(self, zone, ignore_missing=True):
|
def delete_zone(self, zone, ignore_missing=True, delete_shares=False):
|
||||||
"""Delete a zone
|
"""Delete a zone
|
||||||
|
|
||||||
:param zone: The value can be the ID of a zone
|
:param zone: The value can be the ID of a zone
|
||||||
|
@ -79,11 +81,14 @@ class Proxy(proxy.Proxy):
|
||||||
the zone does not exist.
|
the zone does not exist.
|
||||||
When set to ``True``, no exception will be set when attempting to
|
When set to ``True``, no exception will be set when attempting to
|
||||||
delete a nonexistent zone.
|
delete a nonexistent zone.
|
||||||
|
:param bool delete_shares: When True, delete the zone shares along with
|
||||||
|
the zone.
|
||||||
|
|
||||||
:returns: Zone been deleted
|
:returns: Zone been deleted
|
||||||
:rtype: :class:`~openstack.dns.v2.zone.Zone`
|
:rtype: :class:`~openstack.dns.v2.zone.Zone`
|
||||||
"""
|
"""
|
||||||
return self._delete(_zone.Zone, zone, ignore_missing=ignore_missing)
|
return self._delete(_zone.Zone, zone, ignore_missing=ignore_missing,
|
||||||
|
delete_shares=delete_shares)
|
||||||
|
|
||||||
def update_zone(self, zone, **attrs):
|
def update_zone(self, zone, **attrs):
|
||||||
"""Update zone attributes
|
"""Update zone attributes
|
||||||
|
@ -536,6 +541,93 @@ class Proxy(proxy.Proxy):
|
||||||
"""
|
"""
|
||||||
return self._create(_zone_transfer.ZoneTransferAccept, **attrs)
|
return self._create(_zone_transfer.ZoneTransferAccept, **attrs)
|
||||||
|
|
||||||
|
# ======== Zone Shares ========
|
||||||
|
def zone_shares(self, zone, **query):
|
||||||
|
"""Retrieve a generator of zone sharess
|
||||||
|
|
||||||
|
:param zone: The zone ID or a
|
||||||
|
:class:`~openstack.dns.v2.zone.Zone` instance
|
||||||
|
:param dict query: Optional query parameters to be sent to limit the
|
||||||
|
resources being returned.
|
||||||
|
|
||||||
|
* `target_project_id`: The target project ID field.
|
||||||
|
|
||||||
|
:returns: A generator of zone shares
|
||||||
|
:class:`~openstack.dns.v2.zone_share.ZoneShare` instances.
|
||||||
|
"""
|
||||||
|
zone_obj = self._get_resource(_zone.Zone, zone)
|
||||||
|
return self._list(_zone_share.ZoneShare, zone_id=zone_obj.id, **query)
|
||||||
|
|
||||||
|
def get_zone_share(self, zone, zone_share):
|
||||||
|
"""Get a zone share
|
||||||
|
|
||||||
|
:param zone: The value can be the ID of a zone
|
||||||
|
or a :class:`~openstack.dns.v2.zone.Zone` instance.
|
||||||
|
:param zone_share: The zone_share can be either the ID of the zone
|
||||||
|
share or a :class:`~openstack.dns.v2.zone_share.ZoneShare` instance
|
||||||
|
that the zone share belongs to.
|
||||||
|
|
||||||
|
:returns: ZoneShare instance.
|
||||||
|
:rtype: :class:`~openstack.dns.v2.zone_share.ZoneShare`
|
||||||
|
"""
|
||||||
|
zone_obj = self._get_resource(_zone.Zone, zone)
|
||||||
|
return self._get(_zone_share.ZoneShare, zone_share,
|
||||||
|
zone_id=zone_obj.id)
|
||||||
|
|
||||||
|
def find_zone_share(self, zone, zone_share_id, ignore_missing=True):
|
||||||
|
"""Find a single zone share
|
||||||
|
|
||||||
|
:param zone: The value can be the ID of a zone
|
||||||
|
or a :class:`~openstack.dns.v2.zone.Zone` instance.
|
||||||
|
:param zone_share_id: The zone share ID
|
||||||
|
:param bool ignore_missing: When set to ``False``
|
||||||
|
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||||
|
when the zone share does not exist.
|
||||||
|
When set to ``True``, None will be returned when attempting to
|
||||||
|
find a nonexistent zone share.
|
||||||
|
|
||||||
|
:returns: :class:`~openstack.dns.v2.zone_share.ZoneShare`
|
||||||
|
"""
|
||||||
|
zone_obj = self._get_resource(_zone.Zone, zone)
|
||||||
|
return self._find(_zone_share.ZoneShare, zone_share_id,
|
||||||
|
ignore_missing=ignore_missing, zone_id=zone_obj.id)
|
||||||
|
|
||||||
|
def create_zone_share(self, zone, **attrs):
|
||||||
|
"""Create a new zone share from attributes
|
||||||
|
|
||||||
|
:param zone: The zone ID or a
|
||||||
|
:class:`~openstack.dns.v2.zone.Zone` instance
|
||||||
|
:param dict attrs: Keyword arguments which will be used to create
|
||||||
|
a :class:`~openstack.dns.v2.zone_share.ZoneShare`,
|
||||||
|
comprised of the properties on the ZoneShare class.
|
||||||
|
|
||||||
|
:returns: The results of zone share creation
|
||||||
|
:rtype: :class:`~openstack.dns.v2.zone_share.ZoneShare`
|
||||||
|
"""
|
||||||
|
zone_obj = self._get_resource(_zone.Zone, zone)
|
||||||
|
return self._create(_zone_share.ZoneShare, zone_id=zone_obj.id,
|
||||||
|
**attrs)
|
||||||
|
|
||||||
|
def delete_zone_share(self, zone, zone_share, ignore_missing=True):
|
||||||
|
"""Delete a zone share
|
||||||
|
|
||||||
|
:param zone: The zone ID or a
|
||||||
|
:class:`~openstack.dns.v2.zone.Zone` instance
|
||||||
|
:param zone_share: The zone_share can be either the ID of the zone
|
||||||
|
share or a :class:`~openstack.dns.v2.zone_share.ZoneShare` instance
|
||||||
|
that the zone share belongs to.
|
||||||
|
:param bool ignore_missing: When set to ``False``
|
||||||
|
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||||
|
the zone share does not exist.
|
||||||
|
When set to ``True``, no exception will be set when attempting to
|
||||||
|
delete a nonexistent zone share.
|
||||||
|
|
||||||
|
:returns: ``None``
|
||||||
|
"""
|
||||||
|
zone_obj = self._get_resource(_zone.Zone, zone)
|
||||||
|
self._delete(_zone_share.ZoneShare, zone_share,
|
||||||
|
ignore_missing=ignore_missing, zone_id=zone_obj.id)
|
||||||
|
|
||||||
def _get_cleanup_dependencies(self):
|
def _get_cleanup_dependencies(self):
|
||||||
# DNS may depend on floating ip
|
# DNS may depend on floating ip
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -79,6 +79,13 @@ class Zone(_base.Resource):
|
||||||
type = resource.Body('type')
|
type = resource.Body('type')
|
||||||
#: Timestamp when the zone was last updated
|
#: Timestamp when the zone was last updated
|
||||||
updated_at = resource.Body('updated_at')
|
updated_at = resource.Body('updated_at')
|
||||||
|
#: Whether the zone is shared with other projects
|
||||||
|
#: *Type: bool*
|
||||||
|
is_shared = resource.Body('shared')
|
||||||
|
|
||||||
|
# Headers for DELETE requests
|
||||||
|
#: If true, delete any existing zone shares along with the zone
|
||||||
|
delete_shares = resource.Header('x-designate-delete-shares', type=bool)
|
||||||
|
|
||||||
def _action(self, session, action, body):
|
def _action(self, session, action, body):
|
||||||
"""Preform actions given the message body.
|
"""Preform actions given the message body.
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
# 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 openstack.dns.v2 import _base
|
||||||
|
from openstack import resource
|
||||||
|
|
||||||
|
|
||||||
|
class ZoneShare(_base.Resource):
|
||||||
|
"""DNS ZONE Share Resource"""
|
||||||
|
|
||||||
|
resources_key = 'shared_zones'
|
||||||
|
base_path = '/zones/%(zone_id)s/shares'
|
||||||
|
|
||||||
|
# capabilities
|
||||||
|
allow_create = True
|
||||||
|
allow_delete = True
|
||||||
|
allow_fetch = True
|
||||||
|
allow_list = True
|
||||||
|
|
||||||
|
_query_mapping = resource.QueryParameters('target_project_id')
|
||||||
|
|
||||||
|
# Properties
|
||||||
|
#: Timestamp when the share was created.
|
||||||
|
created_at = resource.Body('created_at')
|
||||||
|
#: Timestamp when the member was last updated.
|
||||||
|
updated_at = resource.Body('updated_at')
|
||||||
|
#: The zone ID of the zone being shared.
|
||||||
|
zone_id = resource.Body('zone_id')
|
||||||
|
#: The project ID that owns the share.
|
||||||
|
project_id = resource.Body('project_id')
|
||||||
|
#: The target project ID that the zone is shared with.
|
||||||
|
target_project_id = resource.Body('target_project_id')
|
||||||
|
|
||||||
|
# URI Properties
|
||||||
|
#: The ID of the zone being shared.
|
||||||
|
zone_id = resource.URI('zone_id')
|
|
@ -0,0 +1,25 @@
|
||||||
|
# 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 openstack import resource
|
||||||
|
|
||||||
|
|
||||||
|
class Version(resource.Resource):
|
||||||
|
resource_key = 'version'
|
||||||
|
resources_key = 'versions'
|
||||||
|
base_path = '/'
|
||||||
|
|
||||||
|
# capabilities
|
||||||
|
allow_list = True
|
||||||
|
|
||||||
|
# Properties
|
||||||
|
links = resource.Body('links')
|
||||||
|
status = resource.Body('status')
|
|
@ -12,6 +12,7 @@
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from openstack import connection
|
from openstack import connection
|
||||||
|
from openstack import exceptions
|
||||||
from openstack.tests.functional import base
|
from openstack.tests.functional import base
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,3 +67,25 @@ class TestZone(base.BaseFunctionalTest):
|
||||||
ttl=3600,
|
ttl=3600,
|
||||||
records=['192.168.1.1']
|
records=['192.168.1.1']
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def test_delete_zone_with_shares(self):
|
||||||
|
zone_name = 'example-{0}.org.'.format(random.randint(1, 10000))
|
||||||
|
zone = self.conn.dns.create_zone(
|
||||||
|
name=zone_name,
|
||||||
|
email='joe@example.org',
|
||||||
|
type='PRIMARY',
|
||||||
|
ttl=7200,
|
||||||
|
description='example zone'
|
||||||
|
)
|
||||||
|
self.addCleanup(self.conn.dns.delete_zone, zone)
|
||||||
|
|
||||||
|
demo_project_id = self.operator_cloud.get_project('demo')['id']
|
||||||
|
zone_share = self.conn.dns.create_zone_share(
|
||||||
|
zone, target_project_id=demo_project_id)
|
||||||
|
self.addCleanup(self.conn.dns.delete_zone_share, zone, zone_share)
|
||||||
|
|
||||||
|
# Test that we cannot delete a zone with shares
|
||||||
|
self.assertRaises(exceptions.BadRequestException,
|
||||||
|
self.conn.dns.delete_zone, zone)
|
||||||
|
|
||||||
|
self.conn.dns.delete_zone(zone, delete_shares=True)
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
# 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.
|
||||||
|
import random
|
||||||
|
|
||||||
|
from openstack import exceptions
|
||||||
|
from openstack.tests.functional import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestZoneShare(base.BaseFunctionalTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestZoneShare, self).setUp()
|
||||||
|
self.require_service('dns')
|
||||||
|
if not self.user_cloud:
|
||||||
|
self.skipTest("The demo cloud is required for this test")
|
||||||
|
|
||||||
|
# Note: zone deletion is not an immediate operation, so each time
|
||||||
|
# chose a new zone name for a test
|
||||||
|
# getUniqueString is not guaranteed to return unique string between
|
||||||
|
# different tests of the same class.
|
||||||
|
self.ZONE_NAME = 'example-{0}.org.'.format(random.randint(1, 10000))
|
||||||
|
|
||||||
|
self.zone = self.operator_cloud.dns.create_zone(
|
||||||
|
name=self.ZONE_NAME,
|
||||||
|
email='joe@example.org',
|
||||||
|
type='PRIMARY',
|
||||||
|
ttl=7200,
|
||||||
|
description='example zone for sdk zone share tests'
|
||||||
|
)
|
||||||
|
self.addCleanup(self.operator_cloud.dns.delete_zone, self.zone,
|
||||||
|
delete_shares=True)
|
||||||
|
|
||||||
|
self.project_id = self.operator_cloud.session.get_project_id()
|
||||||
|
self.demo_project_id = self.user_cloud.session.get_project_id()
|
||||||
|
|
||||||
|
def test_create_delete_zone_share(self):
|
||||||
|
zone_share = self.operator_cloud.dns.create_zone_share(
|
||||||
|
self.zone, target_project_id=self.demo_project_id)
|
||||||
|
self.addCleanup(self.operator_cloud.dns.delete_zone_share, self.zone,
|
||||||
|
zone_share)
|
||||||
|
|
||||||
|
self.assertEqual(self.zone.id, zone_share.zone_id)
|
||||||
|
self.assertEqual(self.project_id, zone_share.project_id)
|
||||||
|
self.assertEqual(self.demo_project_id, zone_share.target_project_id)
|
||||||
|
self.assertIsNotNone(zone_share.id)
|
||||||
|
self.assertIsNotNone(zone_share.created_at)
|
||||||
|
self.assertIsNone(zone_share.updated_at)
|
||||||
|
|
||||||
|
def test_get_zone_share(self):
|
||||||
|
orig_zone_share = self.operator_cloud.dns.create_zone_share(
|
||||||
|
self.zone, target_project_id=self.demo_project_id)
|
||||||
|
self.addCleanup(self.operator_cloud.dns.delete_zone_share, self.zone,
|
||||||
|
orig_zone_share)
|
||||||
|
|
||||||
|
zone_share = self.operator_cloud.dns.get_zone_share(self.zone,
|
||||||
|
orig_zone_share)
|
||||||
|
|
||||||
|
self.assertEqual(self.zone.id, zone_share.zone_id)
|
||||||
|
self.assertEqual(self.project_id, zone_share.project_id)
|
||||||
|
self.assertEqual(self.demo_project_id, zone_share.target_project_id)
|
||||||
|
self.assertEqual(orig_zone_share.id, zone_share.id)
|
||||||
|
self.assertEqual(orig_zone_share.created_at, zone_share.created_at)
|
||||||
|
self.assertEqual(orig_zone_share.updated_at, zone_share.updated_at)
|
||||||
|
|
||||||
|
def test_find_zone_share(self):
|
||||||
|
orig_zone_share = self.operator_cloud.dns.create_zone_share(
|
||||||
|
self.zone, target_project_id=self.demo_project_id)
|
||||||
|
self.addCleanup(self.operator_cloud.dns.delete_zone_share, self.zone,
|
||||||
|
orig_zone_share)
|
||||||
|
|
||||||
|
zone_share = self.operator_cloud.dns.find_zone_share(
|
||||||
|
self.zone, orig_zone_share.id)
|
||||||
|
|
||||||
|
self.assertEqual(self.zone.id, zone_share.zone_id)
|
||||||
|
self.assertEqual(self.project_id, zone_share.project_id)
|
||||||
|
self.assertEqual(self.demo_project_id, zone_share.target_project_id)
|
||||||
|
self.assertEqual(orig_zone_share.id, zone_share.id)
|
||||||
|
self.assertEqual(orig_zone_share.created_at, zone_share.created_at)
|
||||||
|
self.assertEqual(orig_zone_share.updated_at, zone_share.updated_at)
|
||||||
|
|
||||||
|
def test_find_zone_share_ignore_missing(self):
|
||||||
|
zone_share = self.operator_cloud.dns.find_zone_share(self.zone,
|
||||||
|
'bogus_id')
|
||||||
|
self.assertIsNone(zone_share)
|
||||||
|
|
||||||
|
def test_find_zone_share_ignore_missing_false(self):
|
||||||
|
self.assertRaises(exceptions.ResourceNotFound,
|
||||||
|
self.operator_cloud.dns.find_zone_share,
|
||||||
|
self.zone, 'bogus_id', ignore_missing=False)
|
||||||
|
|
||||||
|
def test_list_zone_shares(self):
|
||||||
|
zone_share = self.operator_cloud.dns.create_zone_share(
|
||||||
|
self.zone, target_project_id=self.demo_project_id)
|
||||||
|
self.addCleanup(self.operator_cloud.dns.delete_zone_share, self.zone,
|
||||||
|
zone_share)
|
||||||
|
|
||||||
|
target_ids = [o.target_project_id for o in
|
||||||
|
self.operator_cloud.dns.zone_shares(self.zone)]
|
||||||
|
self.assertIn(self.demo_project_id, target_ids)
|
||||||
|
|
||||||
|
def test_list_zone_shares_with_target_id(self):
|
||||||
|
zone_share = self.operator_cloud.dns.create_zone_share(
|
||||||
|
self.zone, target_project_id=self.demo_project_id)
|
||||||
|
self.addCleanup(self.operator_cloud.dns.delete_zone_share, self.zone,
|
||||||
|
zone_share)
|
||||||
|
|
||||||
|
target_ids = [o.target_project_id for o in
|
||||||
|
self.operator_cloud.dns.zone_shares(
|
||||||
|
self.zone, target_project_id=self.demo_project_id)]
|
||||||
|
self.assertIn(self.demo_project_id, target_ids)
|
|
@ -0,0 +1,42 @@
|
||||||
|
# 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 openstack.dns import version
|
||||||
|
from openstack.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
|
IDENTIFIER = 'IDENTIFIER'
|
||||||
|
EXAMPLE = {
|
||||||
|
'id': IDENTIFIER,
|
||||||
|
'links': '2',
|
||||||
|
'status': '3',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestVersion(base.TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
sot = version.Version()
|
||||||
|
self.assertEqual('version', sot.resource_key)
|
||||||
|
self.assertEqual('versions', sot.resources_key)
|
||||||
|
self.assertEqual('/', sot.base_path)
|
||||||
|
self.assertFalse(sot.allow_create)
|
||||||
|
self.assertFalse(sot.allow_fetch)
|
||||||
|
self.assertFalse(sot.allow_commit)
|
||||||
|
self.assertFalse(sot.allow_delete)
|
||||||
|
self.assertTrue(sot.allow_list)
|
||||||
|
|
||||||
|
def test_make_it(self):
|
||||||
|
sot = version.Version(**EXAMPLE)
|
||||||
|
self.assertEqual(EXAMPLE['id'], sot.id)
|
||||||
|
self.assertEqual(EXAMPLE['links'], sot.links)
|
||||||
|
self.assertEqual(EXAMPLE['status'], sot.status)
|
|
@ -16,6 +16,7 @@ from openstack.dns.v2 import recordset
|
||||||
from openstack.dns.v2 import zone
|
from openstack.dns.v2 import zone
|
||||||
from openstack.dns.v2 import zone_export
|
from openstack.dns.v2 import zone_export
|
||||||
from openstack.dns.v2 import zone_import
|
from openstack.dns.v2 import zone_import
|
||||||
|
from openstack.dns.v2 import zone_share
|
||||||
from openstack.dns.v2 import zone_transfer
|
from openstack.dns.v2 import zone_transfer
|
||||||
from openstack.tests.unit import test_proxy_base
|
from openstack.tests.unit import test_proxy_base
|
||||||
|
|
||||||
|
@ -34,8 +35,9 @@ class TestDnsZone(TestDnsProxy):
|
||||||
'prepend_key': False})
|
'prepend_key': False})
|
||||||
|
|
||||||
def test_zone_delete(self):
|
def test_zone_delete(self):
|
||||||
self.verify_delete(self.proxy.delete_zone,
|
self.verify_delete(
|
||||||
zone.Zone, True)
|
self.proxy.delete_zone, zone.Zone, True,
|
||||||
|
expected_kwargs={'ignore_missing': True, 'delete_shares': False})
|
||||||
|
|
||||||
def test_zone_find(self):
|
def test_zone_find(self):
|
||||||
self.verify_find(self.proxy.find_zone, zone.Zone)
|
self.verify_find(self.proxy.find_zone, zone.Zone)
|
||||||
|
@ -213,3 +215,40 @@ class TestDnsZoneTransferAccept(TestDnsProxy):
|
||||||
def test_zone_transfer_accept_create(self):
|
def test_zone_transfer_accept_create(self):
|
||||||
self.verify_create(self.proxy.create_zone_transfer_accept,
|
self.verify_create(self.proxy.create_zone_transfer_accept,
|
||||||
zone_transfer.ZoneTransferAccept)
|
zone_transfer.ZoneTransferAccept)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDnsZoneShare(TestDnsProxy):
|
||||||
|
def test_zone_share_create(self):
|
||||||
|
self.verify_create(self.proxy.create_zone_share, zone_share.ZoneShare,
|
||||||
|
method_kwargs={'zone': 'bogus_id'},
|
||||||
|
expected_kwargs={'zone_id': 'bogus_id'})
|
||||||
|
|
||||||
|
def test_zone_share_delete(self):
|
||||||
|
self.verify_delete(
|
||||||
|
self.proxy.delete_zone_share, zone_share.ZoneShare,
|
||||||
|
ignore_missing=True,
|
||||||
|
method_args={'zone': 'bogus_id', 'zone_share': 'bogus_id'},
|
||||||
|
expected_args=['zone_share'],
|
||||||
|
expected_kwargs={'zone_id': 'zone', 'ignore_missing': True})
|
||||||
|
|
||||||
|
def test_zone_share_find(self):
|
||||||
|
self.verify_find(
|
||||||
|
self.proxy.find_zone_share, zone_share.ZoneShare,
|
||||||
|
method_args=['zone'],
|
||||||
|
expected_args=['zone'],
|
||||||
|
expected_kwargs={'zone_id': 'resource_name',
|
||||||
|
'ignore_missing': True})
|
||||||
|
|
||||||
|
def test_zone_share_get(self):
|
||||||
|
self.verify_get(
|
||||||
|
self.proxy.get_zone_share, zone_share.ZoneShare,
|
||||||
|
method_args=['zone', 'zone_share'],
|
||||||
|
expected_args=['zone_share'],
|
||||||
|
expected_kwargs={'zone_id': 'zone'})
|
||||||
|
|
||||||
|
def test_zone_shares(self):
|
||||||
|
self.verify_list(
|
||||||
|
self.proxy.zone_shares, zone_share.ZoneShare,
|
||||||
|
method_args=['zone'],
|
||||||
|
expected_args=[],
|
||||||
|
expected_kwargs={'zone_id': 'zone'})
|
||||||
|
|
|
@ -28,7 +28,8 @@ EXAMPLE = {
|
||||||
'type': 'PRIMARY',
|
'type': 'PRIMARY',
|
||||||
'ttl': 7200,
|
'ttl': 7200,
|
||||||
'description': 'This is an example zone.',
|
'description': 'This is an example zone.',
|
||||||
'status': 'ACTIVE'
|
'status': 'ACTIVE',
|
||||||
|
'shared': False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ class TestZone(base.TestCase):
|
||||||
self.assertEqual(EXAMPLE['type'], sot.type)
|
self.assertEqual(EXAMPLE['type'], sot.type)
|
||||||
self.assertEqual(EXAMPLE['name'], sot.name)
|
self.assertEqual(EXAMPLE['name'], sot.name)
|
||||||
self.assertEqual(EXAMPLE['status'], sot.status)
|
self.assertEqual(EXAMPLE['status'], sot.status)
|
||||||
|
self.assertEqual(EXAMPLE['shared'], sot.is_shared)
|
||||||
|
|
||||||
def test_abandon(self):
|
def test_abandon(self):
|
||||||
sot = zone.Zone(**EXAMPLE)
|
sot = zone.Zone(**EXAMPLE)
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
# 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 unittest import mock
|
||||||
|
|
||||||
|
from keystoneauth1 import adapter
|
||||||
|
|
||||||
|
from openstack.dns.v2 import zone_share
|
||||||
|
from openstack.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestZoneShare(base.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestZoneShare, self).setUp()
|
||||||
|
self.resp = mock.Mock()
|
||||||
|
self.resp.body = None
|
||||||
|
self.resp.json = mock.Mock(return_value=self.resp.body)
|
||||||
|
self.resp.status_code = 200
|
||||||
|
self.sess = mock.Mock(spec=adapter.Adapter)
|
||||||
|
self.sess.post = mock.Mock(return_value=self.resp)
|
||||||
|
self.sess.default_microversion = None
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
sot = zone_share.ZoneShare()
|
||||||
|
self.assertEqual(None, sot.resource_key)
|
||||||
|
self.assertEqual('shared_zones', sot.resources_key)
|
||||||
|
self.assertEqual('/zones/%(zone_id)s/shares', sot.base_path)
|
||||||
|
self.assertTrue(sot.allow_list)
|
||||||
|
self.assertTrue(sot.allow_create)
|
||||||
|
self.assertTrue(sot.allow_fetch)
|
||||||
|
self.assertTrue(sot.allow_delete)
|
||||||
|
self.assertFalse(sot.allow_commit)
|
||||||
|
|
||||||
|
self.assertDictEqual({'target_project_id': 'target_project_id',
|
||||||
|
'limit': 'limit', 'marker': 'marker'},
|
||||||
|
sot._query_mapping._mapping)
|
||||||
|
|
||||||
|
def test_make_it(self):
|
||||||
|
share_id = 'bogus_id'
|
||||||
|
zone_id = 'bogus_zone_id'
|
||||||
|
project_id = 'bogus_project_id'
|
||||||
|
target_id = 'bogus_target_id'
|
||||||
|
expected = {
|
||||||
|
'id': share_id,
|
||||||
|
'zone_id': zone_id,
|
||||||
|
'project_id': project_id,
|
||||||
|
'target_project_id': target_id}
|
||||||
|
|
||||||
|
sot = zone_share.ZoneShare(**expected)
|
||||||
|
self.assertEqual(share_id, sot.id)
|
||||||
|
self.assertEqual(zone_id, sot.zone_id)
|
||||||
|
self.assertEqual(project_id, sot.project_id)
|
||||||
|
self.assertEqual(target_id, sot.target_project_id)
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add Designate (DNS) support for zone shares.
|
Loading…
Reference in New Issue