Merge "Move session loading into loading module"

This commit is contained in:
Jenkins 2015-08-24 18:51:22 +00:00 committed by Gerrit Code Review
commit 505af7a61b
3 changed files with 237 additions and 208 deletions

View File

@ -0,0 +1,229 @@
# 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.
import argparse
import os
try:
from oslo_config import cfg
except ImportError:
cfg = None
from keystoneauth1 import _utils as utils
from keystoneauth1.loading import base
from keystoneauth1 import session
def _positive_non_zero_float(argument_value):
if argument_value is None:
return None
try:
value = float(argument_value)
except ValueError:
msg = "%s must be a float" % argument_value
raise argparse.ArgumentTypeError(msg)
if value <= 0:
msg = "%s must be greater than 0" % argument_value
raise argparse.ArgumentTypeError(msg)
return value
class Session(base.BaseLoader):
@property
def plugin_class(self):
return session.Session
def get_options(self):
return []
@utils.positional(1)
def load_from_options(self,
insecure=False,
verify=None,
cacert=None,
cert=None,
key=None,
**kwargs):
"""Create a session with individual certificate parameters.
Some parameters used to create a session don't lend themselves to be
loaded from config/CLI etc. Create a session by converting those
parameters into session __init__ parameters.
"""
if verify is None:
if insecure:
verify = False
else:
verify = cacert or True
if cert and key:
# passing cert and key together is deprecated in favour of the
# requests lib form of having the cert and key as a tuple
cert = (cert, key)
return super(Session, self).load_from_options(verify=verify,
cert=cert,
**kwargs)
def register_argparse_arguments(self, parser):
parser.add_argument('--insecure',
default=False,
action='store_true',
help='Explicitly allow client to perform '
'"insecure" TLS (https) requests. The '
'server\'s certificate will not be verified '
'against any certificate authorities. This '
'option should be used with caution.')
parser.add_argument('--os-cacert',
metavar='<ca-certificate>',
default=os.environ.get('OS_CACERT'),
help='Specify a CA bundle file to use in '
'verifying a TLS (https) server certificate. '
'Defaults to env[OS_CACERT].')
parser.add_argument('--os-cert',
metavar='<certificate>',
default=os.environ.get('OS_CERT'),
help='Defaults to env[OS_CERT].')
parser.add_argument('--os-key',
metavar='<key>',
default=os.environ.get('OS_KEY'),
help='Defaults to env[OS_KEY].')
parser.add_argument('--timeout',
default=600,
type=_positive_non_zero_float,
metavar='<seconds>',
help='Set request timeout (in seconds).')
def load_from_argparse_arguments(self, namespace, **kwargs):
kwargs['insecure'] = namespace.insecure
kwargs['cacert'] = namespace.os_cacert
kwargs['cert'] = namespace.os_cert
kwargs['key'] = namespace.os_key
kwargs['timeout'] = namespace.timeout
return super(Session, self).load_from_argparse_arguments(namespace,
**kwargs)
def _get_conf_options(self, deprecated_opts=None):
"""Get the oslo_config options that are needed for a
:py:class:`.Session`.
These may be useful without being registered for config file generation
or to manipulate the options before registering them yourself.
The options that are set are:
:cafile: The certificate authority filename.
:certfile: The client certificate file to present.
:keyfile: The key for the client certificate.
:insecure: Whether to ignore SSL verification.
:timeout: The max time to wait for HTTP connections.
:param dict deprecated_opts: Deprecated options that should be included
in the definition of new options. This should be a dict from the
name of the new option to a list of oslo.DeprecatedOpts that
correspond to the new option. (optional)
For example, to support the ``ca_file`` option pointing to the new
``cafile`` option name::
old_opt = oslo_cfg.DeprecatedOpt('ca_file', 'old_group')
deprecated_opts={'cafile': [old_opt]}
:returns: A list of oslo_config options.
"""
if not cfg:
raise ImportError("oslo.config is not an automatic dependency of "
"keystoneauth. If you wish to use oslo.config "
"you need to import it into your application's "
"requirements file. ")
if deprecated_opts is None:
deprecated_opts = {}
return [cfg.StrOpt('cafile',
deprecated_opts=deprecated_opts.get('cafile'),
help='PEM encoded Certificate Authority to use '
'when verifying HTTPs connections.'),
cfg.StrOpt('certfile',
deprecated_opts=deprecated_opts.get('certfile'),
help='PEM encoded client certificate cert file'),
cfg.StrOpt('keyfile',
deprecated_opts=deprecated_opts.get('keyfile'),
help='PEM encoded client certificate key file'),
cfg.BoolOpt('insecure',
default=False,
deprecated_opts=deprecated_opts.get('insecure'),
help='Verify HTTPS connections.'),
cfg.IntOpt('timeout',
deprecated_opts=deprecated_opts.get('timeout'),
help='Timeout value for http requests'),
]
def register_conf_options(self, conf, group, deprecated_opts=None):
"""Register the oslo_config options that are needed for a session.
The options that are set are:
:cafile: The certificate authority filename.
:certfile: The client certificate file to present.
:keyfile: The key for the client certificate.
:insecure: Whether to ignore SSL verification.
:timeout: The max time to wait for HTTP connections.
:param oslo_config.Cfg conf: config object to register with.
:param string group: The ini group to register options in.
:param dict deprecated_opts: Deprecated options that should be included
in the definition of new options. This should be a dict from the
name of the new option to a list of oslo.DeprecatedOpts that
correspond to the new option. (optional)
For example, to support the ``ca_file`` option pointing to the new
``cafile`` option name::
old_opt = oslo_cfg.DeprecatedOpt('ca_file', 'old_group')
deprecated_opts={'cafile': [old_opt]}
:returns: The list of options that was registered.
"""
opts = self._get_conf_options(deprecated_opts=deprecated_opts)
conf.register_group(cfg.OptGroup(group))
conf.register_opts(opts, group=group)
return opts
def load_from_conf_options(self, conf, group, **kwargs):
"""Create a session object from an oslo_config object.
The options must have been previously registered with
register_conf_options.
:param oslo_config.Cfg conf: config object to register with.
:param string group: The ini group to register options in.
:param dict kwargs: Additional parameters to pass to session
construction.
:returns: A new session object.
:rtype: :py:class:`.Session`
"""
c = conf[group]
kwargs['insecure'] = c.insecure
kwargs['cacert'] = c.cafile
kwargs['cert'] = c.certfile
kwargs['key'] = c.keyfile
kwargs['timeout'] = c.timeout
return super(Session, self).load_from_conf_options(conf,
group,
**kwargs)

View File

@ -10,18 +10,15 @@
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import datetime
import functools
import hashlib
import json
import logging
import os
import socket
import time
import uuid
from oslo_config import cfg
import requests
import six
from six.moves import urllib
@ -44,20 +41,6 @@ USER_AGENT = 'keystoneauth1'
_logger = logging.getLogger(__name__)
def _positive_non_zero_float(argument_value):
if argument_value is None:
return None
try:
value = float(argument_value)
except ValueError:
msg = "%s must be a float" % argument_value
raise argparse.ArgumentTypeError(msg)
if value <= 0:
msg = "%s must be greater than 0" % argument_value
raise argparse.ArgumentTypeError(msg)
return value
class _JSONEncoder(json.JSONEncoder):
def default(self, o):
@ -550,28 +533,6 @@ class Session(object):
"""
return self.request(url, 'PATCH', **kwargs)
@classmethod
def _make(cls, insecure=False, verify=None, cacert=None, cert=None,
key=None, **kwargs):
"""Create a session with individual certificate parameters.
Some parameters used to create a session don't lend themselves to be
loaded from config/CLI etc. Create a session by converting those
parameters into session __init__ parameters.
"""
if verify is None:
if insecure:
verify = False
else:
verify = cacert or True
if cert and key:
# passing cert and key together is deprecated in favour of the
# requests lib form of having the cert and key as a tuple
cert = (cert, key)
return cls(verify=verify, cert=cert, **kwargs)
def _auth_required(self, auth, msg):
if not auth:
auth = self.auth
@ -735,169 +696,6 @@ class Session(object):
auth = self._auth_required(auth, 'get project_id')
return auth.get_project_id(self)
@utils.positional.classmethod()
def get_conf_options(cls, deprecated_opts=None):
"""Get the oslo_config options that are needed for a
:py:class:`.Session`.
These may be useful without being registered for config file generation
or to manipulate the options before registering them yourself.
The options that are set are:
:cafile: The certificate authority filename.
:certfile: The client certificate file to present.
:keyfile: The key for the client certificate.
:insecure: Whether to ignore SSL verification.
:timeout: The max time to wait for HTTP connections.
:param dict deprecated_opts: Deprecated options that should be included
in the definition of new options. This should be a dict from the
name of the new option to a list of oslo.DeprecatedOpts that
correspond to the new option. (optional)
For example, to support the ``ca_file`` option pointing to the new
``cafile`` option name::
old_opt = oslo_cfg.DeprecatedOpt('ca_file', 'old_group')
deprecated_opts={'cafile': [old_opt]}
:returns: A list of oslo_config options.
"""
if deprecated_opts is None:
deprecated_opts = {}
return [cfg.StrOpt('cafile',
deprecated_opts=deprecated_opts.get('cafile'),
help='PEM encoded Certificate Authority to use '
'when verifying HTTPs connections.'),
cfg.StrOpt('certfile',
deprecated_opts=deprecated_opts.get('certfile'),
help='PEM encoded client certificate cert file'),
cfg.StrOpt('keyfile',
deprecated_opts=deprecated_opts.get('keyfile'),
help='PEM encoded client certificate key file'),
cfg.BoolOpt('insecure',
default=False,
deprecated_opts=deprecated_opts.get('insecure'),
help='Verify HTTPS connections.'),
cfg.IntOpt('timeout',
deprecated_opts=deprecated_opts.get('timeout'),
help='Timeout value for http requests'),
]
@utils.positional.classmethod()
def register_conf_options(cls, conf, group, deprecated_opts=None):
"""Register the oslo_config options that are needed for a session.
The options that are set are:
:cafile: The certificate authority filename.
:certfile: The client certificate file to present.
:keyfile: The key for the client certificate.
:insecure: Whether to ignore SSL verification.
:timeout: The max time to wait for HTTP connections.
:param oslo_config.Cfg conf: config object to register with.
:param string group: The ini group to register options in.
:param dict deprecated_opts: Deprecated options that should be included
in the definition of new options. This should be a dict from the
name of the new option to a list of oslo.DeprecatedOpts that
correspond to the new option. (optional)
For example, to support the ``ca_file`` option pointing to the new
``cafile`` option name::
old_opt = oslo_cfg.DeprecatedOpt('ca_file', 'old_group')
deprecated_opts={'cafile': [old_opt]}
:returns: The list of options that was registered.
"""
opts = cls.get_conf_options(deprecated_opts=deprecated_opts)
conf.register_group(cfg.OptGroup(group))
conf.register_opts(opts, group=group)
return opts
@classmethod
def load_from_conf_options(cls, conf, group, **kwargs):
"""Create a session object from an oslo_config object.
The options must have been previously registered with
register_conf_options.
:param oslo_config.Cfg conf: config object to register with.
:param string group: The ini group to register options in.
:param dict kwargs: Additional parameters to pass to session
construction.
:returns: A new session object.
:rtype: :py:class:`.Session`
"""
c = conf[group]
kwargs['insecure'] = c.insecure
kwargs['cacert'] = c.cafile
kwargs['cert'] = c.certfile
kwargs['key'] = c.keyfile
kwargs['timeout'] = c.timeout
return cls._make(**kwargs)
@staticmethod
def register_cli_options(parser):
"""Register the argparse arguments that are needed for a session.
:param argparse.ArgumentParser parser: parser to add to.
"""
parser.add_argument('--insecure',
default=False,
action='store_true',
help='Explicitly allow client to perform '
'"insecure" TLS (https) requests. The '
'server\'s certificate will not be verified '
'against any certificate authorities. This '
'option should be used with caution.')
parser.add_argument('--os-cacert',
metavar='<ca-certificate>',
default=os.environ.get('OS_CACERT'),
help='Specify a CA bundle file to use in '
'verifying a TLS (https) server certificate. '
'Defaults to env[OS_CACERT].')
parser.add_argument('--os-cert',
metavar='<certificate>',
default=os.environ.get('OS_CERT'),
help='Defaults to env[OS_CERT].')
parser.add_argument('--os-key',
metavar='<key>',
default=os.environ.get('OS_KEY'),
help='Defaults to env[OS_KEY].')
parser.add_argument('--timeout',
default=600,
type=_positive_non_zero_float,
metavar='<seconds>',
help='Set request timeout (in seconds).')
@classmethod
def load_from_cli_options(cls, args, **kwargs):
"""Create a :py:class:`.Session` object from CLI arguments.
The CLI arguments must have been registered with
:py:meth:`.register_cli_options`.
:param Namespace args: result of parsed arguments.
:returns: A new session object.
:rtype: :py:class:`.Session`
"""
kwargs['insecure'] = args.insecure
kwargs['cacert'] = args.os_cacert
kwargs['cert'] = args.os_cert
kwargs['key'] = args.os_key
kwargs['timeout'] = args.timeout
return cls._make(**kwargs)
class TCPKeepAliveAdapter(requests.adapters.HTTPAdapter):
"""The custom adapter used to set TCP Keep-Alive on all connections.

View File

@ -25,6 +25,7 @@ from testtools import matchers
from keystoneauth1 import adapter
from keystoneauth1 import exceptions
from keystoneauth1.loading import session as session_loader
from keystoneauth1 import plugin
from keystoneauth1 import session as client_session
from keystoneauth1.tests.unit import utils
@ -827,15 +828,15 @@ class ConfLoadingTests(utils.TestCase):
super(ConfLoadingTests, self).setUp()
self.conf_fixture = self.useFixture(config.Config())
client_session.Session.register_conf_options(self.conf_fixture.conf,
self.GROUP)
session_loader.Session().register_conf_options(self.conf_fixture.conf,
self.GROUP)
def config(self, **kwargs):
kwargs['group'] = self.GROUP
self.conf_fixture.config(**kwargs)
def get_session(self, **kwargs):
return client_session.Session.load_from_conf_options(
return session_loader.Session().load_from_conf_options(
self.conf_fixture.conf,
self.GROUP,
**kwargs)
@ -871,7 +872,7 @@ class ConfLoadingTests(utils.TestCase):
opt_names = ['cafile', 'certfile', 'keyfile', 'insecure', 'timeout']
depr = dict([(n, [new_deprecated()]) for n in opt_names])
opts = client_session.Session.get_conf_options(deprecated_opts=depr)
opts = session_loader.Session()._get_conf_options(deprecated_opts=depr)
self.assertThat(opt_names, matchers.HasLength(len(opts)))
for opt in opts:
@ -884,11 +885,12 @@ class CliLoadingTests(utils.TestCase):
super(CliLoadingTests, self).setUp()
self.parser = argparse.ArgumentParser()
client_session.Session.register_cli_options(self.parser)
session_loader.Session().register_argparse_arguments(self.parser)
def get_session(self, val, **kwargs):
args = self.parser.parse_args(val.split())
return client_session.Session.load_from_cli_options(args, **kwargs)
return session_loader.Session().load_from_argparse_arguments(args,
**kwargs)
def test_insecure_timeout(self):
s = self.get_session('--insecure --timeout 5.5')