Merge "Define image_members_client of image v2 as library"
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 10364db..98b006d 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -51,6 +51,7 @@
account_generator
cleanup
javelin
+ workspace
==================
Indices and tables
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 3568470..17059e4 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -19,6 +19,7 @@
multiple Microversion tests in a single Tempest operation, configuration
options should represent the range of test target Microversions.
New configuration options are:
+
* min_microversion
* max_microversion
@@ -130,8 +131,9 @@
If that range is out of configured Microversion range then, test
will be skipped.
-*NOTE: Microversion testing is supported at test class level not at individual
-test case level.*
+.. note:: Microversion testing is supported at test class level not at
+ individual test case level.
+
For example:
Below test is applicable for Microversion from 2.2 till 2.9::
@@ -211,3 +213,7 @@
* `2.10`_
.. _2.10: http://docs.openstack.org/developer/nova/api_microversion_history.html#id9
+
+ * `2.20`_
+
+ .. _2.20: http://docs.openstack.org/developer/nova/api_microversion_history.html#id18
diff --git a/doc/source/workspace.rst b/doc/source/workspace.rst
new file mode 100644
index 0000000..41325b2
--- /dev/null
+++ b/doc/source/workspace.rst
@@ -0,0 +1,5 @@
+-----------------
+Tempest Workspace
+-----------------
+
+.. automodule:: tempest.cmd.workspace
diff --git a/releasenotes/releasenotes/notes/add-tempest-workspaces-228a2ba4690b5589.yaml b/releasenotes/releasenotes/notes/add-tempest-workspaces-228a2ba4690b5589.yaml
new file mode 100644
index 0000000..9a1cef6
--- /dev/null
+++ b/releasenotes/releasenotes/notes/add-tempest-workspaces-228a2ba4690b5589.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - Adds tempest workspaces command and WorkspaceManager.
+ This is used to have a centralized repository for managing
+ different tempest configurations.
diff --git a/setup.cfg b/setup.cfg
index 24e0214..0bf493c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -41,6 +41,7 @@
run-stress = tempest.cmd.run_stress:TempestRunStress
list-plugins = tempest.cmd.list_plugins:TempestListPlugins
verify-config = tempest.cmd.verify_tempest_config:TempestVerifyConfig
+ workspace = tempest.cmd.workspace:TempestWorkspace
oslo.config.opts =
tempest.config = tempest.config:list_opts
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 307d6d6..3fefc81 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -137,7 +137,7 @@
@classmethod
def setup_clients(cls):
super(BaseV2MemberImageTest, cls).setup_clients()
- cls.os_image_member_client = cls.os.image_member_client_v2
+ cls.image_member_client = cls.os.image_member_client_v2
cls.alt_image_member_client = cls.os_alt.image_member_client_v2
cls.alt_img_client = cls.os_alt.image_client_v2
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index d8254f5..fe8dd65 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -19,7 +19,7 @@
@test.idempotent_id('5934c6ea-27dc-4d6e-9421-eeb5e045494a')
def test_image_share_accept(self):
image_id = self._create_image()
- member = self.os_image_member_client.create_image_member(
+ member = self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.assertEqual(member['member_id'], self.alt_tenant_id)
self.assertEqual(member['image_id'], image_id)
@@ -29,7 +29,7 @@
self.alt_tenant_id,
status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
- body = self.os_image_member_client.list_image_members(image_id)
+ body = self.image_member_client.list_image_members(image_id)
members = body['members']
member = members[0]
self.assertEqual(len(members), 1, str(members))
@@ -40,7 +40,7 @@
@test.idempotent_id('d9e83e5f-3524-4b38-a900-22abcb26e90e')
def test_image_share_reject(self):
image_id = self._create_image()
- member = self.os_image_member_client.create_image_member(
+ member = self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.assertEqual(member['member_id'], self.alt_tenant_id)
self.assertEqual(member['image_id'], image_id)
@@ -54,14 +54,14 @@
@test.idempotent_id('a6ee18b9-4378-465e-9ad9-9a6de58a3287')
def test_get_image_member(self):
image_id = self._create_image()
- self.os_image_member_client.create_image_member(
+ self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.alt_image_member_client.update_image_member(image_id,
self.alt_tenant_id,
status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
- member = self.os_image_member_client.show_image_member(
+ member = self.image_member_client.show_image_member(
image_id, self.alt_tenant_id)
self.assertEqual(self.alt_tenant_id, member['member_id'])
self.assertEqual(image_id, member['image_id'])
@@ -70,15 +70,15 @@
@test.idempotent_id('72989bc7-2268-48ed-af22-8821e835c914')
def test_remove_image_member(self):
image_id = self._create_image()
- self.os_image_member_client.create_image_member(
+ self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.alt_image_member_client.update_image_member(image_id,
self.alt_tenant_id,
status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
- self.os_image_member_client.delete_image_member(image_id,
- self.alt_tenant_id)
+ self.image_member_client.delete_image_member(image_id,
+ self.alt_tenant_id)
self.assertNotIn(image_id, self._list_image_ids_as_alt())
@test.idempotent_id('634dcc3f-f6e2-4409-b8fd-354a0bb25d83')
@@ -94,7 +94,7 @@
@test.idempotent_id('cb961424-3f68-4d21-8e36-30ad66fb6bfb')
def test_get_private_image(self):
image_id = self._create_image()
- member = self.os_image_member_client.create_image_member(
+ member = self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.assertEqual(member['member_id'], self.alt_tenant_id)
self.assertEqual(member['image_id'], image_id)
@@ -104,6 +104,6 @@
self.alt_tenant_id,
status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
- self.os_image_member_client.delete_image_member(image_id,
- self.alt_tenant_id)
+ self.image_member_client.delete_image_member(image_id,
+ self.alt_tenant_id)
self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
index 5a08d77..fa29a92 100644
--- a/tempest/api/image/v2/test_images_member_negative.py
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -21,7 +21,7 @@
@test.idempotent_id('b79efb37-820d-4cf0-b54c-308b00cf842c')
def test_image_share_invalid_status(self):
image_id = self._create_image()
- member = self.os_image_member_client.create_image_member(
+ member = self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.assertEqual(member['status'], 'pending')
self.assertRaises(lib_exc.BadRequest,
@@ -33,11 +33,11 @@
@test.idempotent_id('27002f74-109e-4a37-acd0-f91cd4597967')
def test_image_share_owner_cannot_accept(self):
image_id = self._create_image()
- member = self.os_image_member_client.create_image_member(
+ member = self.image_member_client.create_image_member(
image_id, member=self.alt_tenant_id)
self.assertEqual(member['status'], 'pending')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
self.assertRaises(lib_exc.Forbidden,
- self.os_image_member_client.update_image_member,
+ self.image_member_client.update_image_member,
image_id, self.alt_tenant_id, status='accepted')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/cmd/init.py b/tempest/cmd/init.py
index 633b9e9..77d62d3 100644
--- a/tempest/cmd/init.py
+++ b/tempest/cmd/init.py
@@ -21,6 +21,8 @@
from oslo_log import log as logging
from six import moves
+from tempest.cmd.workspace import WorkspaceManager
+
LOG = logging.getLogger(__name__)
TESTR_CONF = """[DEFAULT]
@@ -89,6 +91,10 @@
action='store_true', dest='show_global_dir',
help="Print the global config dir location, "
"then exit")
+ parser.add_argument('--name', help="The workspace name", default=None)
+ parser.add_argument('--workspace-path', default=None,
+ help="The path to the workspace file, the default "
+ "is ~/.tempest/workspace")
return parser
def generate_testr_conf(self, local_path):
@@ -114,15 +120,22 @@
config_parse.write(conf_file)
def copy_config(self, etc_dir, config_dir):
- shutil.copytree(config_dir, etc_dir)
+ if os.path.isdir(config_dir):
+ shutil.copytree(config_dir, etc_dir)
+ else:
+ LOG.warning("Global config dir %s can't be found" % config_dir)
def generate_sample_config(self, local_dir, config_dir):
- conf_generator = os.path.join(config_dir,
- 'config-generator.tempest.conf')
+ if os.path.isdir(config_dir):
+ conf_generator = os.path.join(config_dir,
+ 'config-generator.tempest.conf')
- subprocess.call(['oslo-config-generator', '--config-file',
- conf_generator],
- cwd=local_dir)
+ subprocess.call(['oslo-config-generator', '--config-file',
+ conf_generator],
+ cwd=local_dir)
+ else:
+ LOG.warning("Skipping sample config generation because global "
+ "config dir %s can't be found" % config_dir)
def create_working_dir(self, local_dir, config_dir):
# Create local dir if missing
@@ -159,6 +172,10 @@
subprocess.call(['testr', 'init'], cwd=local_dir)
def take_action(self, parsed_args):
+ workspace_manager = WorkspaceManager(parsed_args.workspace_path)
+ name = parsed_args.name or parsed_args.dir.split(os.path.sep)[-1]
+ workspace_manager.register_new_workspace(
+ name, parsed_args.dir, init=True)
config_dir = parsed_args.config_dir or get_tempest_default_config_dir()
if parsed_args.show_global_dir:
print("Global config dir is located at: %s" % config_dir)
diff --git a/tempest/cmd/workspace.py b/tempest/cmd/workspace.py
new file mode 100644
index 0000000..cc82284
--- /dev/null
+++ b/tempest/cmd/workspace.py
@@ -0,0 +1,218 @@
+# Copyright 2016 Rackspace
+#
+# 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.
+
+"""
+Manages Tempest workspaces
+
+This command is used for managing tempest workspaces
+
+Commands
+========
+
+list
+----
+Outputs the name and path of all known tempest workspaces
+
+register
+--------
+Registers a new tempest workspace via a given --name and --path
+
+rename
+------
+Renames a tempest workspace from --old-name to --new-name
+
+move
+----
+Changes the path of a given tempest workspace --name to --path
+
+remove
+------
+Deletes the entry for a given tempest workspace --name
+
+General Options
+===============
+
+ **--workspace_path**: Allows the user to specify a different location for the
+ workspace.yaml file containing the workspace definitions
+ instead of ~/.tempest/workspace.yaml
+"""
+
+import os
+import sys
+
+from cliff import command
+from oslo_concurrency import lockutils
+from oslo_log import log as logging
+import prettytable
+import yaml
+
+from tempest import config
+
+LOG = logging.getLogger(__name__)
+CONF = config.CONF
+
+
+class WorkspaceManager(object):
+ def __init__(self, path=None):
+ lockutils.get_lock_path(CONF)
+ self.path = path or os.path.join(
+ os.path.expanduser("~"), ".tempest", "workspace.yaml")
+ if not os.path.isdir(os.path.dirname(self.path)):
+ os.makedirs(self.path.rsplit(os.path.sep, 1)[0])
+ self.workspaces = {}
+
+ @lockutils.synchronized('workspaces', external=True)
+ def get_workspace(self, name):
+ """Returns the workspace that has the given name"""
+ self._populate()
+ return self.workspaces.get(name)
+
+ @lockutils.synchronized('workspaces', external=True)
+ def rename_workspace(self, old_name, new_name):
+ self._populate()
+ self._name_exists(old_name)
+ self._workspace_name_exists(new_name)
+ self.workspaces[new_name] = self.workspaces.pop(old_name)
+ self._write_file()
+
+ @lockutils.synchronized('workspaces', external=True)
+ def move_workspace(self, name, path):
+ self._populate()
+ path = os.path.abspath(os.path.expanduser(path))
+ self._name_exists(name)
+ self._validate_path(path)
+ self.workspaces[name] = path
+ self._write_file()
+
+ def _name_exists(self, name):
+ if name not in self.workspaces:
+ print("A workspace was not found with name: {0}".format(name))
+ sys.exit(1)
+
+ @lockutils.synchronized('workspaces', external=True)
+ def remove_workspace(self, name):
+ self._populate()
+ self._name_exists(name)
+ self.workspaces.pop(name)
+ self._write_file()
+
+ @lockutils.synchronized('workspaces', external=True)
+ def list_workspaces(self):
+ self._populate()
+ self._validate_workspaces()
+ return self.workspaces
+
+ def _workspace_name_exists(self, name):
+ if name in self.workspaces:
+ print("A workspace already exists with name: {0}.".format(
+ name))
+ sys.exit(1)
+
+ def _validate_path(self, path):
+ if not os.path.exists(path):
+ print("Path does not exist.")
+ sys.exit(1)
+
+ @lockutils.synchronized('workspaces', external=True)
+ def register_new_workspace(self, name, path, init=False):
+ """Adds the new workspace and writes out the new workspace config"""
+ self._populate()
+ path = os.path.abspath(os.path.expanduser(path))
+ # This only happens when register is called from outside of init
+ if not init:
+ self._validate_path(path)
+ self._workspace_name_exists(name)
+ self.workspaces[name] = path
+ self._write_file()
+
+ def _validate_workspaces(self):
+ if self.workspaces is not None:
+ self.workspaces = {n: p for n, p in self.workspaces.items()
+ if os.path.exists(p)}
+ self._write_file()
+
+ def _write_file(self):
+ with open(self.path, 'w') as f:
+ f.write(yaml.dump(self.workspaces))
+
+ def _populate(self):
+ if not os.path.isfile(self.path):
+ return
+ with open(self.path, 'r') as f:
+ self.workspaces = yaml.load(f) or {}
+
+
+class TempestWorkspace(command.Command):
+ def take_action(self, parsed_args):
+ self.manager = WorkspaceManager(parsed_args.workspace_path)
+ if getattr(parsed_args, 'register', None):
+ self.manager.register_new_workspace(
+ parsed_args.name, parsed_args.path)
+ elif getattr(parsed_args, 'rename', None):
+ self.manager.rename_workspace(
+ parsed_args.old_name, parsed_args.new_name)
+ elif getattr(parsed_args, 'move', None):
+ self.manager.move_workspace(
+ parsed_args.name, parsed_args.path)
+ elif getattr(parsed_args, 'remove', None):
+ self.manager.remove_workspace(
+ parsed_args.name)
+ else:
+ self._print_workspaces()
+ sys.exit(0)
+
+ def get_description(self):
+ return 'Tempest workspace actions'
+
+ def get_parser(self, prog_name):
+ parser = super(TempestWorkspace, self).get_parser(prog_name)
+
+ parser.add_argument(
+ '--workspace-path', required=False, default=None,
+ help="The path to the workspace file, the default is "
+ "~/.tempest/workspace.yaml")
+
+ subparsers = parser.add_subparsers()
+
+ list_parser = subparsers.add_parser('list')
+ list_parser.set_defaults(list=True)
+
+ register_parser = subparsers.add_parser('register')
+ register_parser.add_argument('--name', required=True)
+ register_parser.add_argument('--path', required=True)
+ register_parser.set_defaults(register=True)
+
+ update_parser = subparsers.add_parser('rename')
+ update_parser.add_argument('--old-name', required=True)
+ update_parser.add_argument('--new-name', required=True)
+ update_parser.set_defaults(rename=True)
+
+ move_parser = subparsers.add_parser('move')
+ move_parser.add_argument('--name', required=True)
+ move_parser.add_argument('--path', required=True)
+ move_parser.set_defaults(move=True)
+
+ remove_parser = subparsers.add_parser('remove')
+ remove_parser.add_argument('--name', required=True)
+ remove_parser.set_defaults(remove=True)
+
+ return parser
+
+ def _print_workspaces(self):
+ output = prettytable.PrettyTable(["Name", "Path"])
+ if self.manager.list_workspaces() is not None:
+ for name, path in self.manager.list_workspaces().items():
+ output.add_row([name, path])
+
+ print(output)
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index 42c69d5..5992d24 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -86,10 +86,8 @@
self.test_accounts_file = test_accounts_file
if test_accounts_file:
accounts = read_accounts_yaml(self.test_accounts_file)
- self.use_default_creds = False
else:
- accounts = {}
- self.use_default_creds = True
+ raise lib_exc.InvalidCredentials("No accounts file specified")
self.hash_dict = self.get_hash_dict(
accounts, admin_role, object_storage_operator_role,
object_storage_reseller_admin_role)
@@ -165,12 +163,7 @@
return hash_dict
def is_multi_user(self):
- # Default credentials is not a valid option with locking Account
- if self.use_default_creds:
- raise lib_exc.InvalidCredentials(
- "Account file %s doesn't exist" % self.test_accounts_file)
- else:
- return len(self.hash_dict['creds']) > 1
+ return len(self.hash_dict['creds']) > 1
def is_multi_tenant(self):
return self.is_multi_user()
@@ -245,9 +238,6 @@
return temp_creds
def _get_creds(self, roles=None):
- if self.use_default_creds:
- raise lib_exc.InvalidCredentials(
- "Account file %s doesn't exist" % self.test_accounts_file)
useable_hashes = self._get_match_hash_list(roles)
if len(useable_hashes) == 0:
msg = 'No users configured for type/roles %s' % roles
@@ -329,12 +319,9 @@
return self.get_creds_by_roles([self.admin_role])
def is_role_available(self, role):
- if self.use_default_creds:
- return False
- else:
- if self.hash_dict['roles'].get(role):
- return True
- return False
+ if self.hash_dict['roles'].get(role):
+ return True
+ return False
def admin_available(self):
return self.is_role_available(self.admin_role)
diff --git a/tempest/tests/cmd/test_workspace.py b/tempest/tests/cmd/test_workspace.py
new file mode 100644
index 0000000..c4bd7b2
--- /dev/null
+++ b/tempest/tests/cmd/test_workspace.py
@@ -0,0 +1,124 @@
+# Copyright 2016 Rackspace
+#
+# 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 shutil
+import subprocess
+import tempfile
+
+from tempest.cmd.workspace import WorkspaceManager
+from tempest.lib.common.utils import data_utils
+from tempest.tests import base
+
+
+class TestTempestWorkspaceBase(base.TestCase):
+ def setUp(self):
+ super(TestTempestWorkspaceBase, self).setUp()
+ self.name = data_utils.rand_uuid()
+ self.path = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.path, ignore_errors=True)
+ store_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, store_dir, ignore_errors=True)
+ self.store_file = os.path.join(store_dir, 'workspace.yaml')
+ self.workspace_manager = WorkspaceManager(path=self.store_file)
+ self.workspace_manager.register_new_workspace(self.name, self.path)
+
+
+class TestTempestWorkspace(TestTempestWorkspaceBase):
+ def _run_cmd_gets_return_code(self, cmd, expected):
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ return_code = process.returncode
+ msg = ("%s failled with:\nstdout: %s\nstderr: %s" % (' '.join(cmd),
+ stdout, stderr))
+ self.assertEqual(return_code, expected, msg)
+
+ def test_run_workspace_list(self):
+ cmd = ['tempest', 'workspace', '--workspace-path',
+ self.store_file, 'list']
+ self._run_cmd_gets_return_code(cmd, 0)
+
+ def test_run_workspace_register(self):
+ name = data_utils.rand_uuid()
+ path = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, path, ignore_errors=True)
+ cmd = ['tempest', 'workspace', '--workspace-path', self.store_file,
+ 'register', '--name', name, '--path', path]
+ self._run_cmd_gets_return_code(cmd, 0)
+ self.assertIsNotNone(self.workspace_manager.get_workspace(name))
+
+ def test_run_workspace_rename(self):
+ new_name = data_utils.rand_uuid()
+ cmd = ['tempest', 'workspace', '--workspace-path', self.store_file,
+ 'rename', "--old-name", self.name, '--new-name', new_name]
+ self._run_cmd_gets_return_code(cmd, 0)
+ self.assertIsNone(self.workspace_manager.get_workspace(self.name))
+ self.assertIsNotNone(self.workspace_manager.get_workspace(new_name))
+
+ def test_run_workspace_move(self):
+ new_path = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, new_path, ignore_errors=True)
+ cmd = ['tempest', 'workspace', '--workspace-path', self.store_file,
+ 'move', '--name', self.name, '--path', new_path]
+ self._run_cmd_gets_return_code(cmd, 0)
+ self.assertEqual(
+ self.workspace_manager.get_workspace(self.name), new_path)
+
+ def test_run_workspace_remove(self):
+ cmd = ['tempest', 'workspace', '--workspace-path', self.store_file,
+ 'remove', '--name', self.name]
+ self._run_cmd_gets_return_code(cmd, 0)
+ self.assertIsNone(self.workspace_manager.get_workspace(self.name))
+
+
+class TestTempestWorkspaceManager(TestTempestWorkspaceBase):
+ def setUp(self):
+ super(TestTempestWorkspaceManager, self).setUp()
+ self.name = data_utils.rand_uuid()
+ self.path = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.path, ignore_errors=True)
+ store_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, store_dir, ignore_errors=True)
+ self.store_file = os.path.join(store_dir, 'workspace.yaml')
+ self.workspace_manager = WorkspaceManager(path=self.store_file)
+ self.workspace_manager.register_new_workspace(self.name, self.path)
+
+ def test_workspace_manager_get(self):
+ self.assertIsNotNone(self.workspace_manager.get_workspace(self.name))
+
+ def test_workspace_manager_rename(self):
+ new_name = data_utils.rand_uuid()
+ self.workspace_manager.rename_workspace(self.name, new_name)
+ self.assertIsNone(self.workspace_manager.get_workspace(self.name))
+ self.assertIsNotNone(self.workspace_manager.get_workspace(new_name))
+
+ def test_workspace_manager_move(self):
+ new_path = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, new_path, ignore_errors=True)
+ self.workspace_manager.move_workspace(self.name, new_path)
+ self.assertEqual(
+ self.workspace_manager.get_workspace(self.name), new_path)
+
+ def test_workspace_manager_remove(self):
+ self.workspace_manager.remove_workspace(self.name)
+ self.assertIsNone(self.workspace_manager.get_workspace(self.name))
+
+ def test_path_expansion(self):
+ name = data_utils.rand_uuid()
+ path = os.path.join("~", name)
+ os.makedirs(os.path.expanduser(path))
+ self.addCleanup(shutil.rmtree, path, ignore_errors=True)
+ self.workspace_manager.register_new_workspace(name, path)
+ self.assertIsNotNone(self.workspace_manager.get_workspace(name))