summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/vendor-support.rst4
-rw-r--r--os_client_config/config.py87
-rw-r--r--os_client_config/tests/test_config.py15
3 files changed, 97 insertions, 9 deletions
diff --git a/doc/source/vendor-support.rst b/doc/source/vendor-support.rst
index c4f5a4f..77d10eb 100644
--- a/doc/source/vendor-support.rst
+++ b/doc/source/vendor-support.rst
@@ -145,8 +145,8 @@ https://auth.cloud.ovh.net/v2.0
============== ================
Region Name Human Name
============== ================
-SBG-1 Strassbourg, FR
-GRA-1 Gravelines, FR
+SBG1 Strassbourg, FR
+GRA1 Gravelines, FR
============== ================
* Images must be in `raw` format
diff --git a/os_client_config/config.py b/os_client_config/config.py
index e8e76a5..1b6193e 100644
--- a/os_client_config/config.py
+++ b/os_client_config/config.py
@@ -17,7 +17,10 @@ import os
import warnings
import appdirs
-from keystoneauth1 import loading
+try:
+ from keystoneauth1 import loading
+except ImportError:
+ loading = None
import yaml
from os_client_config import cloud_config
@@ -382,8 +385,13 @@ class OpenStackConfig(object):
os_args = dict()
new_args = dict()
for (key, val) in iter(args.items()):
+ if type(args[key]) == dict:
+ # dive into the auth dict
+ new_args[key] = self._fix_args(args[key])
+ continue
+
key = key.replace('-', '_')
- if key.startswith('os'):
+ if key.startswith('os_'):
os_args[key[3:]] = val
else:
new_args[key] = val
@@ -395,7 +403,9 @@ class OpenStackConfig(object):
if opt_name in config:
return config[opt_name]
else:
- for d_opt in opt.deprecated:
+ deprecated = getattr(opt, 'deprecated', getattr(
+ opt, 'deprecated_opts', []))
+ for d_opt in deprecated:
d_opt_name = d_opt.name.replace('-', '_')
if d_opt_name in config:
return config[d_opt_name]
@@ -412,6 +422,54 @@ class OpenStackConfig(object):
config['auth']['token'] = None
return loading.get_plugin_loader(config['auth_type'])
+ def _validate_auth_ksc(self, config):
+ try:
+ import keystoneclient.auth as ksc_auth
+ except ImportError:
+ return config
+
+ # May throw a keystoneclient.exceptions.NoMatchingPlugin
+ plugin_options = ksc_auth.get_plugin_class(
+ config['auth_type']).get_options()
+
+ for p_opt in plugin_options:
+ # if it's in config.auth, win, kill it from config dict
+ # if it's in config and not in config.auth, move it
+ # deprecated loses to current
+ # provided beats default, deprecated or not
+ winning_value = self._find_winning_auth_value(
+ p_opt, config['auth'])
+ if not winning_value:
+ winning_value = self._find_winning_auth_value(p_opt, config)
+
+ # if the plugin tells us that this value is required
+ # then error if it's doesn't exist now
+ if not winning_value and p_opt.required:
+ raise exceptions.OpenStackConfigException(
+ 'Unable to find auth information for cloud'
+ ' {cloud} in config files {files}'
+ ' or environment variables. Missing value {auth_key}'
+ ' required for auth plugin {plugin}'.format(
+ cloud=cloud, files=','.join(self._config_files),
+ auth_key=p_opt.name, plugin=config.get('auth_type')))
+
+ # Clean up after ourselves
+ for opt in [p_opt.name] + [o.name for o in p_opt.deprecated_opts]:
+ opt = opt.replace('-', '_')
+ config.pop(opt, None)
+ config['auth'].pop(opt, None)
+
+ if winning_value:
+ # Prefer the plugin configuration dest value if the value's key
+ # is marked as depreciated.
+ if p_opt.dest is None:
+ config['auth'][p_opt.name.replace('-', '_')] = (
+ winning_value)
+ else:
+ config['auth'][p_opt.dest] = winning_value
+
+ return config
+
def _validate_auth(self, config, loader):
# May throw a keystoneauth1.exceptions.NoMatchingPlugin
@@ -490,12 +548,27 @@ class OpenStackConfig(object):
if type(config[key]) is not bool:
config[key] = get_boolean(config[key])
- loader = self._get_auth_loader(config)
- if validate:
- config = self._validate_auth(config, loader)
- auth_plugin = loader.load_from_options(**config['auth'])
+ if loading:
+ if validate:
+ try:
+ loader = self._get_auth_loader(config)
+ config = self._validate_auth(config, loader)
+ auth_plugin = loader.load_from_options(**config['auth'])
+ except Exception as e:
+ # We WANT the ksa exception normally
+ # but OSC can't handle it right now, so we try deferring
+ # to ksc. If that ALSO fails, it means there is likely
+ # a deeper issue, so we assume the ksa error was correct
+ auth_plugin = None
+ try:
+ config = self._validate_auth_ksc(config)
+ except Exception:
+ raise e
+ else:
+ auth_plugin = None
else:
auth_plugin = None
+ config = self._validate_auth_ksc(config)
# If any of the defaults reference other values, we need to expand
for (key, value) in config.items():
diff --git a/os_client_config/tests/test_config.py b/os_client_config/tests/test_config.py
index b4320ad..3331b33 100644
--- a/os_client_config/tests/test_config.py
+++ b/os_client_config/tests/test_config.py
@@ -106,6 +106,21 @@ class TestConfig(base.TestCase):
cc = c.get_one_cloud('_test_cloud_hyphenated')
self.assertEqual('12345', cc.auth['project_id'])
+ def test_get_one_cloud_with_hyphenated_kwargs(self):
+ c = config.OpenStackConfig(config_files=[self.cloud_yaml],
+ vendor_files=[self.vendor_yaml])
+ args = {
+ 'auth': {
+ 'username': 'testuser',
+ 'password': 'testpass',
+ 'project-id': '12345',
+ 'auth-url': 'http://example.com/v2',
+ },
+ 'region_name': 'test-region',
+ }
+ cc = c.get_one_cloud(**args)
+ self.assertEqual('http://example.com/v2', cc.auth['auth_url'])
+
def test_no_environ(self):
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
vendor_files=[self.vendor_yaml])