diff --git a/neutron/conf/services/extdns_designate_driver.py b/neutron/conf/services/extdns_designate_driver.py index ddb151795d8..39c244f5120 100644 --- a/neutron/conf/services/extdns_designate_driver.py +++ b/neutron/conf/services/extdns_designate_driver.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +from keystoneauth1 import loading from oslo_config import cfg from neutron._i18n import _ @@ -62,3 +63,4 @@ designate_opts = [ def register_designate_opts(cfg=cfg.CONF): cfg.register_opts(designate_opts, 'designate') + loading.conf.register_conf_options(cfg, 'designate') diff --git a/neutron/services/externaldns/drivers/designate/driver.py b/neutron/services/externaldns/drivers/designate/driver.py index 698b036f9f4..e453fd7020c 100644 --- a/neutron/services/externaldns/drivers/designate/driver.py +++ b/neutron/services/externaldns/drivers/designate/driver.py @@ -18,6 +18,7 @@ import netaddr from designateclient import exceptions as d_exc from designateclient.v2 import client as d_client from keystoneauth1.identity.generic import password +from keystoneauth1 import loading from keystoneauth1 import session from keystoneauth1 import token_endpoint from neutron_lib import constants @@ -50,12 +51,16 @@ def get_clients(context): auth = token_endpoint.Token(CONF.designate.url, context.auth_token) client = d_client.Client(session=_SESSION, auth=auth) - admin_auth = password.Password( - auth_url=CONF.designate.admin_auth_url, - username=CONF.designate.admin_username, - password=CONF.designate.admin_password, - tenant_name=CONF.designate.admin_tenant_name, - tenant_id=CONF.designate.admin_tenant_id) + if CONF.designate.auth_type: + admin_auth = loading.load_auth_from_conf_options( + CONF, 'designate') + else: + admin_auth = password.Password( + auth_url=CONF.designate.admin_auth_url, + username=CONF.designate.admin_username, + password=CONF.designate.admin_password, + tenant_name=CONF.designate.admin_tenant_name, + tenant_id=CONF.designate.admin_tenant_id) admin_client = d_client.Client(session=_SESSION, auth=admin_auth) return client, admin_client diff --git a/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py b/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py index cf279af8f58..17fc5de1f23 100644 --- a/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py +++ b/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py @@ -15,6 +15,7 @@ import uuid +from keystoneauth1 import loading import mock import netaddr from neutron_lib import constants @@ -527,7 +528,7 @@ class DNSIntegrationTestCaseDefaultDomain(DNSIntegrationTestCase): self._verify_port_dns(net, port, dns_data_db) -class TestDesignateClient(testtools.TestCase): +class TestDesignateClientKeystoneV2(testtools.TestCase): """Test case for designate clients """ TEST_URL = 'http://127.0.0.1:9001/v2' @@ -542,7 +543,7 @@ class TestDesignateClient(testtools.TestCase): TEST_CONTEXT.auth_token = uuid.uuid4().hex def setUp(self): - super(TestDesignateClient, self).setUp() + super(TestDesignateClientKeystoneV2, self).setUp() config.cfg.CONF.set_override('url', self.TEST_URL, group='designate') @@ -565,8 +566,12 @@ class TestDesignateClient(testtools.TestCase): # enforce session recalculation mock.patch.object(driver, '_SESSION', new=None).start() self.driver_session = ( - mock.patch.object(driver.session, 'Session').start() - ) + mock.patch.object(driver.session, 'Session').start()) + self.load_auth = ( + mock.patch.object(driver.loading, + 'load_auth_from_conf_options').start()) + self.password = ( + mock.patch.object(driver.password, 'Password').start()) def test_insecure_client(self): config.cfg.CONF.set_override('insecure', @@ -584,3 +589,96 @@ class TestDesignateClient(testtools.TestCase): group='designate') driver.get_clients(self.TEST_CONTEXT) self.driver_session.assert_called_with(verify=self.TEST_CA_CERT) + + def test_auth_type_not_defined(self): + driver.get_clients(self.TEST_CONTEXT) + self.load_auth.assert_not_called() + self.password.assert_called_with( + auth_url=self.TEST_ADMIN_AUTH_URL, + password=self.TEST_ADMIN_PASSWORD, + tenant_id=self.TEST_ADMIN_TENANT_ID, + tenant_name=self.TEST_ADMIN_TENANT_NAME, + username=self.TEST_ADMIN_USERNAME) + + +class TestDesignateClientKeystoneV3(testtools.TestCase): + """Test case for designate clients """ + + TEST_URL = 'http://127.0.0.1:9001/v2' + TEST_ADMIN_USERNAME = uuid.uuid4().hex + TEST_ADMIN_PASSWORD = uuid.uuid4().hex + TEST_ADMIN_USER_DOMAIN_ID = 'Default' + TEST_ADMIN_PROJECT_ID = uuid.uuid4().hex + TEST_ADMIN_PROJECT_DOMAIN_ID = 'Default' + TEST_ADMIN_AUTH_URL = 'http://127.0.0.1:35357/v3' + TEST_CA_CERT = uuid.uuid4().hex + + TEST_CONTEXT = mock.Mock() + TEST_CONTEXT.auth_token = uuid.uuid4().hex + + def setUp(self): + super(TestDesignateClientKeystoneV3, self).setUp() + # Register the Password auth plugin options, + # so we can use CONF.set_override + config.cfg.CONF.register_opts( + loading.get_auth_plugin_conf_options('password'), + group='designate') + config.cfg.CONF.set_override('url', + self.TEST_URL, + group='designate') + config.cfg.CONF.set_override('auth_type', + 'password', + group='designate') + config.cfg.CONF.set_override('username', + self.TEST_ADMIN_USERNAME, + group='designate') + config.cfg.CONF.set_override('password', + self.TEST_ADMIN_PASSWORD, + group='designate') + config.cfg.CONF.set_override('user_domain_id', + self.TEST_ADMIN_USER_DOMAIN_ID, + group='designate') + config.cfg.CONF.set_override('project_domain_id', + self.TEST_ADMIN_PROJECT_DOMAIN_ID, + group='designate') + config.cfg.CONF.set_override('auth_url', + self.TEST_ADMIN_AUTH_URL, + group='designate') + + # enforce session recalculation + mock.patch.object(driver, '_SESSION', new=None).start() + self.driver_session = ( + mock.patch.object(driver.session, 'Session').start()) + self.load_auth = ( + mock.patch.object(driver.loading, + 'load_auth_from_conf_options').start()) + self.password = ( + mock.patch.object(driver.password, 'Password').start()) + + def tearDown(self): + super(TestDesignateClientKeystoneV3, self).tearDown() + config.cfg.CONF.unregister_opts( + loading.get_auth_plugin_conf_options('password'), + group='designate') + + def test_insecure_client(self): + config.cfg.CONF.set_override('insecure', + True, + group='designate') + driver.get_clients(self.TEST_CONTEXT) + self.driver_session.assert_called_with(verify=False) + + def test_secure_client(self): + config.cfg.CONF.set_override('insecure', + False, + group='designate') + config.cfg.CONF.set_override('ca_cert', + self.TEST_CA_CERT, + group='designate') + driver.get_clients(self.TEST_CONTEXT) + self.driver_session.assert_called_with(verify=self.TEST_CA_CERT) + + def test_auth_type_password(self): + driver.get_clients(self.TEST_CONTEXT) + self.load_auth.assert_called_with(config.cfg.CONF, 'designate') + self.password.assert_not_called() diff --git a/releasenotes/notes/designate-driver-keystonev3-8e70d152e84388e0.yaml b/releasenotes/notes/designate-driver-keystonev3-8e70d152e84388e0.yaml new file mode 100644 index 00000000000..a7c904ea491 --- /dev/null +++ b/releasenotes/notes/designate-driver-keystonev3-8e70d152e84388e0.yaml @@ -0,0 +1,9 @@ +--- +prelude: > + Designate driver can use Keystone v3 auth options. +features: + - "[designate] section accepts now auth_type parameter, + and the usual keystoneauth options (e.g. auth_url, + username, user_domain_name, password, project_name, + project_domain_name), so Keystone v3 endpoints can + be used."