argus-alm 0.12.10__py3-none-any.whl → 0.13.0__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 (92) hide show
  1. argus/client/base.py +1 -1
  2. argus/client/driver_matrix_tests/cli.py +2 -2
  3. argus/client/driver_matrix_tests/client.py +1 -1
  4. argus/client/generic/cli.py +2 -2
  5. argus/client/sct/client.py +3 -3
  6. argus/client/sirenada/client.py +1 -1
  7. {argus_alm-0.12.10.dist-info → argus_alm-0.13.0.dist-info}/METADATA +2 -4
  8. argus_alm-0.13.0.dist-info/RECORD +20 -0
  9. argus/backend/.gitkeep +0 -0
  10. argus/backend/cli.py +0 -41
  11. argus/backend/controller/__init__.py +0 -0
  12. argus/backend/controller/admin.py +0 -20
  13. argus/backend/controller/admin_api.py +0 -354
  14. argus/backend/controller/api.py +0 -529
  15. argus/backend/controller/auth.py +0 -67
  16. argus/backend/controller/client_api.py +0 -108
  17. argus/backend/controller/main.py +0 -274
  18. argus/backend/controller/notification_api.py +0 -72
  19. argus/backend/controller/notifications.py +0 -13
  20. argus/backend/controller/team.py +0 -126
  21. argus/backend/controller/team_ui.py +0 -18
  22. argus/backend/controller/testrun_api.py +0 -482
  23. argus/backend/controller/view_api.py +0 -162
  24. argus/backend/db.py +0 -100
  25. argus/backend/error_handlers.py +0 -21
  26. argus/backend/events/event_processors.py +0 -34
  27. argus/backend/models/__init__.py +0 -0
  28. argus/backend/models/result.py +0 -138
  29. argus/backend/models/web.py +0 -389
  30. argus/backend/plugins/__init__.py +0 -0
  31. argus/backend/plugins/core.py +0 -225
  32. argus/backend/plugins/driver_matrix_tests/controller.py +0 -63
  33. argus/backend/plugins/driver_matrix_tests/model.py +0 -421
  34. argus/backend/plugins/driver_matrix_tests/plugin.py +0 -22
  35. argus/backend/plugins/driver_matrix_tests/raw_types.py +0 -62
  36. argus/backend/plugins/driver_matrix_tests/service.py +0 -60
  37. argus/backend/plugins/driver_matrix_tests/udt.py +0 -42
  38. argus/backend/plugins/generic/model.py +0 -79
  39. argus/backend/plugins/generic/plugin.py +0 -16
  40. argus/backend/plugins/generic/types.py +0 -13
  41. argus/backend/plugins/loader.py +0 -40
  42. argus/backend/plugins/sct/controller.py +0 -185
  43. argus/backend/plugins/sct/plugin.py +0 -38
  44. argus/backend/plugins/sct/resource_setup.py +0 -178
  45. argus/backend/plugins/sct/service.py +0 -491
  46. argus/backend/plugins/sct/testrun.py +0 -272
  47. argus/backend/plugins/sct/udt.py +0 -101
  48. argus/backend/plugins/sirenada/model.py +0 -113
  49. argus/backend/plugins/sirenada/plugin.py +0 -17
  50. argus/backend/service/admin.py +0 -27
  51. argus/backend/service/argus_service.py +0 -688
  52. argus/backend/service/build_system_monitor.py +0 -188
  53. argus/backend/service/client_service.py +0 -122
  54. argus/backend/service/event_service.py +0 -18
  55. argus/backend/service/jenkins_service.py +0 -240
  56. argus/backend/service/notification_manager.py +0 -150
  57. argus/backend/service/release_manager.py +0 -230
  58. argus/backend/service/results_service.py +0 -317
  59. argus/backend/service/stats.py +0 -540
  60. argus/backend/service/team_manager_service.py +0 -83
  61. argus/backend/service/testrun.py +0 -559
  62. argus/backend/service/user.py +0 -307
  63. argus/backend/service/views.py +0 -258
  64. argus/backend/template_filters.py +0 -27
  65. argus/backend/tests/__init__.py +0 -0
  66. argus/backend/tests/argus_web.test.yaml +0 -39
  67. argus/backend/tests/conftest.py +0 -44
  68. argus/backend/tests/results_service/__init__.py +0 -0
  69. argus/backend/tests/results_service/test_best_results.py +0 -70
  70. argus/backend/util/common.py +0 -65
  71. argus/backend/util/config.py +0 -38
  72. argus/backend/util/encoders.py +0 -41
  73. argus/backend/util/logsetup.py +0 -81
  74. argus/backend/util/module_loaders.py +0 -30
  75. argus/backend/util/send_email.py +0 -91
  76. argus/client/generic_result_old.py +0 -143
  77. argus/db/.gitkeep +0 -0
  78. argus/db/argus_json.py +0 -14
  79. argus/db/cloud_types.py +0 -125
  80. argus/db/config.py +0 -135
  81. argus/db/db_types.py +0 -139
  82. argus/db/interface.py +0 -370
  83. argus/db/testrun.py +0 -740
  84. argus/db/utils.py +0 -15
  85. argus_alm-0.12.10.dist-info/RECORD +0 -96
  86. /argus/{backend → common}/__init__.py +0 -0
  87. /argus/{backend/util → common}/enums.py +0 -0
  88. /argus/{backend/plugins/sct/types.py → common/sct_types.py} +0 -0
  89. /argus/{backend/plugins/sirenada/types.py → common/sirenada_types.py} +0 -0
  90. {argus_alm-0.12.10.dist-info → argus_alm-0.13.0.dist-info}/LICENSE +0 -0
  91. {argus_alm-0.12.10.dist-info → argus_alm-0.13.0.dist-info}/WHEEL +0 -0
  92. {argus_alm-0.12.10.dist-info → argus_alm-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -1,150 +0,0 @@
1
- import logging
2
- from typing import Any
3
- from uuid import UUID
4
- from flask import current_app, render_template
5
- from argus.backend.models.web import ArgusNotification, ArgusNotificationSourceTypes, ArgusNotificationTypes, ArgusNotificationState, User
6
- from argus.backend.util.send_email import Email
7
-
8
- LOGGER = logging.getLogger(__name__)
9
-
10
-
11
- class NotificationManagerException(Exception):
12
- pass
13
-
14
-
15
- class NotificationManagerService:
16
-
17
- def __init__(self, notification_senders: list["NotificationSenderBase"] | None = None) -> None:
18
- self.notification_services: list["NotificationSenderBase"] = [
19
- ArgusDBNotificationSaver(),
20
- EmailNotificationServiceSender()
21
- ]
22
- if notification_senders:
23
- self.notification_services.extend(notification_senders)
24
-
25
- def send_notification(self, receiver: UUID, sender: UUID,
26
- notification_type: ArgusNotificationTypes,
27
- source_type: ArgusNotificationSourceTypes,
28
- source_id: UUID, title: str | None = None,
29
- source_message: str | None = None, content_params: dict | None = None) -> Any:
30
-
31
- for service in self.notification_services:
32
- service.send_notification(receiver, sender, notification_type, source_type,
33
- source_id, title, source_message, content_params)
34
-
35
- def get_notificaton(self, receiver: UUID, notification_id: UUID) -> ArgusNotification:
36
- return ArgusNotification.get(receiver=receiver, id=notification_id)
37
-
38
- def get_unread_count(self, receiver: UUID) -> int:
39
- query = ArgusNotification.filter(
40
- receiver=receiver, state__eq=ArgusNotificationState.UNREAD.value).allow_filtering().all()
41
- return len(query)
42
-
43
- def read_notification(self, receiver: UUID, notification_id: UUID) -> ArgusNotification:
44
- notification = ArgusNotification.get(receiver=receiver, id=notification_id)
45
- notification.state = ArgusNotificationState.READ
46
- return bool(notification.save().state)
47
-
48
- def get_notifications(self, receiver: UUID, limit: int = 20, after: UUID | None = None) -> list[ArgusNotification]:
49
- if after:
50
- return ArgusNotification.filter(receiver=receiver, id__lte=after).all().limit(limit)
51
- return ArgusNotification.filter(receiver=receiver).all().limit(limit)
52
-
53
-
54
- class NotificationSenderBase:
55
- NOTIFICATION_TITLES = {
56
- ArgusNotificationTypes.Mention: "You were mentioned in a comment",
57
- ArgusNotificationTypes.StatusChange: "A run you are assigned to changed status",
58
- ArgusNotificationTypes.AssigneeChange: "You were assigned to a run",
59
- ArgusNotificationTypes.ScheduleChange: "You were assigned to a schedule",
60
- }
61
-
62
- CONTENT_TEMPLATES = {}
63
-
64
- def _check_user(self, user_id: UUID) -> bool:
65
- try:
66
- user = User.get(id=user_id)
67
- if user.id == user_id:
68
- return True
69
- except User.DoesNotExist:
70
- return False
71
-
72
- def _get_title_for_notification_type(self, notification_type: ArgusNotificationTypes) -> str:
73
- if title := self.NOTIFICATION_TITLES.get(notification_type):
74
- return title
75
- raise NotificationManagerException(
76
- f"Title for notification type {notification_type} not found.", notification_type)
77
-
78
- def _render_content(self, content_type: ArgusNotificationTypes, params: dict):
79
- if content_renderer := self.CONTENT_TEMPLATES.get(content_type):
80
- return content_renderer(params)
81
- raise NotificationManagerException(
82
- f"Content renderer for notification type {content_type} not found.", content_type)
83
-
84
- def send_notification(self, receiver: UUID, sender: UUID,
85
- notification_type: ArgusNotificationTypes,
86
- source_type: ArgusNotificationSourceTypes,
87
- source_id: UUID,
88
- title: str | None = None,
89
- content: str | None = None,
90
- content_params: dict | None = None) -> Any:
91
- raise NotImplementedError()
92
-
93
-
94
- class ArgusDBNotificationSaver(NotificationSenderBase):
95
- CONTENT_TEMPLATES = {
96
- ArgusNotificationTypes.Mention: lambda p: render_template("notifications/mention.html.j2", **p if p else {}),
97
- ArgusNotificationTypes.AssigneeChange: lambda p: render_template("notifications/assigned.html.j2", **p if p else {}),
98
- }
99
-
100
- def send_notification(self, receiver: UUID, sender: UUID, notification_type: ArgusNotificationTypes, source_type: ArgusNotificationSourceTypes,
101
- source_id: UUID, title: str | None = None, content: str | None = None, content_params: dict | None = None) -> ArgusNotification:
102
- new_notification = ArgusNotification()
103
- for user in [sender, receiver]:
104
- if not self._check_user(user_id=user):
105
- raise NotificationManagerException(f"UserId {user} not found in the database", user)
106
-
107
- new_notification.sender = sender
108
- new_notification.receiver = receiver
109
- new_notification.type = notification_type.value
110
- new_notification.source_type = source_type.value
111
- new_notification.source_id = source_id
112
- new_notification.title = title if title else self._get_title_for_notification_type(notification_type)
113
- new_notification.content = content if not content_params else self._render_content(
114
- notification_type, content_params)
115
- return new_notification.save()
116
-
117
-
118
- class EmailNotificationServiceSender(NotificationSenderBase):
119
- CONTENT_TEMPLATES = {
120
- ArgusNotificationTypes.Mention: lambda p: render_template(
121
- "notifications/email_mention.html.j2", **p if p else {}),
122
- ArgusNotificationTypes.AssigneeChange: lambda p: render_template("notifications/assigned_email.html.j2", **p if p else {}),
123
- }
124
-
125
- def __init__(self):
126
- self.email = Email(init_connection=False)
127
-
128
- def get_user(self, user_id: UUID) -> User:
129
- return User.get(id=user_id)
130
-
131
- def send_notification(self, receiver: UUID, sender: UUID,
132
- notification_type: ArgusNotificationTypes, source_type: ArgusNotificationSourceTypes,
133
- source_id: UUID, title: str | None = None, content: str | None = None, content_params: dict | None = None):
134
- try:
135
- content_params = content_params or {}
136
- receiver_user = self.get_user(receiver)
137
- sender_user = self.get_user(sender)
138
- subject = title if title else self._get_title_for_notification_type(notification_type)
139
- content_params.update({
140
- "sender": sender_user.full_name,
141
- "message": content,
142
- })
143
-
144
- email_content = self._render_content(notification_type, content_params)
145
-
146
- self.email.send(subject=f"Argus Notification - {subject}",
147
- content=email_content,
148
- recipients=[receiver_user.email])
149
- except Exception as details: # pylint: disable=broad-except
150
- current_app.logger.error("Failed to send email: %s", details)
@@ -1,230 +0,0 @@
1
- import logging
2
- from typing import TypedDict
3
- from uuid import UUID
4
- from argus.backend.db import ScyllaCluster
5
- from argus.backend.plugins.sct.testrun import SCTTestRun
6
- from argus.backend.models.web import ArgusRelease, ArgusGroup, ArgusTest
7
-
8
- LOGGER = logging.getLogger(__name__)
9
-
10
-
11
- class ReleaseManagerException(Exception):
12
- pass
13
-
14
-
15
- class ReleaseEditPayload(TypedDict):
16
- id: str
17
- pretty_name: str
18
- description: str
19
- valid_version_regex: str | None
20
- enabled: bool
21
- perpetual: bool
22
- dormant: bool
23
-
24
-
25
- class ReleaseManagerService:
26
- def __init__(self) -> None:
27
- self.session = ScyllaCluster.get_session()
28
- self.database = ScyllaCluster.get()
29
- self.runs_by_build_id_stmt = self.database.prepare(
30
- "SELECT id, test_id, group_id, release_id, build_id, start_time "
31
- f"FROM {SCTTestRun.table_name()} WHERE build_id = ?"
32
- )
33
- self.update_run_stmt = self.database.prepare(
34
- f"UPDATE {SCTTestRun.table_name()} SET test_id = ?, group_id = ?, release_id = ? "
35
- "WHERE build_id = ? AND start_time = ?"
36
- )
37
-
38
- def get_releases(self) -> list[ArgusRelease]:
39
- return list(ArgusRelease.all())
40
-
41
- def get_groups(self, release_id: UUID) -> list[ArgusGroup]:
42
- return list(ArgusGroup.filter(release_id=release_id).all())
43
-
44
- def get_tests(self, group_id: UUID) -> list[ArgusTest]:
45
- return list(ArgusTest.filter(group_id=group_id).all())
46
-
47
- def toggle_test_enabled(self, test_id: UUID, new_state: bool) -> bool:
48
- test: ArgusTest = ArgusTest.get(id=test_id)
49
- test.enabled = new_state
50
- test.save()
51
-
52
- return test
53
-
54
- def toggle_group_enabled(self, group_id: UUID, new_state: bool) -> bool:
55
- test: ArgusGroup = ArgusGroup.get(id=group_id)
56
- test.enabled = new_state
57
- test.save()
58
-
59
- return test
60
-
61
- def create_release(self, release_name: str, pretty_name: str, perpetual: bool) -> ArgusRelease:
62
- try:
63
- release = ArgusRelease.get(name=release_name)
64
- except ArgusRelease.DoesNotExist:
65
- release = ArgusRelease()
66
- release.name = release_name
67
- release.pretty_name = pretty_name
68
- release.perpetual = perpetual
69
-
70
- release.save()
71
- else:
72
- raise ReleaseManagerException(
73
- f"Release {release_name} already exists!", release_name)
74
-
75
- return release
76
-
77
- def create_group(self, group_name: str, pretty_name: str, build_system_id: str,
78
- release_id: str) -> ArgusGroup:
79
- release = ArgusRelease.get(id=UUID(release_id))
80
-
81
- new_group = ArgusGroup()
82
- new_group.name = group_name
83
- new_group.pretty_name = pretty_name
84
- new_group.release_id = release.id
85
- new_group.build_system_id = build_system_id
86
- new_group.save()
87
-
88
- return new_group
89
-
90
- def create_test(self, test_name, pretty_name, build_id, build_url, group_id, release_id, plugin_name) -> ArgusTest:
91
- release = ArgusRelease.get(id=UUID(release_id))
92
- group = ArgusGroup.get(id=UUID(group_id))
93
-
94
- new_test = ArgusTest()
95
- new_test.name = test_name
96
- new_test.pretty_name = pretty_name
97
- new_test.build_system_id = build_id
98
- new_test.release_id = release.id
99
- new_test.group_id = group.id
100
- new_test.plugin_name = plugin_name
101
- new_test.build_system_url = build_url
102
- new_test.validate_build_system_id()
103
- new_test.save()
104
- self.move_test_runs(new_test)
105
- return new_test
106
-
107
- def delete_group(self, group_id: str, delete_tests: bool = True, new_group_id: str = "") -> bool:
108
- group_to_delete = ArgusGroup.get(id=UUID(group_id))
109
-
110
- tests_to_change = ArgusTest.filter(
111
- group_id=group_to_delete.id)
112
- if delete_tests:
113
- for test in tests_to_change.all():
114
- test.delete()
115
- else:
116
- new_group = ArgusGroup.get(id=UUID(new_group_id))
117
- for test in tests_to_change.all():
118
- test.group_id = new_group.id
119
- test.save()
120
-
121
- group_to_delete.delete()
122
-
123
- return True
124
-
125
- def delete_test(self, test_id: str) -> bool:
126
- test_to_delete = ArgusTest.get(id=test_id)
127
- test_to_delete.delete()
128
-
129
- return True
130
-
131
- def update_group(self, group_id: str, name: str, pretty_name: str, enabled: bool, build_system_id: str) -> bool:
132
- group = ArgusGroup.get(id=UUID(group_id))
133
-
134
- group.name = name
135
- group.build_system_id = build_system_id
136
- group.pretty_name = pretty_name
137
- group.enabled = enabled
138
-
139
- group.save()
140
-
141
- return True
142
-
143
- def update_test(self, test_id: str, name: str, pretty_name: str, plugin_name: str,
144
- enabled: bool, build_system_id: str, build_system_url: str, group_id) -> bool:
145
- test: ArgusTest = ArgusTest.get(id=UUID(test_id))
146
- group = ArgusGroup.get(id=UUID(group_id))
147
-
148
- test.name = name
149
- test.pretty_name = pretty_name
150
- test.plugin_name = plugin_name
151
- test.enabled = enabled
152
- test.build_system_id = build_system_id
153
- test.build_system_url = build_system_url
154
- if test.group_id != group.id:
155
- test.group_id = group.id
156
- LOGGER.info("Relocating old test runs into a new group")
157
-
158
- test.validate_build_system_id()
159
- test.save()
160
- self.move_test_runs(test)
161
- return True
162
-
163
- def set_release_state(self, release_id: str, state: bool) -> bool:
164
- release = ArgusRelease.get(id=UUID(release_id))
165
- release.enabled = state
166
- release.save()
167
-
168
- return True
169
-
170
- def set_release_dormancy(self, release_id: str, dormant: bool) -> bool:
171
- release = ArgusRelease.get(id=UUID(release_id))
172
- release.dormant = dormant
173
- release.save()
174
-
175
- return True
176
-
177
- def set_release_perpetuality(self, release_id: str, perpetual: bool) -> bool:
178
- release = ArgusRelease.get(id=UUID(release_id))
179
- release.perpetual = perpetual
180
- release.save()
181
-
182
- return True
183
-
184
- def edit_release(self, payload: ReleaseEditPayload) -> bool:
185
-
186
- release: ArgusRelease = ArgusRelease.get(id=payload["id"])
187
- release.pretty_name = payload["pretty_name"]
188
- release.perpetual = payload["perpetual"]
189
- release.enabled = payload["enabled"]
190
- release.dormant = payload["dormant"]
191
- release.description = payload["description"]
192
- release.valid_version_regex = payload["valid_version_regex"]
193
-
194
-
195
- release.save()
196
- return True
197
-
198
- def delete_release(self, release_id: str) -> bool:
199
-
200
- release: ArgusRelease = ArgusRelease.get(id=release_id)
201
-
202
- release_groups = ArgusGroup.filter(release_id=release.id)
203
- release_tests = ArgusTest.filter(release_id=release.id)
204
-
205
- for entity in [*release_groups.all(), *release_tests.all()]:
206
- entity.delete()
207
-
208
- release.delete()
209
- return True
210
-
211
- def batch_move_tests(self, new_group_id: str, tests: list[str]) -> bool:
212
- group = ArgusGroup.get(id=UUID(new_group_id))
213
-
214
- tests: list[ArgusTest] = [ArgusTest.get(id=UUID(test_id)) for test_id in tests]
215
-
216
- for test in tests:
217
- test.group_id = group.id
218
- test.save()
219
- self.move_test_runs(test)
220
-
221
- return True
222
-
223
- def move_test_runs(self, test: ArgusTest) -> None:
224
- run_rows = self.session.execute(self.runs_by_build_id_stmt, parameters=(
225
- test.build_system_id,), execution_profile="read_fast")
226
- for run in run_rows:
227
- run["test_id"] = test.id
228
- run["group_id"] = test.group_id
229
- run["release_id"] = test.release_id
230
- self.session.execute(self.update_run_stmt, parameters=run)