Add API to validate ad-hoc action
Add an API that gets an ad-hoc action DSL and validates it. This is done in the same way workflows are validated today. Change-Id: Ibbb949ef38befae1ef83a2a56cda4c817ceb41d4 Implements: blueprint validate-ad-hoc-action-api
This commit is contained in:
parent
2eb1e1e603
commit
594b3e27f9
@ -190,7 +190,7 @@ There are three service groups according to Mistral architecture currently, name
|
||||
Validation
|
||||
----------
|
||||
|
||||
Validation endpoints allow to check correctness of workbook and workflow DSL without having to upload them into Mistral.
|
||||
Validation endpoints allow to check correctness of workbook, workflow and ad-hoc action DSL without having to upload them into Mistral.
|
||||
|
||||
**POST /v2/workbooks/validation**
|
||||
Validate workbook content (DSL grammar and semantics).
|
||||
@ -198,4 +198,7 @@ Validation endpoints allow to check correctness of workbook and workflow DSL wit
|
||||
**POST /v2/workflows/validation**
|
||||
Validate workflow content (DSL grammar and semantics).
|
||||
|
||||
These endpoints expect workbook or workflow text (DSL) correspondingly in a request body.
|
||||
**POST /v2/actions/validation**
|
||||
Validate ad-hoc action content (DSL grammar and semantics).
|
||||
|
||||
These endpoints expect workbook, workflow or ad-hoc action text (DSL) correspondingly in a request body.
|
||||
|
@ -22,11 +22,13 @@ import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from mistral.api.controllers import resource
|
||||
from mistral.api.controllers.v2 import types
|
||||
from mistral.api.controllers.v2 import validation
|
||||
from mistral.api.hooks import content_type as ct_hook
|
||||
from mistral.db.v2 import api as db_api
|
||||
from mistral import exceptions as exc
|
||||
from mistral.services import actions
|
||||
from mistral.utils import rest_utils
|
||||
from mistral.workbook import parser as spec_parser
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
SCOPE_TYPES = wtypes.Enum(str, 'private', 'public')
|
||||
@ -93,6 +95,9 @@ class ActionsController(rest.RestController, hooks.HookController):
|
||||
# delete ContentTypeHook.
|
||||
__hooks__ = [ct_hook.ContentTypeHook("application/json", ['POST', 'PUT'])]
|
||||
|
||||
validate = validation.SpecValidationController(
|
||||
spec_parser.get_action_list_spec_from_yaml)
|
||||
|
||||
@rest_utils.wrap_wsme_controller_exception
|
||||
@wsme_pecan.wsexpose(Action, wtypes.text)
|
||||
def get(self, name):
|
||||
|
@ -36,6 +36,35 @@ my_action:
|
||||
output: "{$.str1}{$.str2}"
|
||||
"""
|
||||
|
||||
ACTION_DEFINITION_INVALID_NO_BASE = """
|
||||
---
|
||||
version: '2.0'
|
||||
|
||||
my_action:
|
||||
description: My super cool action.
|
||||
tags: ['test', 'v2']
|
||||
|
||||
base-input:
|
||||
output: "{$.str1}{$.str2}"
|
||||
"""
|
||||
|
||||
ACTION_DEFINITION_INVALID_YAQL = """
|
||||
---
|
||||
version: '2.0'
|
||||
|
||||
my_action:
|
||||
description: My super cool action.
|
||||
tags: ['test', 'v2']
|
||||
base: std.echo
|
||||
base-input:
|
||||
output: <% $. %>
|
||||
"""
|
||||
|
||||
ACTION_DSL_PARSE_EXCEPTION = """
|
||||
---
|
||||
%
|
||||
"""
|
||||
|
||||
SYSTEM_ACTION_DEFINITION = """
|
||||
---
|
||||
version: '2.0'
|
||||
@ -339,3 +368,62 @@ class TestActionsController(base.APITest):
|
||||
self.assertEqual(400, resp.status_int)
|
||||
|
||||
self.assertIn("Unknown sort direction", resp.body.decode())
|
||||
|
||||
def test_validate(self):
|
||||
resp = self.app.post(
|
||||
'/v2/actions/validate',
|
||||
ACTION_DEFINITION,
|
||||
headers={'Content-Type': 'text/plain'}
|
||||
)
|
||||
|
||||
self.assertEqual(200, resp.status_int)
|
||||
self.assertTrue(resp.json['valid'])
|
||||
|
||||
def test_validate_invalid_model_exception(self):
|
||||
resp = self.app.post(
|
||||
'/v2/actions/validate',
|
||||
ACTION_DEFINITION_INVALID_NO_BASE,
|
||||
headers={'Content-Type': 'text/plain'},
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
self.assertEqual(200, resp.status_int)
|
||||
self.assertFalse(resp.json['valid'])
|
||||
self.assertIn("Invalid DSL", resp.json['error'])
|
||||
|
||||
def test_validate_dsl_parse_exception(self):
|
||||
resp = self.app.post(
|
||||
'/v2/actions/validate',
|
||||
ACTION_DSL_PARSE_EXCEPTION,
|
||||
headers={'Content-Type': 'text/plain'},
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
self.assertEqual(200, resp.status_int)
|
||||
self.assertFalse(resp.json['valid'])
|
||||
self.assertIn("Definition could not be parsed", resp.json['error'])
|
||||
|
||||
def test_validate_yaql_parse_exception(self):
|
||||
resp = self.app.post(
|
||||
'/v2/actions/validate',
|
||||
ACTION_DEFINITION_INVALID_YAQL,
|
||||
headers={'Content-Type': 'text/plain'},
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
self.assertEqual(200, resp.status_int)
|
||||
self.assertFalse(resp.json['valid'])
|
||||
self.assertIn("unexpected end of statement",
|
||||
resp.json['error'])
|
||||
|
||||
def test_validate_empty(self):
|
||||
resp = self.app.post(
|
||||
'/v2/actions/validate',
|
||||
'',
|
||||
headers={'Content-Type': 'text/plain'},
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
self.assertEqual(200, resp.status_int)
|
||||
self.assertFalse(resp.json['valid'])
|
||||
self.assertIn("Invalid DSL", resp.json['error'])
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- New API for validating ad-hoc actions was added.
|
Loading…
Reference in New Issue
Block a user