diff --git a/.gitignore b/.gitignore index 405155413..42bca0b41 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ Pipfile.lock # Tobiko configuration file tobiko.conf +clouds.yaml +ssh_config diff --git a/tobiko/__init__.py b/tobiko/__init__.py index 27fd6b096..31923b8f7 100644 --- a/tobiko/__init__.py +++ b/tobiko/__init__.py @@ -14,6 +14,7 @@ from __future__ import absolute_import from tobiko.common import _asserts +from tobiko.common import _config from tobiko.common import _detail from tobiko.common import _exception from tobiko.common import _fixture @@ -31,6 +32,10 @@ details_content = _detail.details_content FailureException = _asserts.FailureException fail = _asserts.fail +tobiko_config = _config.tobiko_config +tobiko_config_dir = _config.tobiko_config_dir +tobiko_config_path = _config.tobiko_config_path + TobikoException = _exception.TobikoException check_valid_type = _exception.check_valid_type exc_info = _exception.exc_info diff --git a/tobiko/common/_config.py b/tobiko/common/_config.py new file mode 100644 index 000000000..7d6787efc --- /dev/null +++ b/tobiko/common/_config.py @@ -0,0 +1,43 @@ +# Copyright 2020 Red Hat +# +# 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 __future__ import absolute_import + + +import os + +from tobiko.common import _fixture + + +class TobikoConfigFicture(_fixture.SharedFixture): + + config = None + + def setup_fixture(self): + from tobiko import config + self.config = config.CONF.tobiko + + +def tobiko_config(): + return _fixture.setup_fixture(TobikoConfigFicture).config + + +def tobiko_config_dir(): + return tobiko_config().config_dir + + +def tobiko_config_path(path): + path = os.path.expanduser(path) + if not os.path.isabs(path): + path = os.path.join(tobiko_config_dir(), path) + return os.path.realpath(path) diff --git a/tobiko/config.py b/tobiko/config.py index 4a001cf93..0c7508744 100644 --- a/tobiko/config.py +++ b/tobiko/config.py @@ -160,8 +160,9 @@ def init_tobiko_config(default_config_dirs=None, default_config_files=None, CONF.set_source('tobiko', conf) # expand and normalize log_file and log_dir names + conf.config_dir = os.path.realpath(conf.find_file('.')) + log_dir = conf.log_dir or conf.config_dir log_file = conf.log_file or 'tobiko.log' - log_dir = conf.log_dir or conf.find_file('.') log_path = os.path.realpath(os.path.expanduser( os.path.join(log_dir, log_file))) conf.log_dir = os.path.dirname(log_path) diff --git a/tobiko/openstack/keystone/_clouds_file.py b/tobiko/openstack/keystone/_clouds_file.py index 4091c699c..0ee0f455e 100644 --- a/tobiko/openstack/keystone/_clouds_file.py +++ b/tobiko/openstack/keystone/_clouds_file.py @@ -42,23 +42,21 @@ class DefaultCloudsFileConfig(tobiko.SharedFixture): clouds_files = None def setup_fixture(self): - from tobiko import config - CONF = config.CONF - keystone_conf = CONF.tobiko.keystone + keystone_conf = tobiko.tobiko_config().keystone self.cloud_name = keystone_conf.cloud_name - self.clouds_file_dirs = [ - os.path.realpath(os.path.expanduser(d)) - for d in keystone_conf.clouds_file_dirs] + self.clouds_file_dirs = keystone_conf.clouds_file_dirs self.clouds_file_names = keystone_conf.clouds_file_names self.clouds_files = self.list_cloud_files() def list_cloud_files(self): cloud_files = [] for directory in self.clouds_file_dirs: - directory = os.path.realpath(os.path.expanduser(directory)) - for file_name in self.clouds_file_names: - file_name = os.path.join(directory, file_name) - cloud_files.append(file_name) + directory = tobiko.tobiko_config_path(directory) + if os.path.isdir(directory): + for file_name in self.clouds_file_names: + file_name = os.path.join(directory, file_name) + if os.path.isfile(file_name): + cloud_files.append(file_name) return cloud_files diff --git a/tobiko/openstack/keystone/_credentials.py b/tobiko/openstack/keystone/_credentials.py index 86e168fbc..4a7032ff2 100644 --- a/tobiko/openstack/keystone/_credentials.py +++ b/tobiko/openstack/keystone/_credentials.py @@ -21,6 +21,7 @@ from oslo_log import log import yaml import tobiko +import testtools LOG = log.getLogger(__name__) @@ -267,17 +268,30 @@ class DefaultKeystoneCredentialsFixture(KeystoneCredentialsFixture): fixtures = DEFAULT_KEYSTONE_CREDENTIALS_FIXTURES def get_credentials(self): + errors = [] for fixture in self.fixtures: try: credentials = tobiko.setup_fixture(fixture).credentials except Exception: - LOG.exception("Error setting up fixture %r", fixture) + LOG.debug("Error getting cretentials from %r", fixture) + errors.append(tobiko.exc_info()) continue if credentials: LOG.info("Got default credentials from fixture %r: %r", fixture, credentials) return credentials + else: + LOG.debug('Got no credentials from %r', fixture) + + if len(errors) == 1: + errors[0].reraise() + elif errors: + raise testtools.MultipleExceptions(errors) + + raise ValueError("No such credentials from any of: \n " + + '\n '.join(tobiko.get_fixture_name(fixture) + for fixture in self.fixtures)) def api_version_from_url(auth_url): diff --git a/tobiko/shell/ssh/_config.py b/tobiko/shell/ssh/_config.py index a285c4a99..7613b454c 100644 --- a/tobiko/shell/ssh/_config.py +++ b/tobiko/shell/ssh/_config.py @@ -44,9 +44,7 @@ class SSHDefaultConfigFixture(tobiko.SharedFixture): conf = None def setup_fixture(self): - from tobiko import config - CONF = config.CONF - self.conf = CONF.tobiko.ssh + self.conf = tobiko.tobiko_config().ssh def __getattr__(self, name): return getattr(self.conf, name) @@ -72,7 +70,7 @@ class SSHConfigFixture(tobiko.SharedFixture): def setup_ssh_config(self): self.config = paramiko.SSHConfig() for config_file in self.config_files: - config_file = os.path.expanduser(config_file) + config_file = tobiko.tobiko_config_path(config_file) if os.path.exists(config_file): LOG.debug("Parsing %r config file...", config_file) with open(config_file) as f: diff --git a/tobiko/shell/ssh/config.py b/tobiko/shell/ssh/config.py index 9d2048eb2..1c08d13f1 100644 --- a/tobiko/shell/ssh/config.py +++ b/tobiko/shell/ssh/config.py @@ -34,7 +34,8 @@ OPTIONS = [ default=None, help=('Default SSH username')), cfg.ListOpt('config_files', - default=['/etc/ssh/ssh_config', '~/.ssh/config'], + default=['/etc/ssh/ssh_config', '~/.ssh/config', + './ssh_config'], help="Default user SSH configuration files"), cfg.StrOpt('key_file', default='~/.ssh/id_rsa',