diff --git a/releasenotes/notes/add-user-access-related-to-osc-ae7da3a8f5fbdd6a.yaml b/releasenotes/notes/add-user-access-related-to-osc-ae7da3a8f5fbdd6a.yaml new file mode 100644 index 00000000..0becfa6a --- /dev/null +++ b/releasenotes/notes/add-user-access-related-to-osc-ae7da3a8f5fbdd6a.yaml @@ -0,0 +1,7 @@ +--- +features: + - The command ``trove user-grant-access`` and ``trove user-revoke-access`` + and ``trove user-show-access`` are now available to use in + the python-openstackclient CLI as ``openstack database user + grant access`` and ``openstack database user revoke access`` and + ``openstack database user show access`` diff --git a/setup.cfg b/setup.cfg index eb495f39..04ec7df4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -54,8 +54,11 @@ openstack.database.v1 = database_limit_list = troveclient.osc.v1.database_limits:ListDatabaseLimits database_user_create = troveclient.osc.v1.database_users:CreateDatabaseUser database_user_delete = troveclient.osc.v1.database_users:DeleteDatabaseUser + database_user_grant_access = troveclient.osc.v1.database_users:GrantDatabaseUserAccess database_user_list = troveclient.osc.v1.database_users:ListDatabaseUsers + database_user_revoke_access = troveclient.osc.v1.database_users:RevokeDatabaseUserAccess database_user_show = troveclient.osc.v1.database_users:ShowDatabaseUser + database_user_show_access = troveclient.osc.v1.database_users:ShowDatabaseUserAccess datastore_list = troveclient.osc.v1.datastores:ListDatastores datastore_show = troveclient.osc.v1.datastores:ShowDatastore datastore_version_list = troveclient.osc.v1.datastores:ListDatastoreVersions diff --git a/troveclient/osc/v1/database_users.py b/troveclient/osc/v1/database_users.py index dac7daea..36aba86e 100644 --- a/troveclient/osc/v1/database_users.py +++ b/troveclient/osc/v1/database_users.py @@ -160,3 +160,117 @@ class DeleteDatabaseUser(command.Command): msg = (_("Failed to delete user %(user)s: %(e)s") % {'user': parsed_args.name, 'e': e}) raise exceptions.CommandError(msg) + + +class GrantDatabaseUserAccess(command.Command): + + _description = _("Grants access to a database(s) for a user.") + + def get_parser(self, prog_name): + parser = super(GrantDatabaseUserAccess, self).get_parser(prog_name) + parser.add_argument( + 'instance', + metavar='', + help=_('ID or name of the instance.') + ) + parser.add_argument( + 'name', + metavar='', + help=_('Name of user.') + ) + parser.add_argument( + '--host', + metavar='', + default=None, + help=_('Optional host of user.') + ) + parser.add_argument( + 'databases', + metavar='', + nargs="+", + default=[], + help=_('List of databases.') + ) + return parser + + def take_action(self, parsed_args): + manager = self.app.client_manager.database + users = manager.users + instance = utils.find_resource(manager.instances, + parsed_args.instance) + users.grant(instance, parsed_args.name, + parsed_args.databases, hostname=parsed_args.host) + + +class RevokeDatabaseUserAccess(command.Command): + + _description = _("Revokes access to a database for a user.") + + def get_parser(self, prog_name): + parser = super(RevokeDatabaseUserAccess, self).get_parser(prog_name) + parser.add_argument( + 'instance', + metavar='', + help=_('ID or name of the instance.') + ) + parser.add_argument( + 'name', + metavar='', + help=_('Name of user.') + ) + parser.add_argument( + '--host', + metavar='', + default=None, + help=_('Optional host of user.') + ) + parser.add_argument( + 'databases', + metavar='', + help=_('A single database.') + ) + return parser + + def take_action(self, parsed_args): + manager = self.app.client_manager.database + users = manager.users + instance = utils.find_resource(manager.instances, + parsed_args.instance) + users.revoke(instance, parsed_args.name, + parsed_args.databases, hostname=parsed_args.host) + + +class ShowDatabaseUserAccess(command.Lister): + + _description = _("Shows access details of a user of an instance.") + columns = ['Name'] + + def get_parser(self, prog_name): + parser = super(ShowDatabaseUserAccess, self).get_parser(prog_name) + parser.add_argument( + 'instance', + metavar='', + help=_('ID or name of the instance.') + ) + parser.add_argument( + 'name', + metavar='', + help=_('Name of user.') + ) + parser.add_argument( + '--host', + metavar='', + default=None, + help=_('Optional host of user.') + ) + return parser + + def take_action(self, parsed_args): + manager = self.app.client_manager.database + users = manager.users + instance = utils.find_resource(manager.instances, + parsed_args.instance) + names = users.list_access(instance, parsed_args.name, + hostname=parsed_args.host) + access = [utils.get_item_properties(n, self.columns) for n in names] + return self.columns, access diff --git a/troveclient/tests/osc/v1/fakes.py b/troveclient/tests/osc/v1/fakes.py index 77730864..277274de 100644 --- a/troveclient/tests/osc/v1/fakes.py +++ b/troveclient/tests/osc/v1/fakes.py @@ -87,10 +87,16 @@ class FakeLimits(object): class FakeUsers(object): fake_users = fakes.FakeHTTPClient().get_instances_1234_users()[2]['users'] + fake_user_access = fakes.FakeHTTPClient().\ + get_instances_1234_users_jacob_databases()[2] def get_instances_1234_users_harry(self): return users.User(None, self.fake_users[2]) + def get_instances_1234_users_access(self): + return [databases.Database(self, db) for db in + self.fake_user_access['databases']] + class FakeInstances(object): fake_instances = (fakes.FakeHTTPClient().get_instances()[2]['instances']) diff --git a/troveclient/tests/osc/v1/test_database_users.py b/troveclient/tests/osc/v1/test_database_users.py index 9fb98395..f40079ea 100644 --- a/troveclient/tests/osc/v1/test_database_users.py +++ b/troveclient/tests/osc/v1/test_database_users.py @@ -136,3 +136,70 @@ class TestDatabaseUserDelete(TestUsers): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) + + +class TestDatabaseUserGrantAccess(TestUsers): + + def setUp(self): + super(TestDatabaseUserGrantAccess, self).setUp() + self.cmd = database_users.GrantDatabaseUserAccess(self.app, None) + + @mock.patch.object(utils, 'find_resource') + def test_user_grant_access(self, mock_find): + args = ['userinstance', 'user1', '--host', '1.1.1.1', 'db1'] + verifylist = [ + ('instance', 'userinstance'), + ('name', 'user1'), + ('host', '1.1.1.1'), + ('databases', ['db1']), + ] + mock_find.return_value = args[0] + parsed_args = self.check_parser(self.cmd, args, verifylist) + result = self.cmd.take_action(parsed_args) + self.assertIsNone(result) + + +class TestDatabaseUserRevokeAccess(TestUsers): + + def setUp(self): + super(TestDatabaseUserRevokeAccess, self).setUp() + self.cmd = database_users.RevokeDatabaseUserAccess(self.app, None) + + @mock.patch.object(utils, 'find_resource') + def test_user_grant_access(self, mock_find): + args = ['userinstance', 'user1', '--host', '1.1.1.1', 'db1'] + verifylist = [ + ('instance', 'userinstance'), + ('name', 'user1'), + ('host', '1.1.1.1'), + ('databases', 'db1'), + ] + mock_find.return_value = args[0] + parsed_args = self.check_parser(self.cmd, args, verifylist) + result = self.cmd.take_action(parsed_args) + self.assertIsNone(result) + + +class TestDatabaseUserShowAccess(TestUsers): + columns = database_users.ShowDatabaseUserAccess.columns + values = [('db_1',), ('db_2',)] + + def setUp(self): + super(TestDatabaseUserShowAccess, self).setUp() + self.cmd = database_users.ShowDatabaseUserAccess(self.app, None) + self.data = self.fake_users.get_instances_1234_users_access() + self.user_client.list_access.return_value = self.data + + @mock.patch.object(utils, 'find_resource') + def test_user_grant_access(self, mock_find): + args = ['userinstance', 'user1', '--host', '1.1.1.1'] + verifylist = [ + ('instance', 'userinstance'), + ('name', 'user1'), + ('host', '1.1.1.1'), + ] + mock_find.return_value = args[0] + parsed_args = self.check_parser(self.cmd, args, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.assertEqual(self.columns, columns) + self.assertEqual(self.values, data)