Use openstack.config for config and Session objects

The TimingSession functionality has been merged into keystoneauth. This
allows us to use the CloudRegion object to get the Session directly.

Change-Id: Ib4c9210e681a2d2d9c5fc40de2c3ede1a5003154
This commit is contained in:
Monty Taylor 2018-05-26 10:53:33 -07:00
parent bcf08b9c06
commit ee79f6166e
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
13 changed files with 65 additions and 168 deletions

View File

@ -31,7 +31,7 @@ Jinja2==2.10
jmespath==0.9.0
jsonpatch==1.16
jsonpointer==1.13
keystoneauth1==3.4.0
keystoneauth1==3.7.0
kombu==4.0.0
linecache2==1.0.0
MarkupSafe==1.0
@ -44,8 +44,7 @@ munch==2.1.0
netaddr==0.7.18
netifaces==0.10.4
openstackdocstheme==1.18.1
openstacksdk==0.11.2
os-client-config==1.28.0
openstacksdk==0.13.0
os-service-types==1.2.0
os-testr==1.0.0
oslo.concurrency==3.25.0

View File

@ -15,15 +15,8 @@
import logging
try:
from openstack.config import exceptions as occ_exceptions
except ImportError:
from os_client_config import exceptions as occ_exceptions
try:
from openstack.config import loader as config
except ImportError:
from os_client_config import config
from openstack.config import exceptions as sdk_exceptions
from openstack.config import loader as config
from oslo_utils import strutils
import six
@ -220,7 +213,7 @@ class OSC_Config(config.OpenStackConfig):
prompt_options.append(p_opt)
if msgs:
raise occ_exceptions.OpenStackConfigException('\n'.join(msgs))
raise sdk_exceptions.OpenStackConfigException('\n'.join(msgs))
else:
for p_opt in prompt_options:
config['auth'][p_opt.dest] = self._pw_callback(p_opt.prompt)

View File

@ -19,22 +19,14 @@ import copy
import logging
import sys
from openstack.config import loader as config # noqa
from openstack import connection
from oslo_utils import strutils
import six
from osc_lib.api import auth
from osc_lib import exceptions
from osc_lib import session as osc_session
from osc_lib import version
# NOTE(dtroyer): Attempt an import to detect if the SDK installed is new
# enough to not use Profile. If so, use that.
try:
from openstack.config import loader as config # noqa
profile = None
except ImportError:
from openstack import profile
LOG = logging.getLogger(__name__)
@ -209,22 +201,9 @@ class ClientManager(object):
self._cli_options.remote_project_domain_name
)
self.session = osc_session.TimingSession(
auth=self.auth,
verify=self.verify,
cert=self.cert,
app_name=self._app_name,
app_version=self._app_version,
additional_user_agent=[('osc-lib', version.version_string)],
)
self.session = self._cli_options.get_session()
# Create a common default SDK Connection object if it is the newer
# non-Profile style.
if profile is None:
self.sdk_connection = connection.Connection(
config=self._cli_options,
session=self.session,
)
self.sdk_connection = connection.Connection(config=self._cli_options)
self._auth_setup_completed = True

View File

@ -27,13 +27,10 @@ class Timing(command.Lister):
results = []
total = 0.0
for url, td in self.app.timing_data:
# NOTE(dtroyer): Take the long way here because total_seconds()
# was added in py27.
sec = (td.microseconds + (td.seconds + td.days *
86400) * 1e6) / 1e6
for td in self.app.timing_data:
sec = td.elapsed.total_seconds()
total += sec
results.append((url, sec))
results.append((td.method + ' ' + td.url, sec))
results.append(('Total', total))
return (
column_headers,

View File

@ -1,50 +0,0 @@
# 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.
#
"""Subclass of keystoneauth1.session"""
from keystoneauth1 import session
class TimingSession(session.Session):
"""A Session that supports collection of timing data per Method URL"""
def __init__(
self,
**kwargs
):
"""Pass through all arguments except timing"""
super(TimingSession, self).__init__(**kwargs)
# times is a list of tuples: ("method url", elapsed_time)
self.times = []
def get_timings(self):
return self.times
def reset_timings(self):
self.times = []
def request(self, url, method, **kwargs):
"""Wrap the usual request() method with the timers"""
resp = super(TimingSession, self).request(url, method, **kwargs)
for h in resp.history:
self.times.append((
"%s %s" % (h.request.method, h.request.url),
h.elapsed,
))
self.times.append((
"%s %s" % (resp.request.method, resp.request.url),
resp.elapsed,
))
return resp

View File

@ -38,6 +38,7 @@ from osc_lib import exceptions as exc
from osc_lib.i18n import _
from osc_lib import logs
from osc_lib import utils
from osc_lib import version
osprofiler_profiler = importutils.try_import("osprofiler.profiler")
@ -336,7 +337,7 @@ class OpenStackShell(app.App):
* super()
* _final_defaults()
* OpenStackConfig
* get_one_cloud
* get_one
* _load_plugins()
* _load_commands()
* ClientManager
@ -423,7 +424,7 @@ class OpenStackShell(app.App):
# NOTE(dtroyer): Need to do this with validate=False to defer the
# auth plugin handling to ClientManager.setup_auth()
self.cloud = self.cloud_config.get_one_cloud(
self.cloud = self.cloud_config.get_one(
cloud=self.options.cloud,
argparse=self.options,
validate=False,
@ -462,7 +463,7 @@ class OpenStackShell(app.App):
)
# NOTE(dtroyer): If auth is not required for a command, skip
# get_one_Cloud()'s validation to avoid loading plugins
# get_one()'s validation to avoid loading plugins
validate = cmd.auth_required
# NOTE(dtroyer): Save the auth required state of the _current_ command
@ -470,10 +471,13 @@ class OpenStackShell(app.App):
self.client_manager._auth_required = cmd.auth_required
# Validate auth options
self.cloud = self.cloud_config.get_one_cloud(
self.cloud = self.cloud_config.get_one(
cloud=self.options.cloud,
argparse=self.options,
validate=validate,
app_name=self.client_manager._app_name,
app_version=self.client_manager._app_version,
additional_user_agent=[('osc-lib', version.version_string)],
)
# Push the updated args into ClientManager
self.client_manager._cli_options = self.cloud

View File

@ -15,12 +15,15 @@
import datetime
from keystoneauth1 import session
from osc_lib.command import timing
from osc_lib.tests import fakes
from osc_lib.tests import utils
timing_url = 'GET http://localhost:5000'
timing_method = 'GET'
timing_url = 'http://localhost:5000'
timing_elapsed = 0.872809
@ -73,9 +76,10 @@ class TestTiming(utils.TestCommand):
self.assertEqual(datalist, data)
def test_timing_list(self):
self.app.timing_data = [(
timing_url,
datetime.timedelta(microseconds=timing_elapsed * 1000000),
self.app.timing_data = [session.RequestTiming(
method=timing_method,
url=timing_url,
elapsed=datetime.timedelta(microseconds=timing_elapsed * 1000000),
)]
arglist = []
@ -88,7 +92,7 @@ class TestTiming(utils.TestCommand):
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, columns)
datalist = [
(timing_url, timing_elapsed),
(timing_method + ' ' + timing_url, timing_elapsed),
('Total', timing_elapsed),
]
self.assertEqual(datalist, data)

View File

@ -24,14 +24,8 @@ from keystoneauth1 import loading
from keystoneauth1 import noauth
from keystoneauth1 import token_endpoint
try:
from openstack.config import cloud_config
from openstack.config import defaults
_occ_in_sdk = True
except ImportError:
from os_client_config import cloud_config
from os_client_config import defaults
_occ_in_sdk = False
from openstack.config import cloud_config
from openstack.config import defaults
from openstack import connection
from osc_lib.api import auth
@ -423,10 +417,7 @@ class TestClientManagerSDK(utils.TestClientManager):
auth_required=True,
)
if _occ_in_sdk:
self.assertIsInstance(
client_manager.sdk_connection,
connection.Connection,
)
else:
self.assertIsNone(getattr(client_manager, 'sdk_connection', None))
self.assertIsInstance(
client_manager.sdk_connection,
connection.Connection,
)

View File

@ -22,16 +22,7 @@ import testtools
from osc_lib import shell
from osc_lib.tests import utils
# NOTE(dtroyer): Attempt the import to detect if the SDK installed is new
# enough to contain the os_client_config code. If so, use
# that path for mocks.
CONFIG_MOCK_BASE = "openstack.config.loader"
try:
from openstack.config import loader as config # noqa
except ImportError:
# Fall back to os-client-config
CONFIG_MOCK_BASE = "os_client_config.config"
from openstack.config import loader as config # noqa
DEFAULT_AUTH_URL = "http://127.0.0.1:5000/v2.0/"
DEFAULT_PROJECT_ID = "xxxx-yyyy-zzzz"
@ -197,12 +188,12 @@ class TestShellOptions(utils.TestShell):
def test_empty_auth(self):
os.environ = {}
self._assert_initialize_app_arg("", {})
self._assert_cloud_config_arg("", {})
self._assert_cloud_region_arg("", {})
def test_no_options(self):
os.environ = {}
self._assert_initialize_app_arg("", {})
self._assert_cloud_config_arg("", {})
self._assert_cloud_region_arg("", {})
def test_global_options(self):
self._test_options_init_app(global_options)
@ -322,7 +313,7 @@ class TestShellCli(utils.TestShell):
self.assertEqual('mickey', _shell.options.key)
self.assertEqual(('mycert', 'mickey'), _shell.client_manager.cert)
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_config_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_config_file")
def test_shell_args_cloud_no_vendor(self, config_mock):
"""Test cloud config options without the vendor file"""
config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_1))
@ -371,8 +362,8 @@ class TestShellCli(utils.TestShell):
self.assertIsNone(_shell.cloud.config['key'])
self.assertIsNone(_shell.client_manager.cert)
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_vendor_file")
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_config_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_vendor_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_config_file")
def test_shell_args_cloud_public(self, config_mock, public_mock):
"""Test cloud config options with the vendor file"""
config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2))
@ -420,8 +411,8 @@ class TestShellCli(utils.TestShell):
self.assertEqual('mickey', _shell.cloud.config['key'])
self.assertEqual(('mycert', 'mickey'), _shell.client_manager.cert)
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_vendor_file")
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_config_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_vendor_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_config_file")
def test_shell_args_precedence(self, config_mock, vendor_mock):
config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2))
vendor_mock.return_value = ('file.yaml', copy.deepcopy(PUBLIC_1))
@ -477,8 +468,8 @@ class TestShellCliPrecedence(utils.TestShell):
}
self.useFixture(utils.EnvFixture(env.copy()))
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_vendor_file")
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_config_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_vendor_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_config_file")
def test_shell_args_precedence_1(self, config_mock, vendor_mock):
"""Test environment overriding occ"""
config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2))
@ -525,8 +516,8 @@ class TestShellCliPrecedence(utils.TestShell):
_shell.client_manager.region_name,
)
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_vendor_file")
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_config_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_vendor_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_config_file")
def test_shell_args_precedence_2(self, config_mock, vendor_mock):
"""Test command line overriding environment and occ"""
config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2))
@ -573,8 +564,8 @@ class TestShellCliPrecedence(utils.TestShell):
_shell.client_manager.region_name,
)
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_vendor_file")
@mock.patch(CONFIG_MOCK_BASE + ".OpenStackConfig._load_config_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_vendor_file")
@mock.patch("openstack.config.loader.OpenStackConfig._load_config_file")
def test_shell_args_precedence_3(self, config_mock, vendor_mock):
"""Test command line overriding environment and occ"""
config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_1))

View File

@ -24,12 +24,8 @@ from cliff import columns as cliff_columns
import fixtures
from keystoneauth1 import loading
try:
from openstack.config import cloud_config
from openstack.config import defaults
except ImportError:
from os_client_config import cloud_config
from os_client_config import defaults
from openstack.config import cloud_region
from openstack.config import defaults
from oslo_utils import importutils
from requests_mock.contrib import fixture
@ -40,16 +36,6 @@ from osc_lib import clientmanager
from osc_lib import shell
from osc_lib.tests import fakes
# NOTE(dtroyer): Attempt the import to detect if the SDK installed is new
# enough to contain the os_client_config code. If so, use
# that path for mocks.
CONFIG_MOCK_BASE = "openstack.config.loader"
try:
from openstack.config import loader as config # noqa
except ImportError:
# Fall back to os-client-config
CONFIG_MOCK_BASE = "os_client_config.config"
def fake_execute(shell, cmd):
"""Pretend to execute shell commands."""
@ -301,9 +287,9 @@ class TestClientManager(TestCase):
loader = loading.get_plugin_loader(auth_plugin_name)
auth_plugin = loader.load_from_options(**auth_dict)
client_manager = self._clientmanager_class()(
cli_options=cloud_config.CloudConfig(
cli_options=cloud_region.CloudRegion(
name='t1',
region='1',
region_name='1',
config=cli_options,
auth_plugin=auth_plugin,
),
@ -361,10 +347,10 @@ class TestShell(TestCase):
"%s does not match" % k,
)
def _assert_cloud_config_arg(self, cmd_options, default_args):
"""Check the args passed to cloud_config.get_one_cloud()
def _assert_cloud_region_arg(self, cmd_options, default_args):
"""Check the args passed to OpenStackConfig.get_one()
The argparse argument to get_one_cloud() is an argparse.Namespace
The argparse argument to get_one() is an argparse.Namespace
object that contains all of the options processed to this point in
initialize_app().
"""
@ -373,7 +359,7 @@ class TestShell(TestCase):
cloud.config = {}
self.occ_get_one = mock.Mock(return_value=cloud)
with mock.patch(
CONFIG_MOCK_BASE + ".OpenStackConfig.get_one_cloud",
"openstack.config.loader.OpenStackConfig.get_one",
self.occ_get_one,
):
_shell = make_shell(shell_class=self.shell_class)
@ -432,7 +418,7 @@ class TestShell(TestCase):
kwargs = {
key: test_opts[opt][0],
}
self._assert_cloud_config_arg(cmd, kwargs)
self._assert_cloud_region_arg(cmd, kwargs)
def _test_env_get_one_cloud(self, test_opts):
"""Test environment options sent "to openstack.config"""
@ -447,4 +433,4 @@ class TestShell(TestCase):
opt2env(opt): test_opts[opt][0],
}
os.environ = env.copy()
self._assert_cloud_config_arg("", kwargs)
self._assert_cloud_region_arg("", kwargs)

View File

@ -0,0 +1,5 @@
---
upgrade:
- |
The dependency on ``os-client-config`` has been removed in favor of
direct use of ``openstacksdk``.

View File

@ -6,9 +6,8 @@ six>=1.10.0 # MIT
Babel!=2.4.0,>=2.3.4 # BSD
cliff!=2.9.0,>=2.8.0 # Apache-2.0
keystoneauth1>=3.4.0 # Apache-2.0
openstacksdk>=0.11.2 # Apache-2.0
os-client-config>=1.28.0 # Apache-2.0
keystoneauth1>=3.7.0 # Apache-2.0
openstacksdk>=0.13.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
simplejson>=3.5.1 # MIT

View File

@ -22,7 +22,6 @@ basepython = python3
commands =
pip install -q -e "git+file://{toxinidir}/../cliff#egg=cliff"
pip install -q -e "git+file://{toxinidir}/../keystoneauth#egg=keystoneauth"
pip install -q -e "git+file://{toxinidir}/../os-client-config#egg=os_client_config"
pip install -q -e "git+file://{toxinidir}/../openstacksdk#egg=openstacksdk"
pip freeze
ostestr {posargs}