Add namespace support for workbooks to client

Accept namespace parameter for workbook commands

Depends-On: I2c66b3961915f0f35a9c468eb6dd0c0c70995234
Change-Id: I0a9da7673616e935b6653ed13ea041bb0c07afc8
This commit is contained in:
hardikj
2018-07-25 18:50:42 +05:30
committed by Dougal Matthews
parent e3f6213341
commit 094526322f
5 changed files with 92 additions and 24 deletions

View File

@@ -25,7 +25,22 @@ class Workbook(base.Resource):
class WorkbookManager(base.ResourceManager): class WorkbookManager(base.ResourceManager):
resource_class = Workbook resource_class = Workbook
def create(self, definition, scope='private'): def _get_workbooks_url(self, resource=None, namespace=None, scope=None):
path = '/workbooks'
if resource:
path += '/%s' % resource
if scope and namespace:
path += '?scope=%s&namespace=%s' % (scope, namespace)
elif scope:
path += '?scope=%s' % scope
elif namespace:
path += '?namespace=%s' % namespace
return path
def create(self, definition, namespace='', scope='private'):
self._ensure_not_empty(definition=definition) self._ensure_not_empty(definition=definition)
# If the specified definition is actually a file, read in the # If the specified definition is actually a file, read in the
@@ -34,7 +49,7 @@ class WorkbookManager(base.ResourceManager):
try: try:
resp = self.http_client.post( resp = self.http_client.post(
'/workbooks?scope=%s' % scope, self._get_workbooks_url(None, namespace, scope),
definition, definition,
headers={'content-type': 'text/plain'} headers={'content-type': 'text/plain'}
) )
@@ -46,7 +61,7 @@ class WorkbookManager(base.ResourceManager):
return self.resource_class(self, base.extract_json(resp, None)) return self.resource_class(self, base.extract_json(resp, None))
def update(self, definition, scope='private'): def update(self, definition, namespace='', scope='private'):
self._ensure_not_empty(definition=definition) self._ensure_not_empty(definition=definition)
# If the specified definition is actually a file, read in the # If the specified definition is actually a file, read in the
@@ -55,7 +70,7 @@ class WorkbookManager(base.ResourceManager):
try: try:
resp = self.http_client.put( resp = self.http_client.put(
'/workbooks?scope=%s' % scope, self._get_workbooks_url(None, namespace, scope),
definition, definition,
headers={'content-type': 'text/plain'} headers={'content-type': 'text/plain'}
) )
@@ -67,18 +82,23 @@ class WorkbookManager(base.ResourceManager):
return self.resource_class(self, base.extract_json(resp, None)) return self.resource_class(self, base.extract_json(resp, None))
def list(self): def list(self, namespace=''):
return self._list('/workbooks', response_key='workbooks') return self._list(
self._get_workbooks_url(None, namespace),
response_key='workbooks'
)
def get(self, name): def get(self, name, namespace=''):
self._ensure_not_empty(name=name) self._ensure_not_empty(name=name)
return self._get('/workbooks/%s' % name) return self._get(
self._get_workbooks_url(name, namespace)
)
def delete(self, name): def delete(self, name, namespace=''):
self._ensure_not_empty(name=name) self._ensure_not_empty(name=name)
self._delete('/workbooks/%s' % name) self._delete(self._get_workbooks_url(name, namespace))
def validate(self, definition): def validate(self, definition):
self._ensure_not_empty(definition=definition) self._ensure_not_empty(definition=definition)

View File

@@ -24,6 +24,7 @@ from mistralclient import utils
def format(workbook=None): def format(workbook=None):
columns = ( columns = (
'Name', 'Name',
'Namespace',
'Tags', 'Tags',
'Scope', 'Scope',
'Created at', 'Created at',
@@ -33,6 +34,7 @@ def format(workbook=None):
if workbook: if workbook:
data = ( data = (
workbook.name, workbook.name,
workbook.namespace,
base.wrap(', '.join(workbook.tags or '')) or '<none>', base.wrap(', '.join(workbook.tags or '')) or '<none>',
workbook.scope, workbook.scope,
workbook.created_at, workbook.created_at,
@@ -66,16 +68,23 @@ class Get(command.ShowOne):
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(Get, self).get_parser(prog_name) parser = super(Get, self).get_parser(prog_name)
parser.add_argument('workbook', help='Workbook name')
parser.add_argument( parser.add_argument(
'workbook', '--namespace',
help='Workbook name' nargs='?',
default='',
help="Namespace to get the workbook from."
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
mistral_client = self.app.client_manager.workflow_engine mistral_client = self.app.client_manager.workflow_engine
workbook = mistral_client.workbooks.get(parsed_args.workbook) workbook = mistral_client.workbooks.get(
parsed_args.workbook,
parsed_args.namespace
)
return format(workbook) return format(workbook)
@@ -97,6 +106,13 @@ class Create(command.ShowOne):
help='With this flag workbook will be marked as "public".' help='With this flag workbook will be marked as "public".'
) )
parser.add_argument(
'--namespace',
nargs='?',
default='',
help="Namespace to create the workbook within."
)
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
@@ -105,6 +121,7 @@ class Create(command.ShowOne):
mistral_client = self.app.client_manager.workflow_engine mistral_client = self.app.client_manager.workflow_engine
workbook = mistral_client.workbooks.create( workbook = mistral_client.workbooks.create(
parsed_args.definition.read(), parsed_args.definition.read(),
namespace=parsed_args.namespace,
scope=scope scope=scope
) )
@@ -118,13 +135,20 @@ class Delete(command.Command):
parser = super(Delete, self).get_parser(prog_name) parser = super(Delete, self).get_parser(prog_name)
parser.add_argument('workbook', nargs='+', help='Name of workbook(s).') parser.add_argument('workbook', nargs='+', help='Name of workbook(s).')
parser.add_argument(
'--namespace',
nargs='?',
default=None,
help="Namespace to delete the workbook(s) from."
)
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
mistral_client = self.app.client_manager.workflow_engine mistral_client = self.app.client_manager.workflow_engine
utils.do_action_on_many( utils.do_action_on_many(
lambda s: mistral_client.workbooks.delete(s), lambda s: mistral_client.workbooks.delete(s,
parsed_args.namespace),
parsed_args.workbook, parsed_args.workbook,
"Request to delete workbook %s has been accepted.", "Request to delete workbook %s has been accepted.",
"Unable to delete the specified workbook(s)." "Unable to delete the specified workbook(s)."
@@ -142,6 +166,12 @@ class Update(command.ShowOne):
type=argparse.FileType('r'), type=argparse.FileType('r'),
help='Workbook definition file' help='Workbook definition file'
) )
parser.add_argument(
'--namespace',
nargs='?',
default=None,
help="Namespace to update the workbook in."
)
parser.add_argument( parser.add_argument(
'--public', '--public',
action='store_true', action='store_true',
@@ -156,6 +186,7 @@ class Update(command.ShowOne):
mistral_client = self.app.client_manager.workflow_engine mistral_client = self.app.client_manager.workflow_engine
workbook = mistral_client.workbooks.update( workbook = mistral_client.workbooks.update(
parsed_args.definition.read(), parsed_args.definition.read(),
namespace=parsed_args.namespace,
scope=scope scope=scope
) )

View File

@@ -111,12 +111,21 @@ class MistralClientTestBase(base.MistralCLIAuth, base.MistralCLIAltAuth):
else: else:
return self.mistral_alt_user(cmd, params) return self.mistral_alt_user(cmd, params)
def workbook_create(self, wb_def, admin=True, scope='private'): def workbook_create(self, wb_def, namespace='', admin=True,
scope='private'):
params = '{0}'.format(wb_def) params = '{0}'.format(wb_def)
namespace_params = ''
if namespace:
namespace_params += ' --namespace {}'.format(namespace)
if scope == 'public': if scope == 'public':
params += ' --public' params += ' --public'
params += namespace_params
wb = self.mistral_cli( wb = self.mistral_cli(
admin, admin,
'workbook-create', 'workbook-create',
@@ -125,11 +134,13 @@ class MistralClientTestBase(base.MistralCLIAuth, base.MistralCLIAltAuth):
wb_name = self.get_field_value(wb, "Name") wb_name = self.get_field_value(wb, "Name")
wb_delete_params = wb_name + namespace_params
self.addCleanup( self.addCleanup(
self.mistral_cli, self.mistral_cli,
admin, admin,
'workbook-delete', 'workbook-delete',
params=wb_name params=wb_delete_params
) )
self.addCleanup( self.addCleanup(

View File

@@ -22,6 +22,7 @@ from mistralclient.tests.unit import base
WORKBOOK_DICT = { WORKBOOK_DICT = {
'name': 'a', 'name': 'a',
'namespace': '',
'tags': ['a', 'b'], 'tags': ['a', 'b'],
'scope': 'private', 'scope': 'private',
'created_at': '1', 'created_at': '1',
@@ -55,7 +56,7 @@ class TestCLIWorkbooksV2(base.BaseCommandTest):
result = self.call(workbook_cmd.Create, app_args=['wb.yaml']) result = self.call(workbook_cmd.Create, app_args=['wb.yaml'])
self.assertEqual(('a', 'a, b', 'private', '1', '1'), result[1]) self.assertEqual(('a', '', 'a, b', 'private', '1', '1'), result[1])
@mock.patch('argparse.open', create=True) @mock.patch('argparse.open', create=True)
def test_create_public(self, mock_open): def test_create_public(self, mock_open):
@@ -69,7 +70,7 @@ class TestCLIWorkbooksV2(base.BaseCommandTest):
app_args=['wb.yaml', '--public'] app_args=['wb.yaml', '--public']
) )
self.assertEqual(('a', 'a, b', 'public', '1', '1'), result[1]) self.assertEqual(('a', '', 'a, b', 'public', '1', '1'), result[1])
self.assertEqual( self.assertEqual(
'public', 'public',
@@ -82,7 +83,7 @@ class TestCLIWorkbooksV2(base.BaseCommandTest):
result = self.call(workbook_cmd.Update, app_args=['definition']) result = self.call(workbook_cmd.Update, app_args=['definition'])
self.assertEqual(('a', 'a, b', 'private', '1', '1'), result[1]) self.assertEqual(('a', '', 'a, b', 'private', '1', '1'), result[1])
@mock.patch('argparse.open', create=True) @mock.patch('argparse.open', create=True)
def test_update_public(self, mock_open): def test_update_public(self, mock_open):
@@ -96,7 +97,7 @@ class TestCLIWorkbooksV2(base.BaseCommandTest):
app_args=['definition', '--public'] app_args=['definition', '--public']
) )
self.assertEqual(('a', 'a, b', 'public', '1', '1'), result[1]) self.assertEqual(('a', '', 'a, b', 'public', '1', '1'), result[1])
self.assertEqual( self.assertEqual(
'public', 'public',
@@ -108,26 +109,26 @@ class TestCLIWorkbooksV2(base.BaseCommandTest):
result = self.call(workbook_cmd.List) result = self.call(workbook_cmd.List)
self.assertEqual([('a', 'a, b', 'private', '1', '1')], result[1]) self.assertEqual([('a', '', 'a, b', 'private', '1', '1')], result[1])
def test_get(self): def test_get(self):
self.client.workbooks.get.return_value = WORKBOOK self.client.workbooks.get.return_value = WORKBOOK
result = self.call(workbook_cmd.Get, app_args=['name']) result = self.call(workbook_cmd.Get, app_args=['name'])
self.assertEqual(('a', 'a, b', 'private', '1', '1'), result[1]) self.assertEqual(('a', '', 'a, b', 'private', '1', '1'), result[1])
def test_delete(self): def test_delete(self):
self.call(workbook_cmd.Delete, app_args=['name']) self.call(workbook_cmd.Delete, app_args=['name'])
self.client.workbooks.delete.assert_called_once_with('name') self.client.workbooks.delete.assert_called_once_with('name', None)
def test_delete_with_multi_names(self): def test_delete_with_multi_names(self):
self.call(workbook_cmd.Delete, app_args=['name1', 'name2']) self.call(workbook_cmd.Delete, app_args=['name1', 'name2'])
self.assertEqual(2, self.client.workbooks.delete.call_count) self.assertEqual(2, self.client.workbooks.delete.call_count)
self.assertEqual( self.assertEqual(
[mock.call('name1'), mock.call('name2')], [mock.call('name1', None), mock.call('name2', None)],
self.client.workbooks.delete.call_args_list self.client.workbooks.delete.call_args_list
) )

View File

@@ -0,0 +1,5 @@
---
features:
- |
Add namespace parameter to workbook commands. Namespace parameter allows
to create multiple workbooks with same name under different namespaces.