Add workbook and workflow validate commands
Add workbook-validate and workflow-validate commands to validate workbook and workflow definition respectively. The commands print the error if validation fails else returns command prompt. Change-Id: I25b220a2a9abd720f24ee6b23ce37ee977845793 Implements: blueprint api-validate-dsl
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
# Copyright 2014 - Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -62,3 +63,17 @@ class WorkbookManager(base.ResourceManager):
|
|||||||
self._ensure_not_empty(name=name)
|
self._ensure_not_empty(name=name)
|
||||||
|
|
||||||
self._delete('/workbooks/%s' % name)
|
self._delete('/workbooks/%s' % name)
|
||||||
|
|
||||||
|
def validate(self, definition):
|
||||||
|
self._ensure_not_empty(definition=definition)
|
||||||
|
|
||||||
|
resp = self.client.http_client.post(
|
||||||
|
'/workbooks/validate',
|
||||||
|
definition,
|
||||||
|
headers={'content-type': 'text/plain'}
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 200:
|
||||||
|
self._raise_api_exception(resp)
|
||||||
|
|
||||||
|
return base.extract_json(resp, None)
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
# Copyright 2014 - Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -64,3 +65,17 @@ class WorkflowManager(base.ResourceManager):
|
|||||||
self._ensure_not_empty(name=name)
|
self._ensure_not_empty(name=name)
|
||||||
|
|
||||||
self._delete('/workflows/%s' % name)
|
self._delete('/workflows/%s' % name)
|
||||||
|
|
||||||
|
def validate(self, definition):
|
||||||
|
self._ensure_not_empty(definition=definition)
|
||||||
|
|
||||||
|
resp = self.client.http_client.post(
|
||||||
|
'/workflows/validate',
|
||||||
|
definition,
|
||||||
|
headers={'content-type': 'text/plain'}
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 200:
|
||||||
|
self._raise_api_exception(resp)
|
||||||
|
|
||||||
|
return base.extract_json(resp, None)
|
||||||
|
@@ -1,18 +1,17 @@
|
|||||||
# Copyright 2014 - Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
# All Rights Reserved
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# you may not use this file except in compliance with the License.
|
||||||
# a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# License for the specific language governing permissions and limitations
|
# See the License for the specific language governing permissions and
|
||||||
# under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
@@ -22,6 +21,8 @@ from cliff import show
|
|||||||
|
|
||||||
from mistralclient.api.v2 import workbooks
|
from mistralclient.api.v2 import workbooks
|
||||||
from mistralclient.commands.v2 import base
|
from mistralclient.commands.v2 import base
|
||||||
|
from mistralclient import exceptions as exc
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -153,3 +154,28 @@ class GetDefinition(command.Command):
|
|||||||
parsed_args.name).definition
|
parsed_args.name).definition
|
||||||
|
|
||||||
self.app.stdout.write(definition or "\n")
|
self.app.stdout.write(definition or "\n")
|
||||||
|
|
||||||
|
|
||||||
|
class Validate(show.ShowOne):
|
||||||
|
"""Validate workbook."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Validate, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'definition',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
help='Workbook definition file'
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
result = workbooks.WorkbookManager(self.app.client).validate(
|
||||||
|
parsed_args.definition.read())
|
||||||
|
|
||||||
|
if not result.get('valid', None):
|
||||||
|
raise exc.MistralClientException(
|
||||||
|
result.get('error', 'Unknown exception.'))
|
||||||
|
|
||||||
|
return tuple(), tuple()
|
||||||
|
@@ -1,18 +1,17 @@
|
|||||||
# Copyright 2014 - Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
# All Rights Reserved
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# you may not use this file except in compliance with the License.
|
||||||
# a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# License for the specific language governing permissions and limitations
|
# See the License for the specific language governing permissions and
|
||||||
# under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
@@ -22,6 +21,8 @@ from cliff import show
|
|||||||
|
|
||||||
from mistralclient.api.v2 import workflows
|
from mistralclient.api.v2 import workflows
|
||||||
from mistralclient.commands.v2 import base
|
from mistralclient.commands.v2 import base
|
||||||
|
from mistralclient import exceptions as exc
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -163,4 +164,29 @@ class GetDefinition(command.Command):
|
|||||||
definition = workflows.WorkflowManager(self.app.client).get(
|
definition = workflows.WorkflowManager(self.app.client).get(
|
||||||
parsed_args.name).definition
|
parsed_args.name).definition
|
||||||
|
|
||||||
self.app.stdout.write(definition or "\n")
|
self.app.stdout.write(definition or "\n")
|
||||||
|
|
||||||
|
|
||||||
|
class Validate(show.ShowOne):
|
||||||
|
"""Validate workflow."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Validate, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'definition',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
help='Workflow definition file'
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
result = workflows.WorkflowManager(self.app.client).validate(
|
||||||
|
parsed_args.definition.read())
|
||||||
|
|
||||||
|
if not result.get('valid', None):
|
||||||
|
raise exc.MistralClientException(
|
||||||
|
result.get('error', 'Unknown exception.'))
|
||||||
|
|
||||||
|
return tuple(), tuple()
|
||||||
|
@@ -1,18 +1,16 @@
|
|||||||
# Copyright 2015 StackStorm, Inc.
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
# All Rights Reserved
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# you may not use this file except in compliance with the License.
|
||||||
# a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# License for the specific language governing permissions and limitations
|
# See the License for the specific language governing permissions and
|
||||||
# under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Command-line interface to the Mistral APIs
|
Command-line interface to the Mistral APIs
|
||||||
@@ -247,6 +245,7 @@ class MistralShell(app.App):
|
|||||||
'workbook-update': mistralclient.commands.v2.workbooks.Update,
|
'workbook-update': mistralclient.commands.v2.workbooks.Update,
|
||||||
'workbook-get-definition':
|
'workbook-get-definition':
|
||||||
mistralclient.commands.v2.workbooks.GetDefinition,
|
mistralclient.commands.v2.workbooks.GetDefinition,
|
||||||
|
'workbook-validate': mistralclient.commands.v2.workbooks.Validate,
|
||||||
'workflow-list': mistralclient.commands.v2.workflows.List,
|
'workflow-list': mistralclient.commands.v2.workflows.List,
|
||||||
'workflow-get': mistralclient.commands.v2.workflows.Get,
|
'workflow-get': mistralclient.commands.v2.workflows.Get,
|
||||||
'workflow-create': mistralclient.commands.v2.workflows.Create,
|
'workflow-create': mistralclient.commands.v2.workflows.Create,
|
||||||
@@ -254,6 +253,7 @@ class MistralShell(app.App):
|
|||||||
'workflow-update': mistralclient.commands.v2.workflows.Update,
|
'workflow-update': mistralclient.commands.v2.workflows.Update,
|
||||||
'workflow-get-definition':
|
'workflow-get-definition':
|
||||||
mistralclient.commands.v2.workflows.GetDefinition,
|
mistralclient.commands.v2.workflows.GetDefinition,
|
||||||
|
'workflow-validate': mistralclient.commands.v2.workflows.Validate,
|
||||||
'environment-create':
|
'environment-create':
|
||||||
mistralclient.commands.v2.environments.Create,
|
mistralclient.commands.v2.environments.Create,
|
||||||
'environment-delete':
|
'environment-delete':
|
||||||
|
@@ -1,23 +1,23 @@
|
|||||||
# Copyright 2014 Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
# All Rights Reserved
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# you may not use this file except in compliance with the License.
|
||||||
# a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# License for the specific language governing permissions and limitations
|
# See the License for the specific language governing permissions and
|
||||||
# under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from mistralclient.api.v2 import workbooks
|
from mistralclient.api.v2 import workbooks
|
||||||
from mistralclient.commands.v2 import workbooks as workbook_cmd
|
from mistralclient.commands.v2 import workbooks as workbook_cmd
|
||||||
|
from mistralclient import exceptions as exc
|
||||||
from mistralclient.tests.unit import base
|
from mistralclient.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@@ -95,4 +95,26 @@ class TestCLIWorkbooksV2(base.BaseCommandTest):
|
|||||||
|
|
||||||
self.call(workbook_cmd.GetDefinition, app_args=['name'])
|
self.call(workbook_cmd.GetDefinition, app_args=['name'])
|
||||||
|
|
||||||
self.app.stdout.write.assert_called_with(WB_DEF)
|
self.app.stdout.write.assert_called_with(WB_DEF)
|
||||||
|
|
||||||
|
@mock.patch('argparse.open', create=True)
|
||||||
|
@mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.validate')
|
||||||
|
def test_validate(self, mock, mock_open):
|
||||||
|
mock.return_value = {'valid': True}
|
||||||
|
mock_open.return_value = mock.MagicMock(spec=file)
|
||||||
|
|
||||||
|
result = self.call(workbook_cmd.Validate, app_args=['wb.yaml'])
|
||||||
|
|
||||||
|
self.assertEqual(result[0], tuple())
|
||||||
|
self.assertEqual(result[1], tuple())
|
||||||
|
|
||||||
|
@mock.patch('argparse.open', create=True)
|
||||||
|
@mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.validate')
|
||||||
|
def test_validate_failed(self, mock, mock_open):
|
||||||
|
mock.return_value = {'valid': False, 'error': 'Invalid DSL...'}
|
||||||
|
mock_open.return_value = mock.MagicMock(spec=file)
|
||||||
|
|
||||||
|
self.assertRaises(exc.MistralClientException,
|
||||||
|
self.call,
|
||||||
|
workbook_cmd.Validate,
|
||||||
|
app_args=['wb.yaml'])
|
||||||
|
@@ -1,23 +1,23 @@
|
|||||||
# Copyright 2014 Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
# All Rights Reserved
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# you may not use this file except in compliance with the License.
|
||||||
# a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# License for the specific language governing permissions and limitations
|
# See the License for the specific language governing permissions and
|
||||||
# under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from mistralclient.api.v2 import workflows
|
from mistralclient.api.v2 import workflows
|
||||||
from mistralclient.commands.v2 import workflows as workflow_cmd
|
from mistralclient.commands.v2 import workflows as workflow_cmd
|
||||||
|
from mistralclient import exceptions as exc
|
||||||
from mistralclient.tests.unit import base
|
from mistralclient.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@@ -90,4 +90,26 @@ class TestCLIWorkflowsV2(base.BaseCommandTest):
|
|||||||
|
|
||||||
self.call(workflow_cmd.GetDefinition, app_args=['name'])
|
self.call(workflow_cmd.GetDefinition, app_args=['name'])
|
||||||
|
|
||||||
self.app.stdout.write.assert_called_with(WF_DEF)
|
self.app.stdout.write.assert_called_with(WF_DEF)
|
||||||
|
|
||||||
|
@mock.patch('argparse.open', create=True)
|
||||||
|
@mock.patch('mistralclient.api.v2.workflows.WorkflowManager.validate')
|
||||||
|
def test_validate(self, mock, mock_open):
|
||||||
|
mock.return_value = {'valid': True}
|
||||||
|
mock_open.return_value = mock.MagicMock(spec=file)
|
||||||
|
|
||||||
|
result = self.call(workflow_cmd.Validate, app_args=['wf.yaml'])
|
||||||
|
|
||||||
|
self.assertEqual(result[0], tuple())
|
||||||
|
self.assertEqual(result[1], tuple())
|
||||||
|
|
||||||
|
@mock.patch('argparse.open', create=True)
|
||||||
|
@mock.patch('mistralclient.api.v2.workflows.WorkflowManager.validate')
|
||||||
|
def test_validate_failed(self, mock, mock_open):
|
||||||
|
mock.return_value = {'valid': False, 'error': 'Invalid DSL...'}
|
||||||
|
mock_open.return_value = mock.MagicMock(spec=file)
|
||||||
|
|
||||||
|
self.assertRaises(exc.MistralClientException,
|
||||||
|
self.call,
|
||||||
|
workflow_cmd.Validate,
|
||||||
|
app_args=['wf.yaml'])
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
# Copyright 2014 - Mirantis, Inc.
|
# Copyright 2014 - Mirantis, Inc.
|
||||||
|
# Copyright 2015 - StackStorm, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from mistralclient.api import base as api_base
|
||||||
from mistralclient.api.v2 import workbooks
|
from mistralclient.api.v2 import workbooks
|
||||||
from mistralclient.tests.unit.v2 import base
|
from mistralclient.tests.unit.v2 import base
|
||||||
|
|
||||||
@@ -41,11 +43,25 @@ workflows:
|
|||||||
action: std.http url="http://some_url" server_id=1
|
action: std.http url="http://some_url" server_id=1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
WORKBOOK = {'definition': WB_DEF}
|
INVALID_WB_DEF = """
|
||||||
|
version: 2.0
|
||||||
|
|
||||||
|
name: wb
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
wf1:
|
||||||
|
type: direct
|
||||||
|
tasks:
|
||||||
|
task1:
|
||||||
|
action: std.http url="localhost:8989"
|
||||||
|
workflow: wf2
|
||||||
|
"""
|
||||||
|
|
||||||
|
WORKBOOK = {'definition': WB_DEF}
|
||||||
|
|
||||||
URL_TEMPLATE = '/workbooks'
|
URL_TEMPLATE = '/workbooks'
|
||||||
URL_TEMPLATE_NAME = '/workbooks/%s'
|
URL_TEMPLATE_NAME = '/workbooks/%s'
|
||||||
|
URL_TEMPLATE_VALIDATE = '/workbooks/validate'
|
||||||
|
|
||||||
|
|
||||||
class TestWorkbooksV2(base.BaseClientV2Test):
|
class TestWorkbooksV2(base.BaseClientV2Test):
|
||||||
@@ -112,3 +128,56 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
self.workbooks.delete('wb')
|
self.workbooks.delete('wb')
|
||||||
|
|
||||||
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'wb')
|
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'wb')
|
||||||
|
|
||||||
|
def test_validate(self):
|
||||||
|
mock = self.mock_http_post(status_code=200,
|
||||||
|
content={'valid': True})
|
||||||
|
|
||||||
|
result = self.workbooks.validate(WB_DEF)
|
||||||
|
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
self.assertIn('valid', result)
|
||||||
|
self.assertTrue(result['valid'])
|
||||||
|
|
||||||
|
mock.assert_called_once_with(
|
||||||
|
URL_TEMPLATE_VALIDATE,
|
||||||
|
WB_DEF,
|
||||||
|
headers={'content-type': 'text/plain'}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_validate_failed(self):
|
||||||
|
mock_result = {
|
||||||
|
"valid": False,
|
||||||
|
"error": "Task properties 'action' and 'workflow' "
|
||||||
|
"can't be specified both"
|
||||||
|
}
|
||||||
|
|
||||||
|
mock = self.mock_http_post(status_code=200, content=mock_result)
|
||||||
|
|
||||||
|
result = self.workbooks.validate(INVALID_WB_DEF)
|
||||||
|
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
self.assertIn('valid', result)
|
||||||
|
self.assertFalse(result['valid'])
|
||||||
|
self.assertIn('error', result)
|
||||||
|
self.assertIn("Task properties 'action' and 'workflow' "
|
||||||
|
"can't be specified both", result['error'])
|
||||||
|
|
||||||
|
mock.assert_called_once_with(
|
||||||
|
URL_TEMPLATE_VALIDATE,
|
||||||
|
INVALID_WB_DEF,
|
||||||
|
headers={'content-type': 'text/plain'}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_validate_api_failed(self):
|
||||||
|
mock = self.mock_http_post(status_code=500, content={})
|
||||||
|
|
||||||
|
self.assertRaises(api_base.APIException,
|
||||||
|
self.workbooks.validate,
|
||||||
|
WB_DEF)
|
||||||
|
|
||||||
|
mock.assert_called_once_with(
|
||||||
|
URL_TEMPLATE_VALIDATE,
|
||||||
|
WB_DEF,
|
||||||
|
headers={'content-type': 'text/plain'}
|
||||||
|
)
|
||||||
|
Reference in New Issue
Block a user