diff options
Diffstat (limited to 'openstackclient')
| -rw-r--r-- | openstackclient/identity/v3/project.py | 15 | ||||
| -rw-r--r-- | openstackclient/image/v1/image.py | 2 | ||||
| -rw-r--r-- | openstackclient/image/v2/image.py | 2 | ||||
| -rw-r--r-- | openstackclient/shell.py | 18 | ||||
| -rw-r--r-- | openstackclient/tests/identity/v3/fakes.py | 10 | ||||
| -rw-r--r-- | openstackclient/tests/identity/v3/test_project.py | 100 |
6 files changed, 131 insertions, 16 deletions
diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py index c5560f5e..0cb3c453 100644 --- a/openstackclient/identity/v3/project.py +++ b/openstackclient/identity/v3/project.py @@ -47,6 +47,11 @@ class CreateProject(show.ShowOne): help='Domain owning the project (name or ID)', ) parser.add_argument( + '--parent', + metavar='<project>', + help='Parent of the project (name or ID)', + ) + parser.add_argument( '--description', metavar='<description>', help='Project description', @@ -85,6 +90,13 @@ class CreateProject(show.ShowOne): domain = common.find_domain(identity_client, parsed_args.domain).id + parent = None + if parsed_args.parent: + parent = utils.find_resource( + identity_client.projects, + parsed_args.parent, + ).id + enabled = True if parsed_args.disable: enabled = False @@ -96,6 +108,7 @@ class CreateProject(show.ShowOne): project = identity_client.projects.create( name=parsed_args.name, domain=domain, + parent=parent, description=parsed_args.description, enabled=enabled, **kwargs @@ -110,8 +123,6 @@ class CreateProject(show.ShowOne): raise e project._info.pop('links') - # TODO(stevemar): Remove the line below when we support multitenancy - project._info.pop('parent_id', None) return zip(*sorted(six.iteritems(project._info))) diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py index 4c07d360..830b99ba 100644 --- a/openstackclient/image/v1/image.py +++ b/openstackclient/image/v1/image.py @@ -348,7 +348,7 @@ class ListImage(lister.Lister): help='List additional fields in output', ) - # --page-size has never worked, leave here for silent compatability + # --page-size has never worked, leave here for silent compatibility # We'll implement limit/marker differently later parser.add_argument( "--page-size", diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index eb82c910..99bf2674 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -98,7 +98,7 @@ class ListImage(lister.Lister): help='List additional fields in output', ) - # --page-size has never worked, leave here for silent compatability + # --page-size has never worked, leave here for silent compatibility # We'll implement limit/marker differently later parser.add_argument( "--page-size", diff --git a/openstackclient/shell.py b/openstackclient/shell.py index 00f4a3c9..5e291021 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -24,6 +24,7 @@ import warnings from cliff import app from cliff import command +from cliff import complete from cliff import help import openstackclient @@ -76,6 +77,7 @@ class OpenStackShell(app.App): # Some commands do not need authentication help.HelpCommand.auth_required = False + complete.CompleteCommand.auth_required = False super(OpenStackShell, self).__init__( description=__doc__.strip(), @@ -137,12 +139,11 @@ class OpenStackShell(app.App): # --debug forces traceback self.dump_stack_trace = True requests_log.setLevel(logging.DEBUG) - cliff_log.setLevel(logging.DEBUG) else: self.dump_stack_trace = False requests_log.setLevel(logging.ERROR) - cliff_log.setLevel(logging.ERROR) + cliff_log.setLevel(logging.ERROR) stevedore_log.setLevel(logging.ERROR) iso8601_log.setLevel(logging.ERROR) @@ -318,19 +319,12 @@ class OpenStackShell(app.App): cmd.__class__.__name__, ) if cmd.auth_required: - try: - # Trigger the Identity client to initialize - self.client_manager.auth_ref - except Exception as e: - self.log.warning("Possible error authenticating: " + str(e)) - pass + # Trigger the Identity client to initialize + self.client_manager.auth_ref return def clean_up(self, cmd, result, err): - self.log.debug('clean_up %s', cmd.__class__.__name__) - - if err: - self.log.debug('got an error: %s', err) + self.log.debug('clean_up %s: %s', cmd.__class__.__name__, err or '') # Process collected timing data if self.options.timing: diff --git a/openstackclient/tests/identity/v3/fakes.py b/openstackclient/tests/identity/v3/fakes.py index 4c7ef6c1..234a3ccf 100644 --- a/openstackclient/tests/identity/v3/fakes.py +++ b/openstackclient/tests/identity/v3/fakes.py @@ -135,6 +135,16 @@ REGION = { 'links': base_url + 'regions/' + region_id, } +PROJECT_WITH_PARENT = { + 'id': project_id + '-with-parent', + 'name': project_name + ' and their parents', + 'description': project_description + ' plus another four', + 'enabled': True, + 'domain_id': domain_id, + 'parent_id': project_id, + 'links': base_url + 'projects/' + (project_id + '-with-parent'), +} + role_id = 'r1' role_name = 'roller' diff --git a/openstackclient/tests/identity/v3/test_project.py b/openstackclient/tests/identity/v3/test_project.py index 874908da..ec50da0c 100644 --- a/openstackclient/tests/identity/v3/test_project.py +++ b/openstackclient/tests/identity/v3/test_project.py @@ -16,6 +16,7 @@ import copy import mock +from openstackclient.common import exceptions from openstackclient.identity.v3 import project from openstackclient.tests import fakes from openstackclient.tests.identity.v3 import fakes as identity_fakes @@ -60,6 +61,7 @@ class TestProjectCreate(TestProject): identity_fakes.project_name, ] verifylist = [ + ('parent', None), ('enable', False), ('disable', False), ('name', identity_fakes.project_name), @@ -75,6 +77,7 @@ class TestProjectCreate(TestProject): 'domain': None, 'description': None, 'enabled': True, + 'parent': None, } # ProjectManager.create(name=, domain=, description=, # enabled=, **kwargs) @@ -103,6 +106,7 @@ class TestProjectCreate(TestProject): ('enable', False), ('disable', False), ('name', identity_fakes.project_name), + ('parent', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -115,6 +119,7 @@ class TestProjectCreate(TestProject): 'domain': None, 'description': 'new desc', 'enabled': True, + 'parent': None, } # ProjectManager.create(name=, domain=, description=, # enabled=, **kwargs) @@ -143,6 +148,7 @@ class TestProjectCreate(TestProject): ('enable', False), ('disable', False), ('name', identity_fakes.project_name), + ('parent', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -155,6 +161,7 @@ class TestProjectCreate(TestProject): 'domain': identity_fakes.domain_id, 'description': None, 'enabled': True, + 'parent': None, } # ProjectManager.create(name=, domain=, description=, # enabled=, **kwargs) @@ -183,6 +190,7 @@ class TestProjectCreate(TestProject): ('enable', False), ('disable', False), ('name', identity_fakes.project_name), + ('parent', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) mocker = mock.Mock() @@ -197,6 +205,7 @@ class TestProjectCreate(TestProject): 'domain': identity_fakes.domain_id, 'description': None, 'enabled': True, + 'parent': None, } self.projects_mock.create.assert_called_with( **kwargs @@ -221,6 +230,7 @@ class TestProjectCreate(TestProject): ('enable', True), ('disable', False), ('name', identity_fakes.project_name), + ('parent', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -233,6 +243,7 @@ class TestProjectCreate(TestProject): 'domain': None, 'description': None, 'enabled': True, + 'parent': None, } # ProjectManager.create(name=, domain=, description=, # enabled=, **kwargs) @@ -260,6 +271,7 @@ class TestProjectCreate(TestProject): ('enable', False), ('disable', True), ('name', identity_fakes.project_name), + ('parent', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -272,6 +284,7 @@ class TestProjectCreate(TestProject): 'domain': None, 'description': None, 'enabled': False, + 'parent': None, } # ProjectManager.create(name=, domain=, # description=, enabled=, **kwargs) @@ -311,6 +324,7 @@ class TestProjectCreate(TestProject): 'domain': None, 'description': None, 'enabled': True, + 'parent': None, 'fee': 'fi', 'fo': 'fum', } @@ -331,6 +345,92 @@ class TestProjectCreate(TestProject): ) self.assertEqual(datalist, data) + def test_project_create_parent(self): + self.projects_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.PROJECT), + loaded=True, + ) + self.projects_mock.create.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.PROJECT_WITH_PARENT), + loaded=True, + ) + + arglist = [ + '--domain', identity_fakes.PROJECT_WITH_PARENT['domain_id'], + '--parent', identity_fakes.PROJECT['name'], + identity_fakes.PROJECT_WITH_PARENT['name'], + ] + verifylist = [ + ('domain', identity_fakes.PROJECT_WITH_PARENT['domain_id']), + ('parent', identity_fakes.PROJECT['name']), + ('enable', False), + ('disable', False), + ('name', identity_fakes.PROJECT_WITH_PARENT['name']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + kwargs = { + 'name': identity_fakes.PROJECT_WITH_PARENT['name'], + 'domain': identity_fakes.PROJECT_WITH_PARENT['domain_id'], + 'parent': identity_fakes.PROJECT['id'], + 'description': None, + 'enabled': True, + } + + self.projects_mock.create.assert_called_with( + **kwargs + ) + + collist = ( + 'description', + 'domain_id', + 'enabled', + 'id', + 'name', + 'parent_id', + ) + self.assertEqual(columns, collist) + datalist = ( + identity_fakes.PROJECT_WITH_PARENT['description'], + identity_fakes.PROJECT_WITH_PARENT['domain_id'], + identity_fakes.PROJECT_WITH_PARENT['enabled'], + identity_fakes.PROJECT_WITH_PARENT['id'], + identity_fakes.PROJECT_WITH_PARENT['name'], + identity_fakes.PROJECT['id'], + ) + self.assertEqual(data, datalist) + + def test_project_create_invalid_parent(self): + self.projects_mock.resource_class.__name__ = 'Project' + self.projects_mock.get.side_effect = exceptions.NotFound( + 'Invalid parent') + self.projects_mock.find.side_effect = exceptions.NotFound( + 'Invalid parent') + + arglist = [ + '--domain', identity_fakes.domain_name, + '--parent', 'invalid', + identity_fakes.project_name, + ] + verifylist = [ + ('domain', identity_fakes.domain_name), + ('parent', 'invalid'), + ('enable', False), + ('disable', False), + ('name', identity_fakes.project_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args, + ) + class TestProjectDelete(TestProject): |
