argus-alm 0.15.2__py3-none-any.whl → 0.15.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. argus/_version.py +2 -2
  2. argus/client/generic_result.py +6 -1
  3. {argus_alm-0.15.2.dist-info → argus_alm-0.15.3.dist-info}/METADATA +1 -1
  4. argus_alm-0.15.3.dist-info/RECORD +22 -0
  5. argus/backend/.gitkeep +0 -0
  6. argus/backend/__init__.py +0 -0
  7. argus/backend/cli.py +0 -57
  8. argus/backend/controller/__init__.py +0 -0
  9. argus/backend/controller/admin.py +0 -20
  10. argus/backend/controller/admin_api.py +0 -355
  11. argus/backend/controller/api.py +0 -589
  12. argus/backend/controller/auth.py +0 -67
  13. argus/backend/controller/client_api.py +0 -109
  14. argus/backend/controller/main.py +0 -316
  15. argus/backend/controller/notification_api.py +0 -72
  16. argus/backend/controller/notifications.py +0 -13
  17. argus/backend/controller/planner_api.py +0 -194
  18. argus/backend/controller/team.py +0 -129
  19. argus/backend/controller/team_ui.py +0 -19
  20. argus/backend/controller/testrun_api.py +0 -513
  21. argus/backend/controller/view_api.py +0 -188
  22. argus/backend/controller/views_widgets/__init__.py +0 -0
  23. argus/backend/controller/views_widgets/graphed_stats.py +0 -54
  24. argus/backend/controller/views_widgets/graphs.py +0 -68
  25. argus/backend/controller/views_widgets/highlights.py +0 -135
  26. argus/backend/controller/views_widgets/nemesis_stats.py +0 -26
  27. argus/backend/controller/views_widgets/summary.py +0 -43
  28. argus/backend/db.py +0 -98
  29. argus/backend/error_handlers.py +0 -41
  30. argus/backend/events/event_processors.py +0 -34
  31. argus/backend/models/__init__.py +0 -0
  32. argus/backend/models/argus_ai.py +0 -24
  33. argus/backend/models/github_issue.py +0 -60
  34. argus/backend/models/plan.py +0 -24
  35. argus/backend/models/result.py +0 -187
  36. argus/backend/models/runtime_store.py +0 -58
  37. argus/backend/models/view_widgets.py +0 -25
  38. argus/backend/models/web.py +0 -403
  39. argus/backend/plugins/__init__.py +0 -0
  40. argus/backend/plugins/core.py +0 -248
  41. argus/backend/plugins/driver_matrix_tests/controller.py +0 -66
  42. argus/backend/plugins/driver_matrix_tests/model.py +0 -429
  43. argus/backend/plugins/driver_matrix_tests/plugin.py +0 -21
  44. argus/backend/plugins/driver_matrix_tests/raw_types.py +0 -62
  45. argus/backend/plugins/driver_matrix_tests/service.py +0 -61
  46. argus/backend/plugins/driver_matrix_tests/udt.py +0 -42
  47. argus/backend/plugins/generic/model.py +0 -86
  48. argus/backend/plugins/generic/plugin.py +0 -15
  49. argus/backend/plugins/generic/types.py +0 -14
  50. argus/backend/plugins/loader.py +0 -39
  51. argus/backend/plugins/sct/controller.py +0 -224
  52. argus/backend/plugins/sct/plugin.py +0 -37
  53. argus/backend/plugins/sct/resource_setup.py +0 -177
  54. argus/backend/plugins/sct/service.py +0 -682
  55. argus/backend/plugins/sct/testrun.py +0 -288
  56. argus/backend/plugins/sct/udt.py +0 -100
  57. argus/backend/plugins/sirenada/model.py +0 -118
  58. argus/backend/plugins/sirenada/plugin.py +0 -16
  59. argus/backend/service/admin.py +0 -26
  60. argus/backend/service/argus_service.py +0 -696
  61. argus/backend/service/build_system_monitor.py +0 -185
  62. argus/backend/service/client_service.py +0 -127
  63. argus/backend/service/event_service.py +0 -18
  64. argus/backend/service/github_service.py +0 -233
  65. argus/backend/service/jenkins_service.py +0 -269
  66. argus/backend/service/notification_manager.py +0 -159
  67. argus/backend/service/planner_service.py +0 -608
  68. argus/backend/service/release_manager.py +0 -229
  69. argus/backend/service/results_service.py +0 -690
  70. argus/backend/service/stats.py +0 -610
  71. argus/backend/service/team_manager_service.py +0 -82
  72. argus/backend/service/test_lookup.py +0 -172
  73. argus/backend/service/testrun.py +0 -489
  74. argus/backend/service/user.py +0 -308
  75. argus/backend/service/views.py +0 -219
  76. argus/backend/service/views_widgets/__init__.py +0 -0
  77. argus/backend/service/views_widgets/graphed_stats.py +0 -180
  78. argus/backend/service/views_widgets/highlights.py +0 -374
  79. argus/backend/service/views_widgets/nemesis_stats.py +0 -34
  80. argus/backend/template_filters.py +0 -27
  81. argus/backend/tests/__init__.py +0 -0
  82. argus/backend/tests/client_service/__init__.py +0 -0
  83. argus/backend/tests/client_service/test_submit_results.py +0 -79
  84. argus/backend/tests/conftest.py +0 -180
  85. argus/backend/tests/results_service/__init__.py +0 -0
  86. argus/backend/tests/results_service/test_best_results.py +0 -178
  87. argus/backend/tests/results_service/test_cell.py +0 -65
  88. argus/backend/tests/results_service/test_chartjs_additional_functions.py +0 -259
  89. argus/backend/tests/results_service/test_create_chartjs.py +0 -220
  90. argus/backend/tests/results_service/test_result_metadata.py +0 -100
  91. argus/backend/tests/results_service/test_results_service.py +0 -203
  92. argus/backend/tests/results_service/test_validation_rules.py +0 -213
  93. argus/backend/tests/view_widgets/__init__.py +0 -0
  94. argus/backend/tests/view_widgets/test_highlights_api.py +0 -532
  95. argus/backend/util/common.py +0 -65
  96. argus/backend/util/config.py +0 -38
  97. argus/backend/util/encoders.py +0 -56
  98. argus/backend/util/logsetup.py +0 -80
  99. argus/backend/util/module_loaders.py +0 -30
  100. argus/backend/util/send_email.py +0 -91
  101. argus/client/tests/__init__.py +0 -0
  102. argus/client/tests/conftest.py +0 -19
  103. argus/client/tests/test_package.py +0 -45
  104. argus/client/tests/test_results.py +0 -224
  105. argus_alm-0.15.2.dist-info/RECORD +0 -122
  106. {argus_alm-0.15.2.dist-info → argus_alm-0.15.3.dist-info}/WHEEL +0 -0
  107. {argus_alm-0.15.2.dist-info → argus_alm-0.15.3.dist-info}/entry_points.txt +0 -0
  108. {argus_alm-0.15.2.dist-info → argus_alm-0.15.3.dist-info}/licenses/LICENSE +0 -0
  109. {argus_alm-0.15.2.dist-info → argus_alm-0.15.3.dist-info}/top_level.txt +0 -0
@@ -1,188 +0,0 @@
1
- import logging
2
- from uuid import UUID
3
- from flask import (
4
- Blueprint,
5
- jsonify,
6
- request,
7
- )
8
- from argus.backend.controller.views_widgets.highlights import bp as highlights_bp
9
- from argus.backend.controller.views_widgets.summary import bp as summary_bp
10
- from argus.backend.controller.views_widgets.graphs import bp as graphs_bp
11
- from argus.backend.controller.views_widgets.nemesis_stats import bp as nemesis_stats_bp
12
- from argus.backend.controller.views_widgets.graphed_stats import bp as graphed_stats_bp
13
- from argus.backend.error_handlers import handle_api_exception
14
- from argus.backend.models.web import User
15
- from argus.backend.service.stats import ViewStatsCollector
16
- from argus.backend.service.user import api_login_required
17
- from argus.backend.service.views import UserViewService
18
- from argus.backend.util.common import get_payload
19
-
20
- bp = Blueprint('view_api', __name__, url_prefix='/views')
21
- LOGGER = logging.getLogger(__name__)
22
- bp.register_blueprint(highlights_bp)
23
- bp.register_blueprint(summary_bp)
24
- bp.register_blueprint(graphs_bp)
25
- bp.register_blueprint(graphed_stats_bp)
26
- bp.register_blueprint(nemesis_stats_bp)
27
- bp.register_error_handler(Exception, handle_api_exception)
28
-
29
-
30
- class ViewApiException(Exception):
31
- pass
32
-
33
-
34
- @bp.route("/", methods=["GET"])
35
- @api_login_required
36
- def index():
37
- return {
38
- "status": "ok",
39
- "response": {
40
- "version": "v1",
41
- }
42
- }
43
-
44
-
45
- @bp.route("/create", methods=["POST"])
46
- @api_login_required
47
- def create_view():
48
- payload = get_payload(request)
49
- service = UserViewService()
50
- view = service.create_view(
51
- name=payload["name"],
52
- items=payload["items"],
53
- widget_settings=payload["settings"],
54
- description=payload.get("description"),
55
- display_name=payload.get("displayName")
56
- )
57
- return {
58
- "status": "ok",
59
- "response": view
60
- }
61
-
62
-
63
- @bp.route("/get", methods=["GET"])
64
- @api_login_required
65
- def get_view():
66
- view_id = request.args.get("viewId")
67
- if not view_id:
68
- raise ViewApiException("No viewId provided.")
69
- service = UserViewService()
70
- view = service.get_view(UUID(view_id))
71
- return {
72
- "status": "ok",
73
- "response": view
74
- }
75
-
76
-
77
- @bp.route("/all", methods=["GET"])
78
- @api_login_required
79
- def get_all_views():
80
- user_id = request.args.get("userId")
81
- if user_id:
82
- user = User.get(id=user_id)
83
- else:
84
- user = None
85
- service = UserViewService()
86
- views = service.get_all_views(user)
87
- return {
88
- "status": "ok",
89
- "response": views
90
- }
91
-
92
-
93
- @bp.route("/update", methods=["POST"])
94
- @api_login_required
95
- def update_view():
96
- payload = get_payload(request)
97
- service = UserViewService()
98
- res = service.update_view(view_id=payload["viewId"], update_data=payload["updateData"])
99
- return {
100
- "status": "ok",
101
- "response": res
102
- }
103
-
104
-
105
- @bp.route("/delete", methods=["POST"])
106
- @api_login_required
107
- def delete_view():
108
- payload = get_payload(request)
109
- service = UserViewService()
110
- res = service.delete_view(payload["viewId"])
111
- return {
112
- "status": "ok",
113
- "response": res
114
- }
115
-
116
-
117
- @bp.route("/search", methods=["GET"])
118
- @api_login_required
119
- def search_tests():
120
- query = request.args.get("query")
121
- service = UserViewService()
122
- if query:
123
- res = service.test_lookup(query)
124
- else:
125
- res = []
126
- return {
127
- "status": "ok",
128
- "response": {
129
- "hits": res,
130
- "total": len(res)
131
- }
132
- }
133
-
134
-
135
- @bp.route("/stats", methods=["GET"])
136
- @api_login_required
137
- def view_stats():
138
- view_id = request.args.get("viewId")
139
- if not view_id:
140
- raise ViewApiException("No view id provided.")
141
- limited = bool(int(request.args.get("limited", 0)))
142
- version = request.args.get("productVersion", None)
143
- include_no_version = bool(int(request.args.get("includeNoVersion", True)))
144
- force = bool(int(request.args.get("force", 0)))
145
- widget_id = request.args.get("widgetId", None)
146
- if widget_id:
147
- widget_id = int(widget_id)
148
- collector = ViewStatsCollector(view_id=view_id, filter=version)
149
- stats = collector.collect(limited=limited, force=force, include_no_version=include_no_version, widget_id=widget_id)
150
-
151
- res = jsonify({
152
- "status": "ok",
153
- "response": stats
154
- })
155
- res.cache_control.max_age = 300
156
- return res
157
-
158
-
159
- @bp.route("/<string:view_id>/versions", methods=["GET"])
160
- @api_login_required
161
- def view_versions(view_id: str):
162
- service = UserViewService()
163
- res = service.get_versions_for_view(view_id)
164
- return {
165
- "status": "ok",
166
- "response": res
167
- }
168
-
169
-
170
- @bp.route("/<string:view_id>/resolve", methods=["GET"])
171
- @api_login_required
172
- def view_resolve(view_id: str):
173
- service = UserViewService()
174
- res = service.resolve_view_for_edit(view_id)
175
- return {
176
- "status": "ok",
177
- "response": res
178
- }
179
-
180
- @bp.route("/<string:view_id>/resolve/tests", methods=["GET"])
181
- @api_login_required
182
- def view_resolve_tests(view_id: str):
183
- service = UserViewService()
184
- res = service.resolve_view_tests(view_id)
185
- return {
186
- "status": "ok",
187
- "response": res
188
- }
File without changes
@@ -1,54 +0,0 @@
1
- from uuid import UUID
2
-
3
- from argus.backend.util.common import get_payload
4
- from flask import Blueprint, request
5
-
6
- from argus.backend.models.web import ArgusUserView
7
- from argus.backend.service.views_widgets.graphed_stats import GraphedStatsService
8
- from argus.backend.service.user import api_login_required
9
-
10
- bp = Blueprint("graphed_stats", __name__, url_prefix="/widgets")
11
-
12
-
13
- @bp.route("/graphed_stats", methods=["GET"])
14
- @api_login_required
15
- def get_graphed_stats():
16
- view_id = UUID(request.args.get("view_id"))
17
- view: ArgusUserView = ArgusUserView.get(id=view_id)
18
- service = GraphedStatsService()
19
- response_data = {
20
- "test_runs": [],
21
- "nemesis_data": []
22
- }
23
-
24
- filters = request.args.get("filters")
25
-
26
- for test_id in view.tests:
27
- data = service.get_graphed_stats(test_id, filters)
28
- response_data["test_runs"].extend(data["test_runs"])
29
- response_data["nemesis_data"].extend(data["nemesis_data"])
30
- return {
31
- "status": "ok",
32
- "response": response_data
33
- }
34
-
35
-
36
- @bp.route("/runs_details", methods=["POST"])
37
- @api_login_required
38
- def get_runs_details():
39
- """Get detailed information for provided test runs including assignee and attached issues."""
40
- data = get_payload(request)
41
- if not data or "run_ids" not in data:
42
- raise ValueError("Missing run_ids parameter")
43
-
44
- run_ids = data["run_ids"]
45
- if not isinstance(run_ids, list):
46
- raise ValueError("run_ids must be a list")
47
-
48
- service = GraphedStatsService()
49
- result = service.get_runs_details(run_ids)
50
-
51
- return {
52
- "status": "ok",
53
- "response": result
54
- }
@@ -1,68 +0,0 @@
1
- from uuid import UUID
2
- from datetime import datetime, timezone
3
-
4
- from flask import Blueprint, request
5
-
6
- from argus.backend.models.web import ArgusUserView, ArgusTest
7
- from argus.backend.service.results_service import ResultsService
8
- from argus.backend.service.user import api_login_required
9
- bp = Blueprint("graphs", __name__, url_prefix="/widgets")
10
-
11
-
12
- @bp.route("/graphs/graph_views", methods=["GET"])
13
- @api_login_required
14
- def get_graph_views():
15
- view_id = UUID(request.args.get("view_id"))
16
- view: ArgusUserView = ArgusUserView.get(id=view_id)
17
- start_date = request.args.get("start_date")
18
- end_date = request.args.get("end_date")
19
- service = ResultsService()
20
- response = {}
21
- tests_details = {}
22
-
23
- for test_id in view.tests:
24
- test_uuid = test_id
25
- graph_views = service.get_argus_graph_views(test_uuid)
26
- if graph_views:
27
- test_name = ArgusTest.get(id=test_uuid).name
28
- tests_details[str(test_id)] = {"name": test_name}
29
- view_data = []
30
-
31
- for graph_view in graph_views:
32
- # Get unique table names from all graphs in the view
33
- table_names = set()
34
- for graph_name in graph_view.graphs.keys():
35
- table_name = graph_name.rsplit(" - ", 1)[0]
36
- table_names.add(table_name)
37
-
38
- # Get graphs data for these tables
39
- start_dt = datetime.fromisoformat(start_date).astimezone(timezone.utc) if start_date else None
40
- end_dt = datetime.fromisoformat(end_date).astimezone(timezone.utc) if end_date else None
41
- graphs, ticks, releases_filters = service.get_test_graphs(
42
- test_id=test_uuid,
43
- start_date=start_dt,
44
- end_date=end_dt,
45
- table_names=list(table_names)
46
- )
47
-
48
- # filter out graphs that are not in the graph views
49
- graphs = [graph for graph in graphs if graph["options"]
50
- ["plugins"]["title"]["text"] in graph_view.graphs.keys()]
51
-
52
- if graphs:
53
- view_data.append({
54
- "id": str(graph_view.id),
55
- "name": graph_view.name,
56
- "description": graph_view.description,
57
- "graphs": graphs,
58
- "ticks": ticks,
59
- "releases_filters": releases_filters
60
- })
61
-
62
- response[str(test_id)] = view_data
63
-
64
- return {
65
- "status": "ok",
66
- "response": response,
67
- "tests_details": tests_details
68
- }
@@ -1,135 +0,0 @@
1
- from dataclasses import asdict
2
- from uuid import UUID
3
-
4
- from flask import Blueprint, request, g
5
-
6
- from argus.backend.service.user import api_login_required
7
- from argus.backend.service.views_widgets.highlights import (
8
- HighlightCreate,
9
- HighlightsService,
10
- HighlightArchive,
11
- HighlightUpdate,
12
- HighlightSetAssignee,
13
- HighlightSetCompleted,
14
- CommentUpdate,
15
- CommentDelete,
16
- CommentCreate,
17
- )
18
- from argus.backend.util.common import get_payload
19
-
20
- bp = Blueprint("view_widgets", __name__, url_prefix="/widgets")
21
-
22
-
23
- @bp.route("/highlights/create", methods=["POST"])
24
- @api_login_required
25
- def create_highlight():
26
- creator_id = g.user.id
27
- payload = HighlightCreate(**get_payload(request))
28
- service = HighlightsService()
29
- highlight = service.create(creator_id, payload)
30
- return {"status": "ok", "response": asdict(highlight)}
31
-
32
-
33
- @bp.route("/highlights", methods=["GET"])
34
- @api_login_required
35
- def get_highlights():
36
- view_id = UUID(request.args.get("view_id"))
37
- index = int(request.args.get("index"))
38
- service = HighlightsService()
39
- highlights, action_items = service.get_highlights(view_id, index)
40
- return {
41
- "status": "ok",
42
- "response": {
43
- "highlights": [asdict(h) for h in highlights],
44
- "action_items": [asdict(a) for a in action_items],
45
- },
46
- }
47
-
48
-
49
- @bp.route("/highlights/archive", methods=["POST"])
50
- @api_login_required
51
- def archive_highlight():
52
- payload = HighlightArchive(**get_payload(request))
53
- service = HighlightsService()
54
- service.archive_highlight(payload)
55
- return {"status": "ok"}
56
-
57
-
58
- @bp.route("/highlights/unarchive", methods=["POST"])
59
- @api_login_required
60
- def unarchive_highlight():
61
- payload = HighlightArchive(**get_payload(request))
62
- service = HighlightsService()
63
- service.unarchive_highlight(payload)
64
- return {"status": "ok"}
65
-
66
-
67
- @bp.route("/highlights/update", methods=["POST"])
68
- @api_login_required
69
- def update_highlight():
70
- payload = HighlightUpdate(**get_payload(request))
71
- service = HighlightsService()
72
- updated_highlight = service.update_highlight(g.user.id, payload)
73
- return {"status": "ok", "response": asdict(updated_highlight)}
74
-
75
-
76
- @bp.route("/highlights/set_assignee", methods=["POST"])
77
- @api_login_required
78
- def set_assignee():
79
- payload = HighlightSetAssignee(**get_payload(request))
80
- service = HighlightsService()
81
- updated_action_item = service.set_assignee(payload)
82
- if payload.assignee_id:
83
- service.send_action_notification(sender_id=g.user.id, username=g.user.username, view_id=payload.view_id,
84
- assignee_id=payload.assignee_id, action=updated_action_item.content)
85
- return {"status": "ok", "response": asdict(updated_action_item)}
86
-
87
-
88
- @bp.route("/highlights/set_completed", methods=["POST"])
89
- @api_login_required
90
- def set_completed():
91
- payload = HighlightSetCompleted(**get_payload(request))
92
- service = HighlightsService()
93
- updated_action_item = service.set_completed(payload)
94
- return {"status": "ok", "response": asdict(updated_action_item)}
95
-
96
-
97
- @bp.route("/highlights/comments/create", methods=["POST"])
98
- @api_login_required
99
- def create_comment():
100
- creator_id = g.user.id
101
- payload = CommentCreate(**get_payload(request))
102
- service = HighlightsService()
103
- comment = service.create_comment(creator_id, payload)
104
- return {"status": "ok", "response": asdict(comment)}
105
-
106
-
107
- @bp.route("/highlights/comments/update", methods=["POST"])
108
- @api_login_required
109
- def update_comment():
110
- user_id = g.user.id
111
- payload = CommentUpdate(**get_payload(request))
112
- service = HighlightsService()
113
- updated_comment = service.update_comment(user_id, payload)
114
- return {"status": "ok", "response": asdict(updated_comment)}
115
-
116
-
117
- @bp.route("/highlights/comments/delete", methods=["POST"])
118
- @api_login_required
119
- def delete_comment():
120
- user_id = g.user.id
121
- payload = CommentDelete(**get_payload(request))
122
- service = HighlightsService()
123
- service.delete_comment(user_id, payload)
124
- return {"status": "ok"}
125
-
126
-
127
- @bp.route("/highlights/comments", methods=["GET"])
128
- @api_login_required
129
- def get_comments():
130
- view_id = UUID(request.args.get("view_id"))
131
- index = int(request.args.get("index"))
132
- highlight_created_at = float(request.args.get("created_at"))
133
- service = HighlightsService()
134
- comments = service.get_comments(view_id, index, highlight_created_at)
135
- return {"status": "ok", "response": [asdict(c) for c in comments]}
@@ -1,26 +0,0 @@
1
- from uuid import UUID
2
-
3
- from flask import Blueprint, request
4
-
5
- from argus.backend.models.web import ArgusUserView
6
- from argus.backend.service.views_widgets.nemesis_stats import NemesisStatsService
7
- from argus.backend.service.user import api_login_required
8
-
9
-
10
- bp = Blueprint("nemesis_stats", __name__, url_prefix="/widgets")
11
-
12
-
13
- @bp.route("/nemesis_data", methods=["GET"])
14
- @api_login_required
15
- def get_nemesis_data():
16
- view_id = UUID(request.args.get("view_id"))
17
- view: ArgusUserView = ArgusUserView.get(id=view_id)
18
- service = NemesisStatsService()
19
- nemesis_data = []
20
- for test_id in view.tests:
21
- data = service.get_nemesis_data(test_id)
22
- nemesis_data.extend(data)
23
- return {
24
- "status": "ok",
25
- "response": {"nemesis_data": nemesis_data},
26
- }
@@ -1,43 +0,0 @@
1
- from uuid import UUID
2
-
3
- from flask import Blueprint, request, g
4
-
5
- from argus.backend.models.web import ArgusUserView
6
- from argus.backend.service.results_service import ResultsService
7
- from argus.backend.service.user import api_login_required
8
- from argus.backend.util.common import get_payload
9
-
10
- bp = Blueprint("summary", __name__, url_prefix="/widgets")
11
-
12
-
13
- @bp.route("/summary/versioned_runs", methods=["GET"])
14
- @api_login_required
15
- def get_versioned_runs():
16
- view_id = UUID(request.args.get("view_id"))
17
- view: ArgusUserView = ArgusUserView.get(id=view_id)
18
- service = ResultsService()
19
- versioned_runs = service.get_tests_by_version("scylla-server", view.tests)
20
- return {
21
- "status": "ok",
22
- "response": versioned_runs,
23
- }
24
-
25
-
26
- @bp.route("/summary/runs_results", methods=["POST"])
27
- @api_login_required
28
- def get_runs_results():
29
- versioned_runs = get_payload(request)
30
- service = ResultsService()
31
- response = {}
32
- for test_id, test_methods in versioned_runs.items():
33
- response[test_id] = {}
34
- for method, run in test_methods.items():
35
- response[test_id][method] = {}
36
- run_id = run['run_id']
37
- response[test_id][method][run_id] = service.get_run_results(UUID(test_id), UUID(run_id), key_metrics=[
38
- "P99 read", "P99 write", "duration", "Throughput write", "Throughput read", "allocs_per_op",
39
- "cpu_cycles_per_op", "instructions_per_op", "logallocs_per_op"])
40
- return {
41
- "status": "ok",
42
- "response": response,
43
- }
argus/backend/db.py DELETED
@@ -1,98 +0,0 @@
1
- from functools import cached_property
2
- import logging
3
- from typing import Optional
4
- from flask import g, Flask
5
- from cassandra.policies import WhiteListRoundRobinPolicy
6
- from cassandra import ConsistencyLevel
7
- from cassandra.cluster import ExecutionProfile, EXEC_PROFILE_DEFAULT, Cluster
8
- from cassandra.cluster import PreparedStatement
9
- from cassandra.cqlengine.management import sync_table, sync_type
10
- from cassandra.cqlengine import connection
11
- from cassandra.query import dict_factory
12
- from cassandra.auth import PlainTextAuthProvider
13
- from argus.backend.util.config import Config
14
-
15
- from argus.backend.models.web import USED_MODELS, USED_TYPES
16
-
17
- LOGGER = logging.getLogger(__name__)
18
-
19
-
20
- class ScyllaCluster:
21
- APP_INSTANCE: Optional['ScyllaCluster'] = None
22
-
23
- def __init__(self, config=None):
24
- if not config:
25
- config = Config.load_yaml_config()
26
- self.config = config
27
- self.auth_provider = PlainTextAuthProvider(
28
- username=config["SCYLLA_USERNAME"], password=config["SCYLLA_PASSWORD"])
29
- self.lb_policy = WhiteListRoundRobinPolicy(hosts=config["SCYLLA_CONTACT_POINTS"])
30
- self.execution_profile = ExecutionProfile(
31
- load_balancing_policy=self.lb_policy, consistency_level=ConsistencyLevel.QUORUM)
32
- connection.setup(hosts=config["SCYLLA_CONTACT_POINTS"], default_keyspace=config["SCYLLA_KEYSPACE_NAME"],
33
- auth_provider=self.auth_provider,
34
- protocol_version=4,
35
- execution_profiles={EXEC_PROFILE_DEFAULT: self.execution_profile})
36
- self.cluster: Cluster = connection.get_cluster(connection='default')
37
- self.prepared_statements = {}
38
- self.read_exec_profile = ExecutionProfile(
39
- consistency_level=ConsistencyLevel.ONE,
40
- row_factory=dict_factory,
41
- load_balancing_policy=self.lb_policy
42
- )
43
- self.read_named_tuple_exec_profile = ExecutionProfile(
44
- consistency_level=ConsistencyLevel.ONE,
45
- load_balancing_policy=self.lb_policy
46
- )
47
- self.cluster.add_execution_profile("read_fast", self.read_exec_profile)
48
- self.cluster.add_execution_profile("read_fast_named_tuple", self.read_named_tuple_exec_profile)
49
-
50
- @cached_property
51
- def session(self):
52
- return self.cluster.connect(keyspace=self.config["SCYLLA_KEYSPACE_NAME"])
53
-
54
- @classmethod
55
- def get(cls, config: Config = None) -> 'ScyllaCluster':
56
- if cls.APP_INSTANCE:
57
- return cls.APP_INSTANCE
58
-
59
- cls.APP_INSTANCE = cls(config)
60
- return cls.APP_INSTANCE
61
-
62
- @classmethod
63
- def shutdown(cls):
64
- if cls.APP_INSTANCE:
65
- cls.APP_INSTANCE.cluster.shutdown()
66
- cls.APP_INSTANCE = None
67
-
68
- def prepare(self, query: str) -> PreparedStatement:
69
- if not (statement := self.prepared_statements.get(query)):
70
- LOGGER.info("Unprepared statement %s, preparing...", query)
71
- statement = self.session.prepare(query=query)
72
- self.prepared_statements[query] = statement
73
- return statement
74
-
75
- def sync_core_tables(self):
76
- for udt in USED_TYPES:
77
- LOGGER.info("Syncing type: %s..", udt.__name__)
78
- sync_type(ks_name=self.config["SCYLLA_KEYSPACE_NAME"], type_model=udt)
79
- LOGGER.info("Core Types synchronized.")
80
- for model in USED_MODELS:
81
- LOGGER.info("Syncing model: %s..", model.__name__)
82
- sync_table(model, keyspaces=[self.config["SCYLLA_KEYSPACE_NAME"]])
83
- LOGGER.info("Core Models synchronized.")
84
-
85
- @classmethod
86
- def get_session(cls):
87
- cluster = cls.get()
88
- if 'scylla_session' not in g:
89
- g.scylla_session = cluster.session
90
- return g.scylla_session
91
-
92
- @classmethod
93
- def close_session(cls, error=None):
94
- g.pop("scylla_session", None)
95
-
96
- @classmethod
97
- def attach_to_app(cls, app: Flask):
98
- app.teardown_appcontext(cls.close_session)
@@ -1,41 +0,0 @@
1
- import base64
2
- from hashlib import sha256
3
- import logging
4
- import os
5
- from traceback import format_exception
6
- from flask import request
7
-
8
- LOGGER = logging.getLogger(__name__)
9
-
10
-
11
- class APIException(Exception):
12
- pass
13
-
14
-
15
- class DataValidationError(APIException):
16
- pass
17
-
18
-
19
- def handle_api_exception(exception: Exception):
20
- trace_id = base64.encodebytes(sha256(os.urandom(64)).digest()).decode(encoding="utf-8").strip()
21
- if issubclass(exception.__class__, APIException):
22
- LOGGER.info("[TraceId: %s] Endpoint %s responded with error %s: %s", trace_id,
23
- request.endpoint, exception.__class__.__name__, str(exception))
24
- LOGGER.info("[TraceId: %s] Headers\n%s", trace_id, request.headers)
25
- LOGGER.info("[TraceId: %s] Request Data Start\n%s\nRequest Data End", trace_id,
26
- request.json if request.is_json else request.get_data(as_text=True))
27
- else:
28
- LOGGER.error("[TraceId: %s] Exception in %s\n%s", trace_id,
29
- request.endpoint, "".join(format_exception(exception)))
30
- LOGGER.error("[TraceId: %s] Headers\n%s", trace_id, request.headers)
31
- LOGGER.error("[TraceId: %s] Request Data Start\n%s\nRequest Data End", trace_id,
32
- request.json if request.is_json else request.get_data(as_text=True))
33
-
34
- return {
35
- "status": "error",
36
- "response": {
37
- "trace_id": trace_id,
38
- "exception": exception.__class__.__name__,
39
- "arguments": exception.args
40
- }
41
- }
@@ -1,34 +0,0 @@
1
- from argus.backend.models.web import ArgusEventTypes
2
-
3
-
4
- def event_process_posted_comment(event: dict) -> dict:
5
- return event["message"].format(**event)
6
-
7
-
8
- def event_process_status_changed(event: dict) -> dict:
9
- return event["message"].format(**event)
10
-
11
-
12
- def event_process_investigation_status_changed(event: dict) -> dict:
13
- return event["message"].format(**event)
14
-
15
-
16
- def event_process_assignee_changed(event: dict) -> dict:
17
- return event["message"].format(**event)
18
-
19
-
20
- def event_process_issue_added(event: dict) -> dict:
21
- return event["message"].format(**event)
22
-
23
-
24
- EVENT_PROCESSORS = {
25
- ArgusEventTypes.AssigneeChanged: event_process_assignee_changed,
26
- ArgusEventTypes.TestRunStatusChanged: event_process_status_changed,
27
- ArgusEventTypes.TestRunCommentPosted: event_process_posted_comment,
28
- ArgusEventTypes.TestRunCommentUpdated: event_process_posted_comment,
29
- ArgusEventTypes.TestRunCommentDeleted: event_process_posted_comment,
30
- ArgusEventTypes.TestRunIssueAdded: event_process_issue_added,
31
- ArgusEventTypes.TestRunIssueRemoved: event_process_issue_added,
32
- ArgusEventTypes.TestRunInvestigationStatusChanged: event_process_investigation_status_changed,
33
- ArgusEventTypes.TestRunBatchInvestigationStatusChange: event_process_investigation_status_changed,
34
- }