Merge "Refactor os-client-config usage in from_config"

This commit is contained in:
Jenkins 2015-11-20 00:07:56 +00:00 committed by Gerrit Code Review
commit dadb1c0f3c
6 changed files with 122 additions and 36 deletions

View File

@ -31,8 +31,13 @@ locations:
* ~/.config/openstack
* /etc/openstack
call :py:func:`~openstack.connection.from_config` with an object that has
the name of the cloud configuration to use.
call :py:func:`~openstack.connection.from_config`. The ``from_config``
function takes three optional arguments, such as **cloud_name**,
which allows you to specify one set of cloud credentials in your
``clouds.yaml`` file. Additionally, **cloud_config** and **options**
allow you to pass in configiration data you may have already received
from ``os-client-config``, as well as additional options that the
``os-client-config`` library may need.
.. literalinclude:: ../examples/connect.py
:pyobject: Opts
@ -51,16 +56,8 @@ absolute path of a file.::
export OS_CLIENT_CONFIG_FILE=/path/to/my/config/my-clouds.yaml
and call :py:func:`~openstack.connection.from_config` with an object that has
the name of the cloud configuration to use.
.. literalinclude:: ../examples/connect.py
:pyobject: Opts
.. literalinclude:: ../examples/connect.py
:pyobject: create_connection_from_config
.. note:: To enable logging, set ``debug=True`` in the ``Opts`` object.
and call :py:func:`~openstack.connection.from_config` with the **cloud_name**
of the cloud configuration to use, .
.. Create Connection From Environment Variables
--------------------------------------------

View File

@ -35,8 +35,8 @@ TEST_CLOUD = os.getenv('OS_TEST_CLOUD', 'test_cloud')
class Opts(object):
def __init__(self, test_cloud='test_cloud', debug=False):
self.cloud = test_cloud
def __init__(self, cloud_name='test_cloud', debug=False):
self.cloud = cloud_name
self.debug = debug
@ -46,7 +46,7 @@ def _get_resource_value(resource_key, default):
except KeyError:
return default
opts = Opts(test_cloud=TEST_CLOUD)
opts = Opts(cloud_name=TEST_CLOUD)
occ = os_client_config.OpenStackConfig()
cloud = occ.get_one_cloud(opts.cloud, argparse=opts)
@ -62,7 +62,7 @@ PRIVATE_KEYPAIR_FILE = _get_resource_value('private_keypair_file',
def create_connection_from_config():
return connection.from_config(opts)
return connection.from_config(cloud_config=cloud, options=opts)
def create_connection(auth_url, region, project_name, username, password):

View File

@ -72,17 +72,27 @@ from openstack import utils
_logger = logging.getLogger(__name__)
def from_config(opts):
"""Create a connection from a configuration.
def from_config(cloud_name=None, cloud_config=None, options=None):
"""Create a Connection using os-client-config
Create a :class:`~openstack.connection.Connection` from a configuration
similar to a os-client-config CloudConfig.
:param opts: An options class like the :class:`~argparse.Namespace` class.
:param str cloud_name: Use the `cloud_name` configuration details when
creating the Connection instance.
:param cloud_config: An instance of
`os_client_config.config.OpenStackConfig`
as returned from the os-client-config library.
If no `config` is provided,
`os_client_config.OpenStackConfig` will be called,
and the provided `cloud_name` will be used in
determining which cloud's configuration details
will be used in creation of the
`Connection` instance.
:param options: An argparse Namespace object; allows direct passing
in of argparse options to be added to the cloud config.
This value is passed to the `argparse` argument of
`os_client_config.config.OpenStackConfig.get_one_cloud`.
:rtype: :class:`~openstack.connection.Connection`
"""
# TODO(thowe): I proposed that service name defaults to None in OCC
defaults = {}
prof = profile.Profile()
@ -92,17 +102,15 @@ def from_config(opts):
# TODO(thowe): default is 2 which turns into v2 which doesn't work
# this stuff needs to be fixed where we keep version and path separated.
defaults['network_api_version'] = 'v2.0'
# Get the cloud_config
occ = os_client_config.OpenStackConfig(override_defaults=defaults)
cloud_config = occ.get_one_cloud(opts.cloud, argparse=opts)
if cloud_config is None:
occ = os_client_config.OpenStackConfig(override_defaults=defaults)
cloud_config = occ.get_one_cloud(cloud=cloud_name, argparse=options)
if cloud_config.debug:
utils.enable_logging(True, stream=sys.stdout)
# TODO(mordred) we need to add service_type setting to openstacksdk.
# Some clouds have type overridden as well as name.
prof = profile.Profile()
services = [service.service_type for service in prof.get_services()]
for service in cloud_config.get_services():
if service in services:

View File

@ -19,6 +19,9 @@ from openstack import exceptions
from openstack import service_filter
CLOUD_NAME = os.getenv('OS_CLOUD', 'test_cloud')
def requires_service(**kwargs):
"""Check whether a service is available for this test
@ -50,14 +53,10 @@ def requires_service(**kwargs):
class BaseFunctionalTest(unittest.TestCase):
class Opts(object):
def __init__(self):
self.cloud = os.getenv('OS_CLOUD', 'test_cloud')
@classmethod
def setUpClass(cls):
opts = cls.Opts()
cls.conn = connection.from_config(opts)
cls.conn = connection.from_config(cloud_name=CLOUD_NAME)
@classmethod
def assertIs(cls, expected, actual):

View File

@ -18,15 +18,15 @@ TEST_IMAGE_NAME = 'Test Image'
class TestImage(base.BaseFunctionalTest):
class ImageOpts(base.BaseFunctionalTest.Opts):
class ImageOpts(object):
def __init__(self):
super(TestImage.ImageOpts, self).__init__()
self.image_api_version = '2'
@classmethod
def setUpClass(cls):
opts = cls.ImageOpts()
cls.conn = connection.from_config(opts)
cls.conn = connection.from_config(cloud_name=base.CLOUD_NAME,
options=opts)
cls.img = cls.conn.image.upload_image(
name=TEST_IMAGE_NAME,

View File

@ -10,7 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import tempfile
import mock
import os_client_config
from openstack.auth.identity import v2
from openstack import connection
@ -19,6 +23,24 @@ from openstack.tests.unit import base
from openstack import transport
CONFIG_AUTH_URL = "http://127.0.0.1:5000/v2.0"
CONFIG_USERNAME = "BozoTheClown"
CONFIG_PASSWORD = "TopSecret"
CONFIG_PROJECT = "TheGrandPrizeGame"
CLOUD_CONFIG = """
clouds:
sample:
region_name: RegionOne
auth:
auth_url: {auth_url}
username: {username}
password: {password}
project_name: {project}
""".format(auth_url=CONFIG_AUTH_URL, username=CONFIG_USERNAME,
password=CONFIG_PASSWORD, project=CONFIG_PROJECT)
class TestConnection(base.TestCase):
def setUp(self):
super(TestConnection, self).setUp()
@ -85,3 +107,63 @@ class TestConnection(base.TestCase):
conn = connection.Connection(authenticator=self.auth,
user_agent=user_agent)
self.assertTrue(conn.transport._user_agent.startswith(user_agent))
def _prepare_test_config(self):
# Create a temporary directory where our test config will live
# and insert it into the search path via OS_CLIENT_CONFIG_FILE.
# NOTE: If OCC stops popping OS_C_C_F off of os.environ, this
# will need to change to respect that. It currently works between
# tests because the environment variable is always wiped by OCC itself.
config_dir = tempfile.mkdtemp()
config_path = os.path.join(config_dir, "clouds.yaml")
with open(config_path, "w") as conf:
conf.write(CLOUD_CONFIG)
os.environ["OS_CLIENT_CONFIG_FILE"] = config_path
def test_from_config_given_data(self):
self._prepare_test_config()
data = os_client_config.OpenStackConfig().get_one_cloud("sample")
sot = connection.from_config(cloud_config=data)
self.assertEqual(CONFIG_USERNAME,
sot.authenticator.auth_plugin.username)
self.assertEqual(CONFIG_PASSWORD,
sot.authenticator.auth_plugin.password)
self.assertEqual(CONFIG_AUTH_URL,
sot.authenticator.auth_plugin.auth_url)
self.assertEqual(CONFIG_PROJECT,
sot.authenticator.auth_plugin.tenant_name)
def test_from_config_given_name(self):
self._prepare_test_config()
sot = connection.from_config(cloud_name="sample")
self.assertEqual(CONFIG_USERNAME,
sot.authenticator.auth_plugin.username)
self.assertEqual(CONFIG_PASSWORD,
sot.authenticator.auth_plugin.password)
self.assertEqual(CONFIG_AUTH_URL,
sot.authenticator.auth_plugin.auth_url)
self.assertEqual(CONFIG_PROJECT,
sot.authenticator.auth_plugin.tenant_name)
def test_from_config_given_options(self):
self._prepare_test_config()
version = "100"
class Opts(object):
compute_api_version = version
sot = connection.from_config(cloud_name="sample", options=Opts)
pref = sot.session.profile.get_preference("compute")
# NOTE: Along the way, the `v` prefix gets added so we can build
# up URLs with it.
self.assertEqual("v" + version, pref.version)