Add os-client-config support
This patch adds os-client-config[1] support to python-tempestconf. Further documentation on usage has been added to the included release note. In addition, all args from os-client-config are supported. [1] https://github.com/openstack/os-client-config Co-Authored-By: Martin Kopec <mkopec@redhat.com> Closes Issue: #2 Change-Id: I79e7ffb42071abcf1744f21265660fd5cfe0c6a0
This commit is contained in:
		
				
					committed by
					
						
						Luigi Toscano
					
				
			
			
				
	
			
			
			
						parent
						
							3deb8061aa
						
					
				
				
					commit
					723f92d022
				
			
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,7 @@
 | 
			
		||||
*.py[cod]
 | 
			
		||||
*.pyc
 | 
			
		||||
cirros*
 | 
			
		||||
tempest.conf
 | 
			
		||||
 | 
			
		||||
# Packages
 | 
			
		||||
*.egg*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								README.rst
									
									
									
									
									
								
							@@ -83,3 +83,27 @@ RPM Installation (RDO)
 | 
			
		||||
   ``config_tempest.py`` script and it **accepts the same parameters.**
 | 
			
		||||
   More about new features can be found
 | 
			
		||||
   `here <https://www.rdoproject.org/blog/2017/02/testing-rdo-with-tempest-new-features-in-ocata/>`__
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
os-client-config support
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
python-tempestconf supports `os-client-config <https://github.com/openstack/os-client-config>`__
 | 
			
		||||
so instead of sourcing openstackrc files you can use clouds.yml files. Location where
 | 
			
		||||
these files should be stored and syntax which is used to specify cloud.yaml files
 | 
			
		||||
can be found `here <https://github.com/openstack/os-client-config#config-files>`__
 | 
			
		||||
 | 
			
		||||
In case of git usage:
 | 
			
		||||
 | 
			
		||||
.. code-block:: shell-session
 | 
			
		||||
 | 
			
		||||
    (py27) $ python config_tempest/config_tempest.py --debug --create --os-cloud <name of cloud>
 | 
			
		||||
 | 
			
		||||
In case of RPM:
 | 
			
		||||
 | 
			
		||||
.. code-block:: shell-session
 | 
			
		||||
 | 
			
		||||
    $ tempest init testingdir
 | 
			
		||||
    $ cd testingdir
 | 
			
		||||
    $ discover-tempest-config --debug --create --os-cloud <name of cloud>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,8 @@ import sys
 | 
			
		||||
import tempest.config
 | 
			
		||||
import urllib2
 | 
			
		||||
 | 
			
		||||
import os_client_config
 | 
			
		||||
from oslo_config import cfg
 | 
			
		||||
from tempest.common import identity
 | 
			
		||||
from tempest.lib import auth
 | 
			
		||||
from tempest.lib import exceptions
 | 
			
		||||
@@ -131,7 +133,11 @@ def main():
 | 
			
		||||
                conf.set(section, key, value, priority=True)
 | 
			
		||||
    for section, key, value in args.overrides:
 | 
			
		||||
        conf.set(section, key, value, priority=True)
 | 
			
		||||
    uri = conf.get("identity", "uri")
 | 
			
		||||
    if conf.has_option("identity", "uri"):
 | 
			
		||||
        uri = conf.get("identity", "uri")
 | 
			
		||||
    else:
 | 
			
		||||
        uri = args.config['auth'].get('auth_url')
 | 
			
		||||
        conf.set("identity", "uri", uri)
 | 
			
		||||
    api_version = 2
 | 
			
		||||
    v3_only = False
 | 
			
		||||
    if "v3" in uri and v3_only:
 | 
			
		||||
@@ -149,7 +155,7 @@ def main():
 | 
			
		||||
        conf.set("auth", "allow_tenant_isolation", "False")
 | 
			
		||||
    if args.use_test_accounts:
 | 
			
		||||
        conf.set("auth", "allow_tenant_isolation", "True")
 | 
			
		||||
    clients = ClientManager(conf, not args.non_admin)
 | 
			
		||||
    clients = ClientManager(conf, not args.non_admin, args)
 | 
			
		||||
    swift_discover = conf.get_defaulted('object-storage-feature-enabled',
 | 
			
		||||
                                        'discoverability')
 | 
			
		||||
    services = api_discovery.discover(
 | 
			
		||||
@@ -189,7 +195,9 @@ def main():
 | 
			
		||||
 | 
			
		||||
def parse_arguments():
 | 
			
		||||
    # TODO(tkammer): add mutual exclusion groups
 | 
			
		||||
    cloud_config = os_client_config.OpenStackConfig()
 | 
			
		||||
    parser = argparse.ArgumentParser(__doc__)
 | 
			
		||||
    cloud_config.register_argparse_arguments(parser, sys.argv)
 | 
			
		||||
    parser.add_argument('--create', action='store_true', default=False,
 | 
			
		||||
                        help='create default tempest resources')
 | 
			
		||||
    parser.add_argument('--out', default="etc/tempest.conf",
 | 
			
		||||
@@ -235,14 +243,14 @@ def parse_arguments():
 | 
			
		||||
                                --remove feature-enabled.api_ext=http,https""")
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    if args.create and args.non_admin:
 | 
			
		||||
        raise Exception("Options '--create' and '--non-admin' cannot be used"
 | 
			
		||||
                        " together, since creating" " resources requires"
 | 
			
		||||
                        " admin rights")
 | 
			
		||||
    args.overrides = parse_overrides(args.overrides)
 | 
			
		||||
    args.remove = parse_values_to_remove(args.remove)
 | 
			
		||||
    return args
 | 
			
		||||
    cloud = cloud_config.get_one_cloud(argparse=args)
 | 
			
		||||
    return cloud
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_values_to_remove(options):
 | 
			
		||||
@@ -343,16 +351,40 @@ class ClientManager(object):
 | 
			
		||||
        else:
 | 
			
		||||
            return "v2"
 | 
			
		||||
 | 
			
		||||
    def __init__(self, conf, admin):
 | 
			
		||||
    def __init__(self, conf, admin, args):
 | 
			
		||||
        self.identity_version = self.get_identity_version(conf)
 | 
			
		||||
        username = None
 | 
			
		||||
        password = None
 | 
			
		||||
        tenant_name = None
 | 
			
		||||
        os_client_creds = args.config.get('auth')
 | 
			
		||||
        if os_client_creds:
 | 
			
		||||
            username = os_client_creds.get('username')
 | 
			
		||||
            password = os_client_creds.get('password')
 | 
			
		||||
            tenant_name = os_client_creds.get('project_name')
 | 
			
		||||
        if admin:
 | 
			
		||||
            username = conf.get_defaulted('identity', 'admin_username')
 | 
			
		||||
            password = conf.get_defaulted('identity', 'admin_password')
 | 
			
		||||
            tenant_name = conf.get_defaulted('identity', 'admin_tenant_name')
 | 
			
		||||
            try:
 | 
			
		||||
                username = conf.get_defaulted('identity', 'admin_username')
 | 
			
		||||
                password = conf.get_defaulted('identity', 'admin_password')
 | 
			
		||||
                tenant_name = conf.get_defaulted('identity',
 | 
			
		||||
                                                 'admin_tenant_name')
 | 
			
		||||
            except cfg.NoSuchOptError:
 | 
			
		||||
                LOG.warning(
 | 
			
		||||
                    'Could not load some identity admin options from %s',
 | 
			
		||||
                    DEFAULTS_FILE)
 | 
			
		||||
        else:
 | 
			
		||||
            username = conf.get_defaulted('identity', 'username')
 | 
			
		||||
            password = conf.get_defaulted('identity', 'password')
 | 
			
		||||
            tenant_name = conf.get_defaulted('identity', 'tenant_name')
 | 
			
		||||
            try:
 | 
			
		||||
                # override values only when were set in CLI
 | 
			
		||||
                if conf.has_option('identity', 'username'):
 | 
			
		||||
                    username = conf.get_defaulted('identity', 'username')
 | 
			
		||||
                if conf.has_option('identity', 'password'):
 | 
			
		||||
                    password = conf.get_defaulted('identity', 'password')
 | 
			
		||||
                if conf.has_option('identity', 'tenant_name'):
 | 
			
		||||
                    tenant_name = conf.get_defaulted('identity', 'tenant_name')
 | 
			
		||||
 | 
			
		||||
            except cfg.NoSuchOptError:
 | 
			
		||||
                LOG.warning(
 | 
			
		||||
                    'Could not load some identity options from %s',
 | 
			
		||||
                    DEFAULTS_FILE)
 | 
			
		||||
 | 
			
		||||
        self.identity_region = conf.get_defaulted('identity', 'region')
 | 
			
		||||
        default_params = {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ from config_tempest import api_discovery as api
 | 
			
		||||
from config_tempest import config_tempest as tool
 | 
			
		||||
from fixtures import MonkeyPatch
 | 
			
		||||
import json
 | 
			
		||||
from mock import Mock
 | 
			
		||||
import mock
 | 
			
		||||
from oslotest import base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -44,9 +44,13 @@ class BaseConfigTempestTest(base.BaseTestCase):
 | 
			
		||||
        conf.set("auth", "allow_tenant_isolation", "False")
 | 
			
		||||
        return conf
 | 
			
		||||
 | 
			
		||||
    def _get_clients(self, conf, admin=False):
 | 
			
		||||
    @mock.patch('os_client_config.cloud_config.CloudConfig')
 | 
			
		||||
    def _get_clients(self, conf, mock_args, admin=False):
 | 
			
		||||
        """Returns ClientManager instance"""
 | 
			
		||||
        return tool.ClientManager(conf, admin=admin)
 | 
			
		||||
        mock_function = mock.Mock(return_value=False)
 | 
			
		||||
        func2mock = 'os_client_config.cloud_config.CloudConfig.config.get'
 | 
			
		||||
        self.useFixture(MonkeyPatch(func2mock, mock_function))
 | 
			
		||||
        return tool.ClientManager(conf, admin=admin, args=mock_args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseServiceTest(base.BaseTestCase):
 | 
			
		||||
@@ -176,7 +180,7 @@ class BaseServiceTest(base.BaseTestCase):
 | 
			
		||||
    def _fake_service_do_get_method(self, fake_data):
 | 
			
		||||
        function2mock = 'config_tempest.api_discovery.Service.do_get'
 | 
			
		||||
        do_get_output = json.dumps(fake_data)
 | 
			
		||||
        mocked_do_get = Mock()
 | 
			
		||||
        mocked_do_get = mock.Mock()
 | 
			
		||||
        mocked_do_get.return_value = do_get_output
 | 
			
		||||
        self.useFixture(MonkeyPatch(function2mock, mocked_do_get))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ class TestClientManager(BaseConfigTempestTest):
 | 
			
		||||
        mock_function = mock.Mock(return_value={"id": "my_fake_id"})
 | 
			
		||||
        func2mock = 'config_tempest.config_tempest.identity.get_tenant_by_name'
 | 
			
		||||
        self.useFixture(MonkeyPatch(func2mock, mock_function))
 | 
			
		||||
        tool.ClientManager(self.conf, admin=True)
 | 
			
		||||
        self._get_clients(self.conf, admin=True)
 | 
			
		||||
        # check if admin credentials were set
 | 
			
		||||
        admin_tenant = self.conf.get("identity", "admin_tenant_name")
 | 
			
		||||
        admin_password = self.conf.get("identity", "admin_password")
 | 
			
		||||
@@ -114,6 +114,87 @@ class TestClientManager(BaseConfigTempestTest):
 | 
			
		||||
        self.assertEqual(admin_tenant_id, "my_fake_id")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestOsClientConfigSupport(BaseConfigTempestTest):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestOsClientConfigSupport, self).setUp()
 | 
			
		||||
        self.conf = self._get_conf("v2.0", "v3")
 | 
			
		||||
 | 
			
		||||
    def _check_credentials(self, manager, username, password, tenant_name):
 | 
			
		||||
        exp_user = manager.auth_provider.credentials._initial['username']
 | 
			
		||||
        exp_pass = manager.auth_provider.credentials._initial['password']
 | 
			
		||||
        exp_tenant = manager.auth_provider.credentials._initial['tenant_name']
 | 
			
		||||
        self.assertEqual(exp_user, username)
 | 
			
		||||
        self.assertEqual(exp_pass, password)
 | 
			
		||||
        self.assertEqual(exp_tenant, tenant_name)
 | 
			
		||||
 | 
			
		||||
    def _override_setup(self):
 | 
			
		||||
        cloud_args = {
 | 
			
		||||
            'username': 'cloud_user',
 | 
			
		||||
            'password': 'cloud_pass',
 | 
			
		||||
            'project_name': 'cloud_project'
 | 
			
		||||
        }
 | 
			
		||||
        mock_function = mock.Mock(return_value=cloud_args)
 | 
			
		||||
        func2mock = 'os_client_config.cloud_config.CloudConfig.config.get'
 | 
			
		||||
        self.useFixture(MonkeyPatch(func2mock, mock_function))
 | 
			
		||||
        mock_function = mock.Mock(return_value={"id": "my_fake_id"})
 | 
			
		||||
        func2mock = 'config_tempest.config_tempest.identity.get_tenant_by_name'
 | 
			
		||||
        self.useFixture(MonkeyPatch(func2mock, mock_function))
 | 
			
		||||
 | 
			
		||||
    @mock.patch('os_client_config.cloud_config.CloudConfig')
 | 
			
		||||
    def test_init_manager_client_config(self, mock_args):
 | 
			
		||||
        cloud_args = {
 | 
			
		||||
            'username': 'cloud_user',
 | 
			
		||||
            'password': 'cloud_pass',
 | 
			
		||||
            'project_name': 'cloud_project'
 | 
			
		||||
        }
 | 
			
		||||
        mock_function = mock.Mock(return_value=cloud_args)
 | 
			
		||||
        func2mock = 'os_client_config.cloud_config.CloudConfig.config.get'
 | 
			
		||||
        self.useFixture(MonkeyPatch(func2mock, mock_function))
 | 
			
		||||
        # remove options, pretend like they aren't set in CLI
 | 
			
		||||
        self.conf.remove_option('identity', 'username')
 | 
			
		||||
        self.conf.remove_option('identity', 'password')
 | 
			
		||||
        self.conf.remove_option('identity', 'tenant_name')
 | 
			
		||||
        manager = tool.ClientManager(self.conf, admin=False, args=mock_args)
 | 
			
		||||
        # check if cloud_args credentials were used
 | 
			
		||||
        self._check_credentials(manager,
 | 
			
		||||
                                cloud_args['username'],
 | 
			
		||||
                                cloud_args['password'],
 | 
			
		||||
                                cloud_args['project_name'])
 | 
			
		||||
 | 
			
		||||
    @mock.patch('os_client_config.cloud_config.CloudConfig')
 | 
			
		||||
    def test_init_manager_client_config_get_default(self, mock_args):
 | 
			
		||||
        mock_function = mock.Mock(return_value={})
 | 
			
		||||
        func2mock = 'os_client_config.cloud_config.CloudConfig.config.get'
 | 
			
		||||
        self.useFixture(MonkeyPatch(func2mock, mock_function))
 | 
			
		||||
        manager = tool.ClientManager(self.conf, admin=False, args=mock_args)
 | 
			
		||||
        # cloud_args is empty => check if default credentials were used
 | 
			
		||||
        self._check_credentials(manager,
 | 
			
		||||
                                self.conf.get('identity', 'username'),
 | 
			
		||||
                                self.conf.get('identity', 'password'),
 | 
			
		||||
                                self.conf.get('identity', 'tenant_name'))
 | 
			
		||||
 | 
			
		||||
    @mock.patch('os_client_config.cloud_config.CloudConfig')
 | 
			
		||||
    def test_init_manager_client_config_override(self, mock_args):
 | 
			
		||||
        self._override_setup()
 | 
			
		||||
        manager = tool.ClientManager(self.conf, admin=False, args=mock_args)
 | 
			
		||||
        # check if cloud_args credentials were overrided by the ones set in CLI
 | 
			
		||||
        self._check_credentials(manager,
 | 
			
		||||
                                self.conf.get('identity', 'username'),
 | 
			
		||||
                                self.conf.get('identity', 'password'),
 | 
			
		||||
                                self.conf.get('identity', 'tenant_name'))
 | 
			
		||||
 | 
			
		||||
    @mock.patch('os_client_config.cloud_config.CloudConfig')
 | 
			
		||||
    def test_init_manager_client_config_admin_override(self, mock_args):
 | 
			
		||||
        self._override_setup()
 | 
			
		||||
        manager = tool.ClientManager(self.conf, admin=True, args=mock_args)
 | 
			
		||||
        # check if cloud_args credentials were overrided by admin ones
 | 
			
		||||
        self._check_credentials(manager,
 | 
			
		||||
                                self.conf.get('identity', 'admin_username'),
 | 
			
		||||
                                self.conf.get('identity', 'admin_password'),
 | 
			
		||||
                                self.conf.get('identity', 'admin_tenant_name'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestTempestConf(BaseConfigTempestTest):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestTempestConf, self).setUp()
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
---
 | 
			
		||||
features:
 | 
			
		||||
  - |
 | 
			
		||||
    Enable os-client-config support [1].
 | 
			
		||||
    The tempest config tool now is able to support os-client-config env vars
 | 
			
		||||
    and cloud.yaml support.
 | 
			
		||||
 | 
			
		||||
    [1] https://github.com/openstack/os-client-config
 | 
			
		||||
@@ -6,3 +6,5 @@ pbr>=1.8 # Apache-2.0
 | 
			
		||||
tempest>=14.0.0 # Apache-2.0
 | 
			
		||||
requests>=2.10.0,!=2.12.2 # Apache-2.0
 | 
			
		||||
os-testr>=0.8.0 # Apache-2.0
 | 
			
		||||
os-client-config>=1.26.0 # Apache-2.0
 | 
			
		||||
oslo_config>=3.23.0 # Apache-2.0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user