diff --git a/freezerclient/shell.py b/freezerclient/shell.py index 0ba8c31..5901ebe 100644 --- a/freezerclient/shell.py +++ b/freezerclient/shell.py @@ -98,6 +98,13 @@ class FreezerShell(app.App): help='Specify identity endpoint', ) + parser.add_argument( + '--os-backup-api-version', + dest='os_backup_api_version', + default=os.environ.get('OS_BACKUP_API_VERSION', '2'), + help='Backup API version: 1 or 2' + ) + parser.add_argument( '--os-backup-url', dest='os_backup_url', @@ -250,7 +257,8 @@ class FreezerShell(app.App): 'cacert': self.options.os_cacert, 'insecure': self.options.insecure } - return utils.get_client_instance(opts) + return utils.get_client_instance( + opts, api_version=self.options.os_backup_api_version) def main(argv=sys.argv[1:]): diff --git a/freezerclient/tests/unit/test_shell.py b/freezerclient/tests/unit/test_shell.py new file mode 100644 index 0000000..c1b825f --- /dev/null +++ b/freezerclient/tests/unit/test_shell.py @@ -0,0 +1,137 @@ +# (c) Copyright 2018 ZTE Corporation. +# +# 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 os +import re +import sys + +import fixtures +import six +import testtools +from testtools import matchers + +from freezerclient import shell as openstack_shell + + +DEFAULT_USERNAME = 'username' +DEFAULT_PASSWORD = 'password' +DEFAULT_PROJECT_ID = 'tenant_id' +DEFAULT_PROJECT_NAME = 'tenant_name' +DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/' + + +class ShellTest(testtools.TestCase): + + FAKE_ENV = { + 'OS_USERNAME': DEFAULT_USERNAME, + 'OS_PASSWORD': DEFAULT_PASSWORD, + 'OS_TENANT_ID': DEFAULT_PROJECT_ID, + 'OS_TENANT_NAME': DEFAULT_PROJECT_NAME, + 'OS_PROJECT_ID': DEFAULT_PROJECT_ID, + 'OS_PROJECT_NAME': DEFAULT_PROJECT_NAME, + 'OS_AUTH_URL': DEFAULT_AUTH_URL, + } + + # Patch os.environ to avoid required auth info. + def setUp(self): + super(ShellTest, self).setUp() + for var in self.FAKE_ENV: + self.useFixture( + fixtures.EnvironmentVariable( + var, self.FAKE_ENV[var])) + + def shell(self, argstr, check=False, expected_val=0): + # expected_val is the expected return value after executing + # the command in FreezerShell + orig = (sys.stdout, sys.stderr) + clean_env = {} + _old_env, os.environ = os.environ, clean_env.copy() + try: + sys.stdout = six.moves.cStringIO() + sys.stderr = six.moves.cStringIO() + _shell = openstack_shell.FreezerShell() + _shell.run(argstr.split()) + except SystemExit: + exc_type, exc_value, exc_traceback = sys.exc_info() + self.assertEqual(expected_val, exc_value.code) + finally: + stdout = sys.stdout.getvalue() + stderr = sys.stderr.getvalue() + sys.stdout.close() + sys.stderr.close() + sys.stdout, sys.stderr = orig + os.environ = _old_env + return stdout, stderr, _shell.options + + def test_help(self): + required = 'usage:' + help_text, stderr, _ = self.shell('help') + self.assertThat( + help_text, + matchers.MatchesRegex(required)) + + def test_help_on_subcommand(self): + required = [ + '.*?^usage: .* job-list'] + stdout, stderr, _ = self.shell('help job-list') + for r in required: + self.assertThat( + stdout, + matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) + + def test_help_command(self): + required = 'usage:' + help_text, stderr, _ = self.shell('help action-create') + self.assertThat( + help_text, + matchers.MatchesRegex(required)) + + def test_run_incomplete_command(self): + cmd = 'job-create' + stdout, stderr, _ = self.shell(cmd, check=True, expected_val=2) + search_str = "run job-create: error" + self.assertTrue(any(search_str in string for string + in stderr.split('\n'))) + + def test_set_os_backup_api_version(self): + cmd = ( + '--os-backup-api-version 1 job-list') + stdout, stderr, options = self.shell(cmd) + self.assertEqual("1", options.os_backup_api_version) + + def test_default_os_backup_api_version(self): + cmd = 'help job-list' + stdout, stderr, options = self.shell(cmd) + self.assertEqual("2", options.os_backup_api_version) + + def test_set_os_username_password(self): + cmd = ( + '--os-username caihui --os-password stack job-list') + stdout, stderr, options = self.shell(cmd) + self.assertEqual("caihui", options.os_username) + self.assertEqual("stack", options.os_password) + + def test_set_os_project_name_id(self): + cmd = ( + '--os-project-id tecs0000000001 \ + --os-project-name tecs job-list') + stdout, stderr, options = self.shell(cmd) + self.assertEqual("tecs0000000001", options.os_project_id) + self.assertEqual("tecs", options.os_project_name) + + def test_set_os_auth_url(self): + cmd = ( + '--os-auth-url http://127.0.0.1:5001 job-list') + stdout, stderr, options = self.shell(cmd) + self.assertEqual("http://127.0.0.1:5001", options.os_auth_url) diff --git a/freezerclient/utils.py b/freezerclient/utils.py index 87cbe10..9337166 100644 --- a/freezerclient/utils.py +++ b/freezerclient/utils.py @@ -143,13 +143,17 @@ def prepare_search(search_term): return {} -def check_api_version(): +def check_api_version(api_version=None): """Check freezer version API to use 1: not multi-tenant, useful for infrastructure 2: multi-tenant, useful for backup as a service :return: str """ - freezer_api_version = os.environ.get('OS_BACKUP_API_VERSION', '2') + if not api_version: + freezer_api_version = os.environ.get('OS_BACKUP_API_VERSION', '2') + else: + freezer_api_version = api_version + if freezer_api_version == '1': return '1' elif freezer_api_version == '2': @@ -165,16 +169,15 @@ def get_client_class(api_version=None): Returns freezerclient.v{x}.client.Client :return: class """ - if not api_version: - api_version = check_api_version() - api_string = 'freezerclient.v{0}.client.Client'.format(api_version) + freezer_api_version = check_api_version(api_version) + api_string = 'freezerclient.v{0}.client.Client'.format(freezer_api_version) return importutils.import_class(api_string) -def get_client_instance(kwargs={}, opts=None): +def get_client_instance(kwargs={}, opts=None, api_version=None): """Get Freezerclient Instance. We will the provided auth dict to instantiate a client instance Returns freezerclient.v{x}.client.Client Object :return: Object """ - return get_client_class()(opts=opts, **kwargs) + return get_client_class(api_version)(opts=opts, **kwargs)