summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml2
-rw-r--r--designate/backend/impl_infoblox/connector.py5
-rw-r--r--designate/backend/impl_infoblox/object_manipulator.py26
-rw-r--r--designate/common/decorators/lock.py4
-rw-r--r--designate/tests/unit/backend/test_infoblox.py5
-rw-r--r--designate/tests/unit/common/__init__.py0
-rw-r--r--designate/tests/unit/common/test_zone_lock.py110
-rw-r--r--releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po12
-rw-r--r--setup.cfg12
9 files changed, 159 insertions, 17 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index 87c1dc8d..3c2bd1b9 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -1,6 +1,7 @@
- job:
name: designate-base
parent: devstack-tempest
+ nodeset: openstack-single-node-jammy
vars: &base_vars
devstack_localrc:
DESIGNATE_SERVICE_PORT_DNS: 5322
@@ -35,6 +36,7 @@
- job:
name: designate-base-ipv6-only
parent: devstack-tempest-ipv6
+ nodeset: openstack-single-node-jammy
description: |
Designate devstack-tempest base job for IPv6-only deployment
irrelevant-files: *base_irrelevant_files
diff --git a/designate/backend/impl_infoblox/connector.py b/designate/backend/impl_infoblox/connector.py
index fab9d784..aaf1456f 100644
--- a/designate/backend/impl_infoblox/connector.py
+++ b/designate/backend/impl_infoblox/connector.py
@@ -131,7 +131,10 @@ class Infoblox(object):
headers = {'Content-type': 'application/json'}
- data = jsonutils.dump_as_bytes(payload)
+ # NOTE (scottsol): This can trigger an internal error in Infoblox if
+ # jsonutils sets it to 'null' (a string with quotes). Setting to None
+ # works around this and returns a valid response from Infoblox
+ data = jsonutils.dump_as_bytes(payload) if payload else None
url = self._construct_url(objtype, query_params, extattrs)
r = self.session.get(url,
diff --git a/designate/backend/impl_infoblox/object_manipulator.py b/designate/backend/impl_infoblox/object_manipulator.py
index a2d4fdf5..dbbb431d 100644
--- a/designate/backend/impl_infoblox/object_manipulator.py
+++ b/designate/backend/impl_infoblox/object_manipulator.py
@@ -122,14 +122,16 @@ class InfobloxObjectManipulator(object):
'zone_auth',
{'fqdn': fqdn, 'view': dns_view},
{'ns_group': self.connector.ns_group,
- 'restart_if_needed': True, 'zone_format': zone_format},
+ 'zone_format': zone_format},
check_if_exists=True)
+ self._restart_if_needed()
except exc.InfobloxCannotCreateObject as e:
LOG.warning(e)
def delete_zone_auth(self, fqdn):
self._delete_infoblox_object(
'zone_auth', {'fqdn': fqdn})
+ self._restart_if_needed()
def _create_infoblox_object(self, obj_type, payload,
additional_create_kwargs=None,
@@ -205,3 +207,25 @@ class InfobloxObjectManipulator(object):
if ib_object_ref:
self.connector.delete_object(ib_object_ref)
LOG.info('Infoblox object was deleted: %s', ib_object_ref)
+
+ def _restart_if_needed(self):
+ ib_object_ref = None
+ obj_type = 'grid'
+ warn_msg = ('Infoblox %(obj_type)s will not be restarted because'
+ ' the API object reference cannot be found')
+ try:
+ ib_object_ref = self._get_infoblox_object_or_none(obj_type)
+ if not ib_object_ref:
+ LOG.warning(warn_msg, {'obj_type': obj_type})
+ except exc.InfobloxSearchError as e:
+ LOG.warning(warn_msg, {'obj_type': obj_type})
+ LOG.info(e)
+
+ if ib_object_ref:
+ payload = {
+ "restart_option": "RESTART_IF_NEEDED",
+ "mode": "GROUPED",
+ "services": ["DNS"],
+ }
+ self.connector.call_func(
+ 'restartservices', ib_object_ref, payload)
diff --git a/designate/common/decorators/lock.py b/designate/common/decorators/lock.py
index f633fa4d..97010492 100644
--- a/designate/common/decorators/lock.py
+++ b/designate/common/decorators/lock.py
@@ -52,7 +52,7 @@ def extract_zone_id(args, kwargs):
for arg in itertools.chain(args, kwargs.values()):
if not isinstance(arg, objects.DesignateObject):
continue
- if isinstance(arg, objects.Zone):
+ elif isinstance(arg, objects.Zone):
zone_id = arg.id
if zone_id:
break
@@ -68,8 +68,6 @@ def extract_zone_id(args, kwargs):
arg = args[1]
if isinstance(arg, str):
zone_id = arg
- elif isinstance(zone_id, objects.Zone):
- zone_id = arg.id
return zone_id
diff --git a/designate/tests/unit/backend/test_infoblox.py b/designate/tests/unit/backend/test_infoblox.py
index 81c8351b..731757c4 100644
--- a/designate/tests/unit/backend/test_infoblox.py
+++ b/designate/tests/unit/backend/test_infoblox.py
@@ -88,6 +88,11 @@ class InfobloxBackendTestCase(oslotest.base.BaseTestCase):
json={},
)
+ req_mock.get(
+ '%s/v2.0/grid' % self.base_address,
+ json={},
+ )
+
self.backend.create_zone(self.context, self.zone)
self.backend.delete_zone(self.context, self.zone)
diff --git a/designate/tests/unit/common/__init__.py b/designate/tests/unit/common/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/designate/tests/unit/common/__init__.py
diff --git a/designate/tests/unit/common/test_zone_lock.py b/designate/tests/unit/common/test_zone_lock.py
new file mode 100644
index 00000000..e2d7f4b1
--- /dev/null
+++ b/designate/tests/unit/common/test_zone_lock.py
@@ -0,0 +1,110 @@
+# 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
+
+import oslotest.base
+
+from designate.common.decorators import lock
+from designate import objects
+
+
+class TestExtractZoneId(oslotest.base.BaseTestCase):
+ def setUp(self):
+ super(TestExtractZoneId, self).setUp()
+
+ def test_extract_zone_id_empty(self):
+ self.assertIsNone(lock.extract_zone_id([], {}))
+
+ def test_extract_zone_id_no_valid_objects(self):
+ self.assertIsNone(
+ lock.extract_zone_id([], {
+ 'ptr': objects.PTRList(), 'a': objects.AList()})
+ )
+
+ def test_extract_zone_id_kwargs(self):
+ self.assertEqual(
+ 'test',
+ lock.extract_zone_id([], {'zone_id': 'test'})
+ )
+ self.assertEqual(
+ 'test',
+ lock.extract_zone_id([], {'zone': mock.Mock(id='test')})
+ )
+ self.assertEqual(
+ 'test',
+ lock.extract_zone_id([], {'recordset': mock.Mock(zone_id='test')})
+ )
+ self.assertEqual(
+ 'test',
+ lock.extract_zone_id([], {'record': mock.Mock(zone_id='test')})
+ )
+
+ def test_extract_zone_id_from_zone(self):
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id(['a', 'b', 'c'], {'x': objects.Zone(id=123)})
+ )
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id([objects.Zone(id=123)], {})
+ )
+
+ def test_extract_zone_id_from_recordset(self):
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id([], {'x': objects.RecordSet(zone_id=123)})
+ )
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id([objects.RecordSet(zone_id=123)], {})
+ )
+
+ def test_extract_zone_id_from_record(self):
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id([], {'x': objects.Record(zone_id=123)})
+ )
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id([objects.Record(zone_id=123)], {})
+ )
+
+ def test_extract_zone_id_from_zone_transfer_request(self):
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id(
+ [], {'x': objects.ZoneTransferRequest(zone_id=123)})
+ )
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id(
+ [objects.ZoneTransferRequest(zone_id=123)], {})
+ )
+
+ def test_extract_zone_id_from_zone_transfer_accept(self):
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id(
+ [], {'x': objects.ZoneTransferAccept(zone_id=123)})
+ )
+ self.assertEqual(
+ '123',
+ lock.extract_zone_id([objects.ZoneTransferAccept(zone_id=123)], {})
+ )
+
+ def test_extract_zone_id_from_second_argument(self):
+ self.assertEqual('456', lock.extract_zone_id(['123', '456'], {}))
+
+ def test_extract_zone_id_when_second_argument_is_a_zone(self):
+ self.assertEqual(
+ '456', lock.extract_zone_id(['123', objects.Zone(id=456)], {})
+ )
diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
index 7ff248ae..22363700 100644
--- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
+++ b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
@@ -8,11 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: Designate Release Notes\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-10-15 00:52+0000\n"
+"POT-Creation-Date: 2022-10-25 21:48+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2022-10-16 10:42+0000\n"
+"PO-Revision-Date: 2022-11-04 10:30+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en_GB\n"
@@ -46,8 +46,8 @@ msgstr "12.0.0"
msgid "12.1.0"
msgstr "12.1.0"
-msgid "12.1.0-4"
-msgstr "12.1.0-4"
+msgid "12.1.0-5"
+msgstr "12.1.0-5"
msgid "13.0.0"
msgstr "13.0.0"
@@ -70,8 +70,8 @@ msgstr "14.0.1-5"
msgid "15.0.0"
msgstr "15.0.0"
-msgid "15.0.0.0rc1-11"
-msgstr "15.0.0.0rc1-11"
+msgid "15.0.0.0rc1-14"
+msgstr "15.0.0.0rc1-14"
msgid "2.0.0"
msgstr "2.0.0"
diff --git a/setup.cfg b/setup.cfg
index bad15c98..4d223650 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,13 +1,13 @@
[metadata]
name = designate
-summary = DNS as a Service
-description_file =
- README.rst
+description = DNS as a Service
+long_description = file: README.rst
+
author = OpenStack
author_email = openstack-discuss@lists.openstack.org
-home_page = https://docs.openstack.org/designate/latest/
+url = https://docs.openstack.org/designate/latest/
python_requires = >=3.8
-classifier =
+classifiers =
Environment :: OpenStack
Environment :: No Input/Output (Daemon)
Intended Audience :: Information Technology
@@ -19,7 +19,7 @@ classifier =
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3
Programming Language :: Python :: 3.8
- Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
Topic :: Internet :: Name Service (DNS)
[files]