Skip to content

Commit

Permalink
Merge pull request #2829 from lakshmi-kannan/STORM-2236_chatops_impro…
Browse files Browse the repository at this point in the history
…vements

Chatops related improvements
  • Loading branch information
lakshmi-kannan authored Jul 31, 2016
2 parents ab76c1f + 201d46a commit 569c5ac
Show file tree
Hide file tree
Showing 13 changed files with 382 additions and 19 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ In development
``False``) and the second one is the result. Previously, user could only cause action to fail by
throwing an exception or exiting which didn't allow for a result to be returned. With this new
approach, user can now also return an optional result with a failure. (new feature)
* Include a chatops alias sample in ``examples`` pack that shows how to use ``format`` option to
display chatops messages in custom formatted way. (improvement)
* Fix ``Internal Server Error`` when an undefined jinja variable is used in action alias ack field.
We now send a http status code ``201`` but also explicitly say we couldn't render the ``ack``
field. The ``ack`` is anyways a nice-to-have message which is not critical. Previously, we still
kicked off the execution but sent out ``Internal Server Error`` which might confuse the user
whether execution was kicked off or not. (bug-fix)
* Include testing for chatops ``format_execution_result`` python action. The tests cover various
action types. (improvement)
* Include a field ``elapsed_seconds`` in execution API response for GET calls. The clients using
the API can now use ``elapsed_seconds`` without having to repeat computation. (improvement)

1.5.1 - July 13, 2016
---------------------
Expand Down
Empty file.
54 changes: 54 additions & 0 deletions contrib/chatops/tests/fixtures/http_execution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"action": {
"ref": "core.http"
},
"context": {
"user": "st2admin"
},
"end_timestamp": "2016-07-28T00:46:42.062470Z",
"id": "579955f055fc8c2d33ac03e3",
"liveaction": {
"action": "core.http",
"action_is_workflow": false,
"callback": {},
"id": "579955f055fc8c2d33ac03e2",
"parameters": {
"url": "https://httpbin.org/"
},
"runner_info": {
"hostname": "st2test",
"pid": 11330
}
},
"parameters": {
"url": "https://httpbin.org/"
},
"result": {
"body": "BLAH BLAH BLAH",
"headers": {
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Origin": "*",
"Connection": "keep-alive",
"Content-Length": "12150",
"Content-Type": "text/html; charset=utf-8",
"Date": "Thu, 28 Jul 2016 00:51:25 GMT",
"Server": "nginx"
},
"parsed": false,
"status_code": 200
},
"web_url": "https://localhost.localdomain/#/history/579955f055fc8c2d33ac03e3/general",
"start_timestamp": "2016-07-28T00:46:40.822066Z",
"status": "succeeded",
"runner": {
"enabled": true,
"id": "54c6bb640640fd5211edef0b",
"name": "http-request",
"runner_module": "st2actions.runners.httprunner",
"runner_parameters": {
"url": {
"type": "string"
}
}
}
}
47 changes: 47 additions & 0 deletions contrib/chatops/tests/fixtures/local_cmd_execution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"action": {
"ref": "core.local"
},
"context": {
"user": "st2admin"
},
"end_timestamp": "2016-07-28T00:30:39.555229Z",
"id": "5799522f55fc8c2d33ac03e0",
"liveaction": {
"action": "core.local",
"action_is_workflow": false,
"callback": {},
"id": "5799522f55fc8c2d33ac03df",
"parameters": {
"cmd": "date"
},
"runner_info": {
"hostname": "st2test",
"pid": 11327
}
},
"parameters": {
"cmd": "date"
},
"result": {
"failed": false,
"return_code": 0,
"stderr": "",
"stdout": "Thu Jul 28 00:30:39 UTC 2016",
"succeeded": true
},
"start_timestamp": "2016-07-28T00:30:39.268566Z",
"status": "succeeded",
"web_url": "https://localhost.localdomain/#/history/57967f9355fc8c19a96d9e4f/general",
"runner": {
"enabled": true,
"id": "54c6bb640640fd5211edef0b",
"name": "local-shell-cmd",
"runner_module": "st2actions.runners.localrunner",
"runner_parameters": {
"cmd": {
"type": "string"
}
}
}
}
44 changes: 44 additions & 0 deletions contrib/chatops/tests/fixtures/python_action_execution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"action": {
"ref": "examples.isprime"
},
"context": {
"user": "st2admin"
},
"end_timestamp": "2016-07-28T00:51:55.400941Z",
"id": "5799572a55fc8c2d33ac03ec",
"liveaction": {
"action": "examples.isprime",
"action_is_workflow": false,
"callback": {},
"id": "5799572a55fc8c2d33ac03eb",
"parameters": {
"value": 7
},
"runner_info": {
"hostname": "st2test",
"pid": 11327
}
},
"parameters": {
"value": 7
},
"result": {
"exit_code": 0,
"result": true,
"stderr": "st2.actions.python.PrimeCheckerAction: DEBUG value=7\n",
"stdout": ""
},
"start_timestamp": "2016-07-28T00:51:54.005500Z",
"status": "succeeded",
"web_url": "https://localhost.localdomain/#/history/5799572a55fc8c2d33ac03ec/general",
"runner": {
"enabled": true,
"id": "54c6bb640640fd5211edef0b",
"name": "python-script",
"runner_module": "st2actions.runners.pythonrunner",
"runner_parameters": {

}
}
}
65 changes: 65 additions & 0 deletions contrib/chatops/tests/fixtures/remote_cmd_execution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"action": {
"ref": "core.remote"
},
"context": {
"user": "st2admin"
},
"end_timestamp": "2016-07-25T21:07:33.957268Z",
"id": "57967f9355fc8c19a96d9e4f",
"liveaction": {
"action": "core.remote",
"action_is_workflow": true,
"callback": {},
"id": "57967f9355fc8c19a96d9e4e",
"notify": {
"on-complete": {
"data": {
"source_channel": "chatops_ci",
"user": "lakstorm"
},
"routes": [
"hubot"
]
}
},
"parameters": {
"cmd": "date",
"hosts": "localhost"
},
"runner_info": {
"hostname": "st2test",
"pid": 5686
}
},
"parameters": {
"cmd": "date",
"hosts": "localhost"
},
"web_url": "https://localhost.localdomain/#/history/57967f9355fc8c19a96d9e4f/general",
"result": {
"localhost": {
"failed": false,
"return_code": 0,
"stderr": "",
"stdout": "Mon Jul 25 21:07:32 UTC 2016",
"succeeded": true
}
},
"start_timestamp": "2016-07-25T21:07:31.900544Z",
"status": "succeeded",
"runner": {
"enabled": true,
"id": "54c6bb640640fd5211edef0b",
"name": "remote-shell-cmd",
"runner_module": "st2actions.runners.remote_command_runner",
"runner_parameters": {
"cmd": {
"type": "string"
},
"hosts": {
"type": "string"
}
}
}
}
58 changes: 58 additions & 0 deletions contrib/chatops/tests/test_format_result.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import json
import mock

from st2tests.base import BaseActionTestCase

from format_execution_result import FormatResultAction

__all__ = [
'FormatResultActionTestCase'
]


class FormatResultActionTestCase(BaseActionTestCase):
action_cls = FormatResultAction

def test_rendering_works_remote_shell_cmd(self):
remote_shell_cmd_execution_model = json.loads(
self.get_fixture_content('remote_cmd_execution.json')
)

action = self.get_action_instance()
action._get_execution = mock.MagicMock(
return_value=remote_shell_cmd_execution_model
)
self.assertTrue(action.run(execution_id='57967f9355fc8c19a96d9e4f'))

def test_rendering_local_shell_cmd(self):
local_shell_cmd_execution_model = json.loads(
self.get_fixture_content('local_cmd_execution.json')
)

action = self.get_action_instance()
action._get_execution = mock.MagicMock(
return_value=local_shell_cmd_execution_model
)
self.assertTrue(action.run(execution_id='5799522f55fc8c2d33ac03e0'))

def test_rendering_http_request(self):
http_execution_model = json.loads(
self.get_fixture_content('http_execution.json')
)

action = self.get_action_instance()
action._get_execution = mock.MagicMock(
return_value=http_execution_model
)
self.assertTrue(action.run(execution_id='579955f055fc8c2d33ac03e3'))

def test_rendering_python_action(self):
python_action_execution_model = json.loads(
self.get_fixture_content('python_action_execution.json')
)

action = self.get_action_instance()
action._get_execution = mock.MagicMock(
return_value=python_action_execution_model
)
self.assertTrue(action.run(execution_id='5799572a55fc8c2d33ac03ec'))
19 changes: 19 additions & 0 deletions contrib/examples/aliases/remote_shell_cmd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: "remote_shell_cmd"
action_ref: "core.remote"
description: "Execute a command on a remote host via SSH."
formats:
- "run {{cmd}} on {{hosts}}"
ack:
format: "Hold tight while I run command: *{{execution.parameters.cmd}}* on hosts *{{execution.parameters.hosts}}*"
result:
format: |
Ran command *{{execution.parameters.cmd}}* on *{{ execution.result | length }}* hosts.
Details are as follows:
{% for host in execution.result -%}
Host: *{{host}}*
---> stdout: {{execution.result[host].stdout}}
---> stderr: {{execution.result[host].stderr}}
{%+ endfor %}
38 changes: 25 additions & 13 deletions st2api/st2api/controllers/v1/aliasexecution.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
# limitations under the License.

import jsonschema
import pecan
from jinja2.exceptions import UndefinedError
from pecan import (abort, rest, request)
import six
from pecan import rest

from st2common import log as logging
from st2common.models.api.base import jsexpose
from st2common.exceptions.db import StackStormDBObjectNotFoundError
Expand Down Expand Up @@ -54,7 +55,7 @@ def post(self, payload):
action_alias_name = payload.name if payload else None

if not action_alias_name:
pecan.abort(http_client.BAD_REQUEST, 'Alias execution "name" is required')
abort(http_client.BAD_REQUEST, 'Alias execution "name" is required')

format_str = payload.format or ''
command = payload.command or ''
Expand All @@ -66,12 +67,12 @@ def post(self, payload):

if not action_alias_db:
msg = 'Unable to identify action alias with name "%s".' % (action_alias_name)
pecan.abort(http_client.NOT_FOUND, msg)
abort(http_client.NOT_FOUND, msg)
return

if not action_alias_db.enabled:
msg = 'Action alias with name "%s" is disabled.' % (action_alias_name)
pecan.abort(http_client.BAD_REQUEST, msg)
abort(http_client.BAD_REQUEST, msg)
return

execution_parameters = extract_parameters_for_action_alias_db(
Expand All @@ -98,13 +99,24 @@ def post(self, payload):
}

if action_alias_db.ack:
if 'format' in action_alias_db.ack:
try:
if 'format' in action_alias_db.ack:
result.update({
'message': render({'alias': action_alias_db.ack['format']}, result)['alias']
})
except UndefinedError as e:
result.update({
'message': render({'alias': action_alias_db.ack['format']}, result)['alias']
'message': 'Cannot render "format" in field "ack" for alias. ' + e.message
})
if 'extra' in action_alias_db.ack:

try:
if 'extra' in action_alias_db.ack:
result.update({
'extra': render(action_alias_db.ack['extra'], result)
})
except UndefinedError as e:
result.update({
'extra': render(action_alias_db.ack['extra'], result)
'extra': 'Cannot render "extra" in field "ack" for alias. ' + e.message
})

return result
Expand Down Expand Up @@ -133,7 +145,7 @@ def _schedule_execution(self, action_alias_db, params, notify, context):
if not action_db:
raise StackStormDBObjectNotFoundError('Action with ref "%s" not found ' % (action_ref))

assert_request_user_has_resource_db_permission(request=pecan.request, resource_db=action_db,
assert_request_user_has_resource_db_permission(request=request, resource_db=action_db,
permission_type=PermissionType.ACTION_EXECUTE)

try:
Expand All @@ -152,10 +164,10 @@ def _schedule_execution(self, action_alias_db, params, notify, context):
return ActionExecutionAPI.from_model(action_execution_db)
except ValueError as e:
LOG.exception('Unable to execute action.')
pecan.abort(http_client.BAD_REQUEST, str(e))
abort(http_client.BAD_REQUEST, str(e))
except jsonschema.ValidationError as e:
LOG.exception('Unable to execute action. Parameter validation failed.')
pecan.abort(http_client.BAD_REQUEST, str(e))
abort(http_client.BAD_REQUEST, str(e))
except Exception as e:
LOG.exception('Unable to execute action. Unexpected error encountered.')
pecan.abort(http_client.INTERNAL_SERVER_ERROR, str(e))
abort(http_client.INTERNAL_SERVER_ERROR, str(e))
Loading

0 comments on commit 569c5ac

Please sign in to comment.