diff --git a/saharaclient/tests/integration/configs/config.py b/saharaclient/tests/integration/configs/config.py new file mode 100644 index 00000000..c2e782a3 --- /dev/null +++ b/saharaclient/tests/integration/configs/config.py @@ -0,0 +1,119 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 print_function + +import os +import sys + +from oslo.config import cfg + + +def singleton(cls): + instances = {} + + def get_instance(): + if cls not in instances: + instances[cls] = cls() + return instances[cls] + + return get_instance + +COMMON_CONFIG_GROUP = cfg.OptGroup(name='COMMON') +COMMON_CONFIG_OPTS = [ + cfg.StrOpt('OS_USERNAME', + default='admin', + help='Username for OpenStack.'), + cfg.StrOpt('OS_PASSWORD', + default='admin', + help='Password for OpenStack.'), + cfg.StrOpt('OS_TENANT_NAME', + default='admin', + help='Tenant name for OpenStack.'), + cfg.StrOpt('OS_AUTH_URL', + default='http://127.0.0.1:5000/v2.0', + help='URL for OpenStack.'), + cfg.StrOpt('OS_PROJECT_NAME', + default='admin', + help='Project name for OpenStack.'), + cfg.StrOpt('BYPASS_URL', + default='', + help='The BYPASS_URL value to pass to the cli'), + cfg.StrOpt('SWIFT_AUTH_VERSION', + default=2, + help='OpenStack auth version for Swift.') +] + +VANILLA_CONFIG_GROUP = cfg.OptGroup(name='VANILLA') +VANILLA_CONFIG_OPTS = [ + cfg.BoolOpt('SKIP_ALL_TESTS_FOR_PLUGIN', + default=False, + help='If this flag is True, then all tests for Vanilla plugin ' + 'will be skipped.') +] + +VANILLA2_CONFIG_GROUP = cfg.OptGroup(name='VANILLA2') +VANILLA2_CONFIG_OPTS = [ + cfg.BoolOpt('SKIP_ALL_TESTS_FOR_PLUGIN', + default=True, + help='If this flag is True, then all tests for Vanilla2 plugin' + ' will be skipped.') +] + +HDP_CONFIG_GROUP = cfg.OptGroup(name='HDP') +HDP_CONFIG_OPTS = [ + cfg.BoolOpt('SKIP_ALL_TESTS_FOR_PLUGIN', + default=True, + help='If this flag is True, then all tests for HDP plugin ' + 'will be skipped.') +] + + +def register_config(config, config_group, config_opts): + config.register_group(config_group) + config.register_opts(config_opts, config_group) + + +@singleton +class ITConfig: + def __init__(self): + config = 'itest.conf' + config_files = [] + config_path = '%s/saharaclient/tests/integration/configs/%s' + if not os.path.exists(config_path % (os.getcwd(), config)): + message = '\n**************************************************' \ + '\nINFO: Configuration file "%s" not found *\n' \ + '**************************************************' \ + % config + print(message, file=sys.stderr) + else: + config = os.path.join( + config_path % (os.getcwd(), config) + ) + config_files.append(config) + + register_config(cfg.CONF, COMMON_CONFIG_GROUP, COMMON_CONFIG_OPTS) + register_config(cfg.CONF, VANILLA_CONFIG_GROUP, VANILLA_CONFIG_OPTS) + register_config(cfg.CONF, VANILLA2_CONFIG_GROUP, VANILLA2_CONFIG_OPTS) + register_config(cfg.CONF, HDP_CONFIG_GROUP, HDP_CONFIG_OPTS) + + cfg.CONF( + [], project='Sahara_client_integration_tests', + default_config_files=config_files + ) + self.common_config = cfg.CONF.COMMON + self.vanilla_config = cfg.CONF.VANILLA + self.hdp_config = cfg.CONF.HDP + self.vanilla2_config = cfg.CONF.VANILLA2 diff --git a/saharaclient/tests/integration/configs/itest.conf.sample b/saharaclient/tests/integration/configs/itest.conf.sample new file mode 100644 index 00000000..123eb457 --- /dev/null +++ b/saharaclient/tests/integration/configs/itest.conf.sample @@ -0,0 +1,13 @@ +[COMMON] + +OS_USERNAME = 'admin' +OS_PASSWORD = 'admin' +OS_TENANT_NAME = 'admin' +OS_PROJECT_NAME = 'admin' +OS_AUTH_URL = 'http://127.0.0.1:5000/v2.0' + +[VANILLA] + +[VANILLA2] + +[HDP] diff --git a/saharaclient/tests/integration/configs/itest.conf.sample-full b/saharaclient/tests/integration/configs/itest.conf.sample-full new file mode 100644 index 00000000..d1b55895 --- /dev/null +++ b/saharaclient/tests/integration/configs/itest.conf.sample-full @@ -0,0 +1,34 @@ +[COMMON] + +# Username for OpenStack (string value) +#OS_USERNAME = 'admin' + +# Password for OpenStack (string value) +#OS_PASSWORD = 'admin' + +# Tenant name for OpenStack (string value) +#OS_TENANT_NAME = 'admin' + +# URL for OpenStack (string value) +#OS_AUTH_URL = 'http://127.0.0.1:5000/v2.0' + +# OpenStack auth version for Swift (string value) +#SWIFT_AUTH_VERSION = 2 + +# Project name for OpenStack (string value) +#OS_PROJECT_NAME = 'admin' + +# The BYPASS_URL value to pass to the cli (string value) +#BYPASS_URL = '' + +[VANILLA] + +#SKIP_ALL_TESTS_FOR_PLUGIN = False + +[VANILLA2] + +#SKIP_ALL_TESTS_FOR_PLUGIN = True + +[HDP] + +#SKIP_ALL_TESTS_FOR_PLUGIN = True diff --git a/saharaclient/tests/integration/tests/base.py b/saharaclient/tests/integration/tests/base.py new file mode 100644 index 00000000..afb392f9 --- /dev/null +++ b/saharaclient/tests/integration/tests/base.py @@ -0,0 +1,28 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 testtools + +import saharaclient.tests.integration.tests.clidriver as clidriver +import saharaclient.tests.integration.tests.utils as utils + + +class ITestBase(testtools.TestCase): + def setUp(self): + super(ITestBase, self).setUp() + + # The client is for readonly operations to check results + self.util = utils.Utils() + self.cli = clidriver.CLICommands() diff --git a/saharaclient/tests/integration/tests/clidriver.py b/saharaclient/tests/integration/tests/clidriver.py new file mode 100644 index 00000000..09108e1c --- /dev/null +++ b/saharaclient/tests/integration/tests/clidriver.py @@ -0,0 +1,193 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 logging +import shlex +import six +import subprocess + +from saharaclient.tests.integration.configs import config as cfg + +cfg = cfg.ITConfig() + +LOG = logging.getLogger(__name__) + + +# This is modeled after the client interface in tempest cli tests.2 +class CommandBase(object): + def sahara(self, action, flags='', params='', fail_ok=False): + return self.cmd_with_bypass('sahara', action, flags, params, fail_ok) + + def cmd_with_bypass(self, cmd, action, flags='', params='', fail_ok=False): + if cfg.common_config['BYPASS_URL']: + bypass = '--bypass-url %s' % cfg.common_config['BYPASS_URL'] + flags = bypass + ' ' + flags + return self.cmd_with_auth(cmd, action, flags, params, fail_ok) + + def cmd_with_auth(self, cmd, action, flags='', params='', fail_ok=False): + """Executes given command with auth attributes appended.""" + creds = ('--os-username %s --os-tenant-name %s --os-password %s ' + '--os-auth-url %s ' % + (cfg.common_config['OS_USERNAME'], + cfg.common_config['OS_TENANT_NAME'], + cfg.common_config['OS_PASSWORD'], + cfg.common_config['OS_AUTH_URL'])) + flags = creds + ' ' + flags + return self.cmd(cmd, action, flags, params, fail_ok) + + def cmd(self, cmd, action, flags='', params='', fail_ok=False, + merge_stderr=False): + """Executes specified command for the given action.""" + cmd = ' '.join([cmd, flags, action, params]) + LOG.info("running: '%s'" % cmd) + cmd_str = cmd + cmd = shlex.split(cmd) + result = '' + result_err = '' + try: + stdout = subprocess.PIPE + stderr = subprocess.STDOUT if merge_stderr else subprocess.PIPE + proc = subprocess.Popen( + cmd, stdout=stdout, stderr=stderr) + result, result_err = proc.communicate() + if not fail_ok and proc.returncode != 0: + raise CommandFailed(proc.returncode, + cmd, + result) + finally: + LOG.debug('output of %s:\n%s' % (cmd_str, result)) + if not merge_stderr and result_err: + LOG.debug('error output of %s:\n%s' % (cmd_str, result_err)) + return result + + +class CommandFailed(subprocess.CalledProcessError): + # adds output attribute for python2.6 + def __init__(self, returncode, cmd, output): + super(CommandFailed, self).__init__(returncode, cmd) + self.output = output + + +class CLICommands(CommandBase): + def register_image(self, image_id, username='', description=''): + params = '--id %s' % image_id + if username: + params += ' --username %s' % username + if description: + params += ' --description %s' % description + return self.sahara('image-register', params=params) + + def unregister_image(self, id): + params = '--id %s' % id + return self.sahara('image-unregister', params=params) + + def tag_image(self, id, tag): + params = '--id %s --tag %s' % (id, tag) + return self.sahara('image-add-tag', params=params) + + def node_group_template_create(self, filename): + params = '--json %s' % filename + return self.sahara('node-group-template-create', params=params) + + def node_group_template_delete(self, id): + params = '--id %s' % id + return self.sahara('node-group-template-delete', params=params) + + def cluster_template_create(self, filename): + params = '--json %s' % filename + return self.sahara('cluster-template-create', params=params) + + def cluster_template_delete(self, id): + params = '--id %s' % id + return self.sahara('cluster-template-delete', params=params) + + def cluster_create(self, filename): + params = '--json %s' % filename + return self.sahara('cluster-create', params=params) + + def cluster_delete(self, id): + params = '--id %s' % id + return self.sahara('cluster-delete', params=params) + + def job_binary_create(self, name, url, desc='', username='', password=''): + params = '--name %s --url %s' % (name, url) + if desc: + params += ' --description %s' % desc + if username: + params += ' --user %s' % username + if password: + params += ' --password %s' % password + return self.sahara('job-binary-create', params=params) + + def job_binary_delete(self, id): + params = '--id %s' % id + return self.sahara('job-binary-delete', params=params) + + def job_binary_data_create(self, fname): + params = '--file %s' % fname + return self.sahara('job-binary-data-create', params=params) + + def job_binary_data_delete(self, id): + params = '--id %s' % id + return self.sahara('job-binary-data-delete', params=params) + + def job_template_create(self, name, jobtype, main='', lib=''): + params = '--name %s --type %s' % (name, jobtype) + if main: + params += ' --main %s' % main + if lib: + params += ' --lib %s' % lib + return self.sahara('job-template-create', params=params) + + def job_template_delete(self, id): + params = '--id %s' % id + return self.sahara('job-template-delete', params=params) + + def job_create(self, job_id, cluster_id, input_id='', output_id='', + job_params=None, args=None, configs=None): + params = '--job-template %s --cluster %s' % (job_id, cluster_id) + if input_id: + params += ' --input-data %s' % input_id + if output_id: + params += ' --output-data %s' % output_id + if job_params: + for k, v in six.iteritems(params): + params += ' --param %s=%s' % (k, v) + if args: + for arg in args: + params += ' --arg %s' % arg + if configs: + for k, v in six.iteritems(configs): + params += ' --config %s=%s' % (k, v) + return self.sahara('job-create', params=params) + + def job_delete(self, id): + params = '--id %s' % id + return self.sahara('job-delete', params=params) + + def data_source_create(self, name, datatype, url, + desc='', username='', password=''): + params = '--name %s --type %s --url %s' % (name, datatype, url) + if desc: + params += ' --description %s' % desc + if username: + params += ' --user %s' % username + if password: + params += ' --password %s' % password + return self.sahara('data-source-create', params=params) + + def data_source_delete(self, id): + params = '--id %s' % id + return self.sahara('data-source-delete', params=params) diff --git a/saharaclient/tests/integration/tests/full_test_driver.py b/saharaclient/tests/integration/tests/full_test_driver.py new file mode 100644 index 00000000..a19240f0 --- /dev/null +++ b/saharaclient/tests/integration/tests/full_test_driver.py @@ -0,0 +1,22 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 saharaclient.tests.integration.tests.base as base + + +class FullTestDriver(base.ITestBase): + + def drive_full_test(self, config, ng_templates): + pass diff --git a/saharaclient/tests/integration/tests/test_hdp.py b/saharaclient/tests/integration/tests/test_hdp.py new file mode 100644 index 00000000..dc2f69f2 --- /dev/null +++ b/saharaclient/tests/integration/tests/test_hdp.py @@ -0,0 +1,31 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 testtools + +from saharaclient.tests.integration.configs import config as cfg +import saharaclient.tests.integration.tests.full_test_driver as driver + +cfg = cfg.ITConfig() +hdp = cfg.hdp_config + + +class ClusterHDP(driver.FullTestDriver): + + @testtools.skipIf(hdp.SKIP_ALL_TESTS_FOR_PLUGIN, + 'All tests for Hdp plugin were skipped') + def test_cluster_hdp(self): + ng_templates = {} + self.drive_full_test(hdp, ng_templates) diff --git a/saharaclient/tests/integration/tests/test_vanilla.py b/saharaclient/tests/integration/tests/test_vanilla.py new file mode 100644 index 00000000..a3f49e55 --- /dev/null +++ b/saharaclient/tests/integration/tests/test_vanilla.py @@ -0,0 +1,31 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 testtools + +from saharaclient.tests.integration.configs import config as cfg +import saharaclient.tests.integration.tests.full_test_driver as driver + +cfg = cfg.ITConfig() +vanilla = cfg.vanilla_config + + +class ClusterVanilla(driver.FullTestDriver): + + @testtools.skipIf(vanilla.SKIP_ALL_TESTS_FOR_PLUGIN, + 'All tests for Vanilla plugin were skipped') + def test_cluster_vanilla(self): + ng_templates = {} + self.drive_full_test(vanilla, ng_templates) diff --git a/saharaclient/tests/integration/tests/test_vanilla2.py b/saharaclient/tests/integration/tests/test_vanilla2.py new file mode 100644 index 00000000..b1edfa0d --- /dev/null +++ b/saharaclient/tests/integration/tests/test_vanilla2.py @@ -0,0 +1,31 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 testtools + +from saharaclient.tests.integration.configs import config as cfg +import saharaclient.tests.integration.tests.full_test_driver as driver + +cfg = cfg.ITConfig() +vanilla = cfg.vanilla2_config + + +class ClusterVanilla2(driver.FullTestDriver): + + @testtools.skipIf(vanilla.SKIP_ALL_TESTS_FOR_PLUGIN, + 'All tests for Vanilla2 plugin were skipped') + def test_cluster_vanilla(self): + ng_templates = {} + self.drive_full_test(vanilla, ng_templates) diff --git a/saharaclient/tests/integration/tests/utils.py b/saharaclient/tests/integration/tests/utils.py new file mode 100644 index 00000000..2aa2afb9 --- /dev/null +++ b/saharaclient/tests/integration/tests/utils.py @@ -0,0 +1,39 @@ +# Copyright (c) 2014 Red Hat Inc. +# +# 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 saharaclient.api.client as client +from saharaclient.tests.integration.configs import config as cfg +from swiftclient import client as swift_client + +cfg = cfg.ITConfig() +common = cfg.common_config + + +class Utils(object): + def __init__(self): + self.client = client.Client(username=common['OS_USERNAME'], + api_key=common['OS_PASSWORD'], + auth_url=common['OS_AUTH_URL'], + project_name=common['OS_PROJECT_NAME']) + + +class SwiftUtils(object): + def __init__(self): + self.client = swift_client.Connection( + authurl=common['OS_AUTH_URL'], + user=common['OS_USERNAME'], + key=common['OS_PASSWORD'], + tenant_name=common['OS_TENANT_NAME'], + auth_version=common['SWIFT_AUTH_VERSION']) diff --git a/test-requirements.txt b/test-requirements.txt index b933dfc1..84df32f4 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -7,3 +7,4 @@ docutils==0.9.1 oslosphinx testrepository>=0.0.18 sphinx>=1.1.2,<1.2 +python-swiftclient>=1.6