diff --git a/st2api/st2api/controllers/v1/execution_views.py b/st2api/st2api/controllers/v1/execution_views.py index f4240b94ab..0955f5b4ba 100644 --- a/st2api/st2api/controllers/v1/execution_views.py +++ b/st2api/st2api/controllers/v1/execution_views.py @@ -30,6 +30,7 @@ # tab of st2web. SUPPORTED_FILTERS = { "action": "action.ref", + "pack": "action.pack", "status": "status", "liveaction": "liveaction.id", "parent": "parent", diff --git a/st2api/tests/unit/controllers/v1/test_executions_filters.py b/st2api/tests/unit/controllers/v1/test_executions_filters.py index af451ca519..cd2bba137b 100644 --- a/st2api/tests/unit/controllers/v1/test_executions_filters.py +++ b/st2api/tests/unit/controllers/v1/test_executions_filters.py @@ -196,6 +196,24 @@ def test_query(self): ids = [item["id"] for item in response.json] self.assertListEqual(sorted(ids), sorted(refs)) + def test_query_by_pack(self): + # All test fixtures use the "executions" pack, so filtering by it should + # return all executions (both chain and local types). + all_refs = list(self.refs.keys()) + response = self.app.get("/v1/executions?pack=executions&limit=-1") + self.assertEqual(response.status_int, 200) + self.assertIsInstance(response.json, list) + self.assertGreater(len(response.json), 0) + self.assertEqual(response.headers["X-Total-Count"], str(len(all_refs))) + + def test_query_by_pack_no_match(self): + # Filtering by a pack that has no executions should return an empty list. + response = self.app.get("/v1/executions?pack=nonexistent_pack") + self.assertEqual(response.status_int, 200) + self.assertIsInstance(response.json, list) + self.assertEqual(len(response.json), 0) + self.assertEqual(response.headers["X-Total-Count"], "0") + def test_filters(self): excludes = [ "parent", diff --git a/st2client/st2client/commands/action.py b/st2client/st2client/commands/action.py index 48964746a5..afb519398f 100644 --- a/st2client/st2client/commands/action.py +++ b/st2client/st2client/commands/action.py @@ -1456,6 +1456,10 @@ def __init__(self, resource, *args, **kwargs): # Filter options self.group.add_argument("--action", help="Action reference to filter the list.") + self.group.add_argument( + "--pack", + help="Only return executions from the provided pack.", + ) self.group.add_argument( "--status", help=( @@ -1523,6 +1527,8 @@ def run(self, args, **kwargs): # Filtering options if args.action: kwargs["action"] = args.action + if args.pack: + kwargs["pack"] = args.pack if args.status: kwargs["status"] = args.status if args.user: diff --git a/st2common/st2common/models/db/execution.py b/st2common/st2common/models/db/execution.py index 0de35a5c31..389a0df75b 100644 --- a/st2common/st2common/models/db/execution.py +++ b/st2common/st2common/models/db/execution.py @@ -83,6 +83,7 @@ class ActionExecutionDB(stormbase.StormFoundationDB): "indexes": [ {"fields": ["rule.ref"]}, {"fields": ["action.ref"]}, + {"fields": ["action.pack"]}, {"fields": ["liveaction.id"]}, {"fields": ["start_timestamp"]}, {"fields": ["end_timestamp"]}, diff --git a/st2common/st2common/openapi.yaml.j2 b/st2common/st2common/openapi.yaml.j2 index 6b10362640..0ece7ceb9f 100644 --- a/st2common/st2common/openapi.yaml.j2 +++ b/st2common/st2common/openapi.yaml.j2 @@ -1000,6 +1000,10 @@ paths: in: query description: Action ref filter type: string + - name: pack + in: query + description: Pack name filter + type: string - name: runner in: query description: Runner filter diff --git a/st2tests/st2tests/fixtures/history_views/filters.yaml b/st2tests/st2tests/fixtures/history_views/filters.yaml index 37d8e521de..6049298d96 100644 --- a/st2tests/st2tests/fixtures/history_views/filters.yaml +++ b/st2tests/st2tests/fixtures/history_views/filters.yaml @@ -5,6 +5,8 @@ default: - executions.chain # null is not a valid value for action - null + pack: + - executions rule: - st2.person.joe # null is a valid value for rule