Improve NS1 test coverage

Change-Id: I784acb919790da08c841605c5971a19517c508b1
This commit is contained in:
Erik Olof Gunnar Andersson 2023-12-17 09:12:23 -08:00
parent 39a8c8f116
commit ff70036bf9
2 changed files with 124 additions and 23 deletions
designate
backend
tests/unit/backend

@ -33,14 +33,14 @@ class NS1Backend(base.Backend):
def __init__(self, target):
super().__init__(target)
self.api_endpoint = "https://" + self.options.get('api_endpoint')
self.api_endpoint = 'https://' + self.options.get('api_endpoint')
self.api_token = self.options.get('api_token')
self.tsigkey_name = self.options.get('tsigkey_name', None)
self.tsigkey_hash = self.options.get('tsigkey_hash', None)
self.tsigkey_value = self.options.get('tsigkey_value', None)
self.headers = {
"X-NSONE-Key": self.api_token
'X-NSONE-Key': self.api_token
}
def _build_url(self, zone):
@ -56,7 +56,6 @@ class NS1Backend(base.Backend):
raise exceptions.Backend(e)
def _check_zone_exists(self, zone):
try:
requests.get(
self._build_url(zone),
@ -75,23 +74,22 @@ class NS1Backend(base.Backend):
return True
def create_zone(self, context, zone):
master = self._get_master()
# designate requires "." at end of zone name, NS1 requires omitting
data = {
"zone": zone.name.rstrip('.'),
"secondary": {
"enabled": True,
"primary_ip": master.host,
"primary_port": master.port
'zone': zone.name.rstrip('.'),
'secondary': {
'enabled': True,
'primary_ip': master.host,
'primary_port': master.port
}
}
if self.tsigkey_name:
tsig = {
"enabled": True,
"hash": self.tsigkey_hash,
"name": self.tsigkey_name,
"key": self.tsigkey_value
'enabled': True,
'hash': self.tsigkey_hash,
'name': self.tsigkey_name,
'key': self.tsigkey_value
}
data['secondary']['tsig'] = tsig
@ -105,17 +103,21 @@ class NS1Backend(base.Backend):
except requests.HTTPError as e:
# check if the zone was actually created
if self._check_zone_exists(zone):
LOG.info("%s was created with an error. Deleting zone",
zone.name)
LOG.info(
'%s was created with an error. Deleting zone',
zone.name
)
try:
self.delete_zone(context, zone)
except exceptions.Backend:
LOG.error('Could not delete errored zone %s',
zone.name)
LOG.error(
'Could not delete errored zone %s', zone.name
)
raise exceptions.Backend(e)
else:
LOG.info("Can't create zone %s because it already exists",
zone.name)
LOG.info(
"Can't create zone %s because it already exists", zone.name
)
def delete_zone(self, context, zone, zone_params=None):
"""Delete a DNS zone"""
@ -130,6 +132,7 @@ class NS1Backend(base.Backend):
except requests.HTTPError as e:
raise exceptions.Backend(e)
else:
LOG.warning("Trying to delete zone %s but that zone is not "
"present in the ns1 backend. Assuming success.",
zone)
LOG.warning(
'Trying to delete zone %s but that zone is not present in the '
'ns1 backend. Assuming success.', zone
)

@ -14,9 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from unittest import mock
import oslotest.base
import requests
import requests_mock
from designate.backend import impl_ns1
@ -141,7 +143,6 @@ class NS1BackendTestCase(oslotest.base.BaseTestCase):
@requests_mock.mock()
def test_create_zone_already_exists(self, req_mock):
req_mock.get(self.api_address, status_code=200)
req_mock.put(self.api_address)
@ -178,6 +179,49 @@ class NS1BackendTestCase(oslotest.base.BaseTestCase):
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
)
@requests_mock.mock()
def test_create_zone_fail_http_request(self, req_mock):
req_mock.put(
self.api_address,
status_code=500,
)
req_mock.get(
self.api_address,
status_code=404,
)
self.backend._check_zone_exists = mock.Mock()
self.backend._check_zone_exists.side_effect = [False, True]
self.backend.delete_zone = mock.Mock()
self.assertRaisesRegex(
exceptions.Backend,
'500 Server Error',
self.backend.create_zone, self.context, self.zone
)
@requests_mock.mock()
def test_create_zone_fail_delete_zone(self, req_mock):
req_mock.put(
self.api_address,
status_code=500,
)
req_mock.get(
self.api_address,
status_code=404,
)
self.backend._check_zone_exists = mock.Mock()
self.backend._check_zone_exists.side_effect = [False, True]
self.backend.delete_zone = mock.Mock()
self.backend.delete_zone.side_effect = exceptions.Backend()
self.assertRaisesRegex(
exceptions.Backend,
'500 Server Error',
self.backend.create_zone, self.context, self.zone
)
@requests_mock.mock()
def test_delete_zone_success(self, req_mock):
req_mock.delete(self.api_address, status_code=200)
@ -224,3 +268,57 @@ class NS1BackendTestCase(oslotest.base.BaseTestCase):
self.assertEqual(
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
)
def test_get_master(self):
target_master = objects.PoolTargetMaster(host='192.0.2.1', port=53)
self.backend.options = objects.PoolTargetMasterList(
objects=[target_master]
)
self.assertEqual(target_master, self.backend._get_master())
def test_get_master_no_master(self):
backend = impl_ns1.NS1Backend(
objects.PoolTarget.from_dict({
'id': '4588652b-50e7-46b9-b688-a9bad40a873e',
'type': 'ns1',
'masters': [],
'options': [
{'key': 'api_endpoint', 'value': '192.0.2.3'},
{'key': 'api_token', 'value': 'test_key'},
],
})
)
self.assertRaisesRegex(
exceptions.Backend,
'list index out of range',
backend._get_master
)
@requests_mock.mock()
def test_check_zone_exists_server_error(self, req_mock):
req_mock.get(
self.api_address,
status_code=500
)
self.assertRaisesRegex(
exceptions.Backend,
'500 Server Error',
self.backend._check_zone_exists, self.zone
)
@requests_mock.mock()
def test_check_zone_exists_connection_error(self, req_mock):
req_mock.get(
self.api_address,
exc=requests.ConnectionError('error')
)
self.assertRaisesRegex(
exceptions.Backend,
'error',
self.backend._check_zone_exists, self.zone
)