From 3fe09b84e995d53ed17ba5f07e3a3767cfccae03 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Fri, 29 Mar 2019 15:35:26 +0100 Subject: [PATCH] Allow replacing service implementation Some clouds are offering their own incompatible implementation of system services. While with add_service we can add new implementation of the service, we can not replace system-ones. So let's allow deleting service to be able to have a custom service implementation in SDK. Change-Id: I55ef310d114702e5dc98a237fc1d8d130c09c5e1 --- openstack/service_description.py | 11 ++++++++++- openstack/tests/unit/test_connection.py | 26 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/openstack/service_description.py b/openstack/service_description.py index bfe46a7f5..617bf7b56 100644 --- a/openstack/service_description.py +++ b/openstack/service_description.py @@ -202,4 +202,13 @@ class ServiceDescription(object): raise AttributeError('Service Descriptors cannot be set') def __delete__(self, instance): - raise AttributeError('Service Descriptors cannot be deleted') + # NOTE(gtema) Some clouds are not very fast (or interested at all) + # in bringing their changes upstream. If there are incompatible changes + # downstream we need to allow overriding default implementation by + # deleting service_type attribute of the connection and then + # "add_service" with new implementation. + # This is implemented explicitely not very comfortable to use + # to show how bad it is not to contribute changes back + for service_type in self.all_types: + if service_type in instance._proxies: + del instance._proxies[service_type] diff --git a/openstack/tests/unit/test_connection.py b/openstack/tests/unit/test_connection.py index ce2320cc6..ef4117f96 100644 --- a/openstack/tests/unit/test_connection.py +++ b/openstack/tests/unit/test_connection.py @@ -308,3 +308,29 @@ class TestNewService(base.TestCase): 'openstack.tests.unit.fake.v2._proxy', conn.fake.__class__.__module__) self.assertFalse(conn.fake.dummy()) + + def test_replace_system_service(self): + self.use_keystone_v3(catalog='catalog-v3-fake-v2.json') + conn = self.cloud + + # delete native dns service + delattr(conn, 'dns') + + self.register_uris([ + dict(method='GET', + uri='https://fake.example.com', + status_code=404), + dict(method='GET', + uri='https://fake.example.com/v2/', + status_code=404), + dict(method='GET', + uri=self.get_mock_url('fake'), + status_code=404), + ]) + + # add fake service with alias 'DNS' + service = fake_service.FakeService('fake', aliases=['dns']) + conn.add_service(service) + + # ensure dns service responds as we expect from replacement + self.assertFalse(conn.dns.dummy())