Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trigger type reference based filtering to the /v1/triggerinstances API endpoint #4151

Merged
merged 4 commits into from
May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Added
values - ``succeeded`` (trigger instance matched a rule and action execution was triggered
successfully), ``failed`` (trigger instance matched a rule, but it didn't result in an action
execution due to Jinja rendering failure or other exception). (improvement) #4134
* Add trigger type reference based filtering to the ``/v1/triggerinstances`` API endpoint - e.g.
``/v1/triggerinstances?trigger_type=core.st2.webhook``. (new feature) #4151

Changed
~~~~~~~
Expand Down
8 changes: 7 additions & 1 deletion st2api/st2api/controllers/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,13 @@ def _get_all(self, exclude_fields=None, include_fields=None, advanced_filters=No
if k in ['id', 'name'] and isinstance(filter_value, list):
filters[k + '__in'] = filter_value
else:
filters['__'.join(v.split('.'))] = filter_value
field_name_split = v.split('.')

# Make sure filter value is a list when using "in" filter
if field_name_split[-1] == 'in' and not isinstance(filter_value, (list, tuple)):
filter_value = [filter_value]

filters['__'.join(field_name_split)] = filter_value

if advanced_filters:
for token in advanced_filters.split(' '):
Expand Down
19 changes: 17 additions & 2 deletions st2api/st2api/controllers/v1/triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,10 @@ class TriggerInstanceController(TriggerInstanceControllerMixin, resource.Resourc
the lifecycle of TriggerInstances in the system.
"""
supported_filters = {
'trigger': 'trigger',
'timestamp_gt': 'occurrence_time.gt',
'timestamp_lt': 'occurrence_time.lt',
'status': 'status'
'status': 'status',
'trigger': 'trigger.in'
}

filter_transform_functions = {
Expand Down Expand Up @@ -393,6 +393,21 @@ def get_all(self, sort=None, offset=0, limit=None, requester_user=None, **raw_fi
Handles requests:
GET /triggerinstances/
"""
# If trigger_type filter is provided, filter based on the TriggerType via Trigger object
trigger_type_ref = raw_filters.get('trigger_type', None)

if trigger_type_ref:
# 1. Retrieve TriggerType object id which match this trigger_type ref
trigger_dbs = Trigger.query(type=trigger_type_ref,
only_fields=['ref', 'name', 'pack', 'type'])
trigger_refs = [trigger_db.ref for trigger_db in trigger_dbs]
raw_filters['trigger'] = trigger_refs

if trigger_type_ref and len(raw_filters.get('trigger', [])) == 0:
# Empty list means trigger_type_ref filter was provided, but we matched no Triggers so
# we should return back empty result
return []

trigger_instances = self._get_trigger_instances(sort=sort,
offset=offset,
limit=limit,
Expand Down
24 changes: 24 additions & 0 deletions st2api/tests/unit/controllers/v1/test_triggerinstances.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ def test_get_all_filter_by_timestamp(self):
resp = self.app.get('/v1/triggerinstances?timestamp_lt=%s' % (timestamp_middle))
self.assertEqual(len(resp.json), 1)

def test_get_all_trigger_type_ref_filtering(self):
# 1. Invalid / inexistent trigger type ref
resp = self.app.get('/v1/triggerinstances?trigger_type=foo.bar.invalid')
self.assertEqual(resp.status_int, http_client.OK)
self.assertEqual(len(resp.json), 0)

# 2. Valid trigger type ref with corresponding trigger instances
resp = self.app.get('/v1/triggerinstances?trigger_type=dummy_pack_1.st2.test.triggertype0')
self.assertEqual(resp.status_int, http_client.OK)
self.assertEqual(len(resp.json), 1)

# 3. Valid trigger type ref with no corresponding trigger instances
resp = self.app.get('/v1/triggerinstances?trigger_type=dummy_pack_1.st2.test.triggertype3')
self.assertEqual(resp.status_int, http_client.OK)
self.assertEqual(len(resp.json), 0)

def test_reemit_trigger_instance(self):
resp = self.app.get('/v1/triggerinstances')
self.assertEqual(resp.status_int, http_client.OK)
Expand Down Expand Up @@ -127,9 +143,17 @@ def _setupTriggerTypes(cls):
'payload_schema': {'tp1': None, 'tp2': None, 'tp3': None},
'parameters_schema': {'param1': {'type': 'object'}}
}
TRIGGERTYPE_3 = {
'name': 'st2.test.triggertype3',
'pack': 'dummy_pack_1',
'description': 'test trigger',
'payload_schema': {'tp1': None, 'tp2': None, 'tp3': None},
'parameters_schema': {'param1': {'type': 'object'}}
}
cls.app.post_json('/v1/triggertypes', TRIGGERTYPE_0, expect_errors=False)
cls.app.post_json('/v1/triggertypes', TRIGGERTYPE_1, expect_errors=False)
cls.app.post_json('/v1/triggertypes', TRIGGERTYPE_2, expect_errors=False)
cls.app.post_json('/v1/triggertypes', TRIGGERTYPE_3, expect_errors=False)

@classmethod
def _setupTriggers(cls):
Expand Down
4 changes: 4 additions & 0 deletions st2common/st2common/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3918,6 +3918,10 @@ paths:
description: Start timestamp greater than filter
type: string
pattern: ^\d{4}\-\d{2}\-\d{2}(\s|T)\d{2}:\d{2}:\d{2}(\.\d{3,6})?(Z|\+00|\+0000|\+00:00)$
- name: trigger_type
in: query
description: Trigger type filter
type: string
x-parameters:
- name: user
in: context
Expand Down
4 changes: 4 additions & 0 deletions st2common/st2common/openapi.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3914,6 +3914,10 @@ paths:
description: Start timestamp greater than filter
type: string
pattern: {{ ISO8601_UTC_REGEX }}
- name: trigger_type
in: query
description: Trigger type filter
type: string
x-parameters:
- name: user
in: context
Expand Down