argus-alm 0.12.3__py3-none-any.whl → 0.12.4b1__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.
- argus/backend/controller/admin_api.py +26 -0
- argus/backend/controller/api.py +26 -1
- argus/backend/controller/main.py +21 -0
- argus/backend/controller/testrun_api.py +16 -0
- argus/backend/controller/view_api.py +162 -0
- argus/backend/models/web.py +16 -0
- argus/backend/plugins/core.py +25 -10
- argus/backend/plugins/driver_matrix_tests/controller.py +39 -0
- argus/backend/plugins/driver_matrix_tests/model.py +251 -3
- argus/backend/plugins/driver_matrix_tests/raw_types.py +27 -0
- argus/backend/plugins/driver_matrix_tests/service.py +18 -0
- argus/backend/plugins/driver_matrix_tests/udt.py +14 -13
- argus/backend/plugins/generic/model.py +5 -2
- argus/backend/plugins/sct/service.py +13 -1
- argus/backend/service/argus_service.py +116 -20
- argus/backend/service/build_system_monitor.py +37 -7
- argus/backend/service/jenkins_service.py +2 -1
- argus/backend/service/release_manager.py +14 -0
- argus/backend/service/stats.py +147 -11
- argus/backend/service/testrun.py +44 -5
- argus/backend/service/views.py +258 -0
- argus/backend/template_filters.py +7 -0
- argus/backend/util/common.py +14 -2
- argus/client/driver_matrix_tests/cli.py +110 -0
- argus/client/driver_matrix_tests/client.py +56 -193
- argus_alm-0.12.4b1.dist-info/METADATA +129 -0
- {argus_alm-0.12.3.dist-info → argus_alm-0.12.4b1.dist-info}/RECORD +30 -27
- {argus_alm-0.12.3.dist-info → argus_alm-0.12.4b1.dist-info}/entry_points.txt +1 -0
- argus_alm-0.12.3.dist-info/METADATA +0 -207
- {argus_alm-0.12.3.dist-info → argus_alm-0.12.4b1.dist-info}/LICENSE +0 -0
- {argus_alm-0.12.3.dist-info → argus_alm-0.12.4b1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import logging
|
|
3
|
+
import re
|
|
4
|
+
from functools import partial, reduce
|
|
5
|
+
from typing import Any, Callable, TypedDict
|
|
6
|
+
from urllib.parse import unquote
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
from cassandra.cqlengine.models import Model
|
|
10
|
+
from argus.backend.models.web import ArgusGroup, ArgusRelease, ArgusTest, ArgusUserView, User
|
|
11
|
+
from argus.backend.plugins.loader import all_plugin_models
|
|
12
|
+
from argus.backend.util.common import chunk, current_user
|
|
13
|
+
|
|
14
|
+
LOGGER = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class UserViewException(Exception):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ViewUpdateRequest(TypedDict):
|
|
22
|
+
name: str
|
|
23
|
+
description: str
|
|
24
|
+
display_name: str
|
|
25
|
+
tests: list[str]
|
|
26
|
+
widget_settings: str
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class UserViewService:
|
|
30
|
+
ADD_ALL_ID = UUID("db6f33b2-660b-4639-ba7f-79725ef96616")
|
|
31
|
+
def create_view(self, name: str, items: list[str], widget_settings: str, description: str = None, display_name: str = None) -> ArgusUserView:
|
|
32
|
+
try:
|
|
33
|
+
name_check = ArgusUserView.get(name=name)
|
|
34
|
+
raise UserViewException(f"View with name {name} already exists: {name_check.id}", name, name_check, name_check.id)
|
|
35
|
+
except ArgusUserView.DoesNotExist:
|
|
36
|
+
pass
|
|
37
|
+
view = ArgusUserView()
|
|
38
|
+
view.name = name
|
|
39
|
+
view.display_name = display_name or name
|
|
40
|
+
view.description = description
|
|
41
|
+
view.widget_settings = widget_settings
|
|
42
|
+
view.tests = []
|
|
43
|
+
for entity in items:
|
|
44
|
+
entity_type, entity_id = entity.split(":")
|
|
45
|
+
match (entity_type):
|
|
46
|
+
case "release":
|
|
47
|
+
view.tests.extend(t.id for t in ArgusTest.filter(release_id=entity_id).all())
|
|
48
|
+
view.release_ids.append(entity_id)
|
|
49
|
+
case "group":
|
|
50
|
+
view.tests.extend(t.id for t in ArgusTest.filter(group_id=entity_id).all())
|
|
51
|
+
view.group_ids.append(entity_id)
|
|
52
|
+
case "test":
|
|
53
|
+
view.tests.append(entity_id)
|
|
54
|
+
view.user_id = current_user().id
|
|
55
|
+
|
|
56
|
+
view.save()
|
|
57
|
+
return view
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def index_mapper(item: Model, type = "test"):
|
|
61
|
+
mapped = dict(item)
|
|
62
|
+
mapped["type"] = type
|
|
63
|
+
return mapped
|
|
64
|
+
|
|
65
|
+
def test_lookup(self, query: str):
|
|
66
|
+
def check_visibility(entity: dict):
|
|
67
|
+
if not entity["enabled"]:
|
|
68
|
+
return False
|
|
69
|
+
if entity.get("group") and not entity["group"]["enabled"]:
|
|
70
|
+
return False
|
|
71
|
+
if entity.get("release") and not entity["release"]["enabled"]:
|
|
72
|
+
return False
|
|
73
|
+
return True
|
|
74
|
+
|
|
75
|
+
def facet_extraction(query: str) -> str:
|
|
76
|
+
extractor = re.compile(r"(?:(?P<name>(?:release|group|type)):(?P<value>\"?[\w\d\.\-]*\"?))")
|
|
77
|
+
facets = re.findall(extractor, query)
|
|
78
|
+
|
|
79
|
+
return (re.sub(extractor, "", query).strip(), facets)
|
|
80
|
+
|
|
81
|
+
def type_facet_filter(item: dict, key: str, facet_query: str):
|
|
82
|
+
entity_type: str = item[key]
|
|
83
|
+
return facet_query.lower() == entity_type
|
|
84
|
+
|
|
85
|
+
def facet_filter(item: dict, key: str, facet_query: str):
|
|
86
|
+
if entity := item.get(key):
|
|
87
|
+
name: str = entity.get("pretty_name") or entity.get("name")
|
|
88
|
+
return facet_query.lower() in name.lower() if name else False
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
def facet_wrapper(query_func: Callable[[dict], bool], facet_query: str, facet_type: str) -> bool:
|
|
92
|
+
def inner(item: dict, query: str):
|
|
93
|
+
return query_func(item, query) and facet_funcs[facet_type](item, facet_type, facet_query)
|
|
94
|
+
return inner
|
|
95
|
+
|
|
96
|
+
facet_funcs = {
|
|
97
|
+
"type": type_facet_filter,
|
|
98
|
+
"release": facet_filter,
|
|
99
|
+
"group": facet_filter,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
def index_searcher(item, query: str):
|
|
103
|
+
name: str = item["pretty_name"] or item["name"]
|
|
104
|
+
return unquote(query).lower() in name.lower() if query else True
|
|
105
|
+
|
|
106
|
+
text_query, facets = facet_extraction(query)
|
|
107
|
+
search_func = index_searcher
|
|
108
|
+
for facet, value in facets:
|
|
109
|
+
if facet in facet_funcs.keys():
|
|
110
|
+
search_func = facet_wrapper(query_func=search_func, facet_query=value, facet_type=facet)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
all_tests = ArgusTest.all()
|
|
114
|
+
all_releases = ArgusRelease.all()
|
|
115
|
+
all_groups = ArgusGroup.all()
|
|
116
|
+
release_by_id = {release.id: partial(self.index_mapper, type="release")(release) for release in all_releases}
|
|
117
|
+
group_by_id = {group.id: partial(self.index_mapper, type="group")(group) for group in all_groups}
|
|
118
|
+
index = [self.index_mapper(t) for t in all_tests]
|
|
119
|
+
index = [*release_by_id.values(), *group_by_id.values(), *index]
|
|
120
|
+
for item in index:
|
|
121
|
+
item["group"] = group_by_id.get(item.get("group_id"))
|
|
122
|
+
item["release"] = release_by_id.get(item.get("release_id"))
|
|
123
|
+
|
|
124
|
+
results = filter(partial(search_func, query=text_query), index)
|
|
125
|
+
|
|
126
|
+
return [{ "id": self.ADD_ALL_ID, "name": "Add all...", "type": "special" }, *list(res for res in results if check_visibility(res))]
|
|
127
|
+
|
|
128
|
+
def update_view(self, view_id: str | UUID, update_data: ViewUpdateRequest) -> bool:
|
|
129
|
+
view: ArgusUserView = ArgusUserView.get(id=view_id)
|
|
130
|
+
if view.user_id != current_user().id and not current_user().is_admin():
|
|
131
|
+
raise UserViewException("Unable to modify other users' views")
|
|
132
|
+
for key in ["user_id", "id"]:
|
|
133
|
+
update_data.pop(key, None)
|
|
134
|
+
items = update_data.pop("items")
|
|
135
|
+
for k, value in update_data.items():
|
|
136
|
+
view[k] = value
|
|
137
|
+
view.tests = []
|
|
138
|
+
view.release_ids = []
|
|
139
|
+
view.group_ids = []
|
|
140
|
+
for entity in items:
|
|
141
|
+
entity_type, entity_id = entity.split(":")
|
|
142
|
+
match (entity_type):
|
|
143
|
+
case "release":
|
|
144
|
+
view.tests.extend(t.id for t in ArgusTest.filter(release_id=entity_id).all())
|
|
145
|
+
view.release_ids.append(entity_id)
|
|
146
|
+
case "group":
|
|
147
|
+
view.tests.extend(t.id for t in ArgusTest.filter(group_id=entity_id).all())
|
|
148
|
+
view.group_ids.append(entity_id)
|
|
149
|
+
case "test":
|
|
150
|
+
view.tests.append(entity_id)
|
|
151
|
+
view.last_updated = datetime.datetime.utcnow()
|
|
152
|
+
view.save()
|
|
153
|
+
return True
|
|
154
|
+
|
|
155
|
+
def delete_view(self, view_id: str | UUID) -> bool:
|
|
156
|
+
view = ArgusUserView.get(id=view_id)
|
|
157
|
+
if view.user_id != current_user().id and not current_user().is_admin():
|
|
158
|
+
raise UserViewException("Unable to modify other users' views")
|
|
159
|
+
view.delete()
|
|
160
|
+
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
def get_view(self, view_id: str | UUID) -> ArgusUserView:
|
|
164
|
+
view: ArgusUserView = ArgusUserView.get(id=view_id)
|
|
165
|
+
if datetime.datetime.utcnow() - (view.last_updated or datetime.datetime.fromtimestamp(0)) > datetime.timedelta(hours=1):
|
|
166
|
+
self.refresh_stale_view(view)
|
|
167
|
+
return view
|
|
168
|
+
|
|
169
|
+
def get_view_by_name(self, view_name: str) -> ArgusUserView:
|
|
170
|
+
view: ArgusUserView = ArgusUserView.get(name=view_name)
|
|
171
|
+
if datetime.datetime.utcnow() - (view.last_updated or datetime.datetime.fromtimestamp(0)) > datetime.timedelta(hours=1):
|
|
172
|
+
self.refresh_stale_view(view)
|
|
173
|
+
return view
|
|
174
|
+
|
|
175
|
+
def get_all_views(self, user: User | None = None) -> list[ArgusUserView]:
|
|
176
|
+
if user:
|
|
177
|
+
return list(ArgusUserView.filter(user_id=user.id).all())
|
|
178
|
+
return list(ArgusUserView.filter().all())
|
|
179
|
+
|
|
180
|
+
def resolve_view_tests(self, view_id: str | UUID) -> list[ArgusTest]:
|
|
181
|
+
view = ArgusUserView.get(id=view_id)
|
|
182
|
+
return self.resolve_tests_by_id(view.tests)
|
|
183
|
+
|
|
184
|
+
def resolve_tests_by_id(self, test_ids: list[str | UUID]) -> list[ArgusTest]:
|
|
185
|
+
tests = []
|
|
186
|
+
for batch in chunk(test_ids):
|
|
187
|
+
tests.extend(ArgusTest.filter(id__in=batch).all())
|
|
188
|
+
|
|
189
|
+
return tests
|
|
190
|
+
|
|
191
|
+
def batch_resolve_entity(self, entity: Model, param_name: str, entity_ids: list[UUID]) -> list[Model]:
|
|
192
|
+
result = []
|
|
193
|
+
for batch in chunk(entity_ids):
|
|
194
|
+
result.extend(entity.filter(**{f"{param_name}__in": batch}).allow_filtering().all())
|
|
195
|
+
return result
|
|
196
|
+
|
|
197
|
+
def refresh_stale_view(self, view: ArgusUserView):
|
|
198
|
+
view.tests = [test.id for test in self.resolve_view_tests(view.id)]
|
|
199
|
+
all_tests = set(view.tests)
|
|
200
|
+
all_tests.update(test.id for test in self.batch_resolve_entity(ArgusTest, "group_id", view.group_ids))
|
|
201
|
+
all_tests.update(test.id for test in self.batch_resolve_entity(ArgusTest, "release_id", view.release_ids))
|
|
202
|
+
view.tests = list(all_tests)
|
|
203
|
+
view.last_updated = datetime.datetime.utcnow()
|
|
204
|
+
view.save()
|
|
205
|
+
|
|
206
|
+
return view
|
|
207
|
+
|
|
208
|
+
def resolve_releases_for_tests(self, tests: list[ArgusTest]):
|
|
209
|
+
releases = []
|
|
210
|
+
unique_release_ids = reduce(lambda releases, test: releases.add(test.release_id) or releases, tests, set())
|
|
211
|
+
for batch in chunk(unique_release_ids):
|
|
212
|
+
releases.extend(ArgusRelease.filter(id__in=batch).all())
|
|
213
|
+
|
|
214
|
+
return releases
|
|
215
|
+
|
|
216
|
+
def resolve_groups_for_tests(self, tests: list[ArgusTest]):
|
|
217
|
+
releases = []
|
|
218
|
+
unique_release_ids = reduce(lambda groups, test: groups.add(test.group_id) or groups, tests, set())
|
|
219
|
+
for batch in chunk(unique_release_ids):
|
|
220
|
+
releases.extend(ArgusGroup.filter(id__in=batch).all())
|
|
221
|
+
|
|
222
|
+
return releases
|
|
223
|
+
|
|
224
|
+
def get_versions_for_view(self, view_id: str | UUID) -> list[str]:
|
|
225
|
+
tests = self.resolve_view_tests(view_id)
|
|
226
|
+
unique_versions = {ver for plugin in all_plugin_models()
|
|
227
|
+
for ver in plugin.get_distinct_versions_for_view(tests=tests)}
|
|
228
|
+
|
|
229
|
+
return sorted(list(unique_versions), reverse=True)
|
|
230
|
+
|
|
231
|
+
def resolve_view_for_edit(self, view_id: str | UUID) -> dict:
|
|
232
|
+
view: ArgusUserView = ArgusUserView.get(id=view_id)
|
|
233
|
+
resolved = dict(view)
|
|
234
|
+
view_groups = self.batch_resolve_entity(ArgusGroup, "id", view.group_ids)
|
|
235
|
+
view_releases = self.batch_resolve_entity(ArgusRelease, "id", view.release_ids)
|
|
236
|
+
view_tests = self.resolve_view_tests(view.id)
|
|
237
|
+
all_groups = { group.id: partial(self.index_mapper, type="group")(group) for group in self.resolve_releases_for_tests(view_tests) }
|
|
238
|
+
all_releases ={ release.id: partial(self.index_mapper, type="release")(release) for release in self.resolve_releases_for_tests(view_tests) }
|
|
239
|
+
entities_by_id = {
|
|
240
|
+
entity.id: partial(self.index_mapper, type="release" if isinstance(entity, ArgusRelease) else "group")(entity)
|
|
241
|
+
for container in [view_releases, view_groups]
|
|
242
|
+
for entity in container
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
items = []
|
|
246
|
+
for test in view_tests:
|
|
247
|
+
if not (entities_by_id.get(test.group_id) or entities_by_id.get(test.release_id)):
|
|
248
|
+
item = dict(test)
|
|
249
|
+
item["type"] = "test"
|
|
250
|
+
items.append(item)
|
|
251
|
+
|
|
252
|
+
items = [*entities_by_id.values(), *items]
|
|
253
|
+
for entity in items:
|
|
254
|
+
entity["group"] = all_groups.get(entity.get("group_id"), {}).get("pretty_name") or all_groups.get(entity.get("group_id"), {}).get("name")
|
|
255
|
+
entity["release"] = all_releases.get(entity.get("release_id"), {}).get("pretty_name") or all_releases.get(entity.get("release_id"), {}).get("name")
|
|
256
|
+
|
|
257
|
+
resolved["items"] = items
|
|
258
|
+
return resolved
|
|
@@ -18,3 +18,10 @@ def safe_user(user: User):
|
|
|
18
18
|
user_dict = dict(user.items())
|
|
19
19
|
del user_dict["password"]
|
|
20
20
|
return user_dict
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@is_filter("formatted_date")
|
|
24
|
+
def formatted_date(date: datetime | None):
|
|
25
|
+
if date:
|
|
26
|
+
return date.strftime("%d/%m/%Y %H:%M:%S")
|
|
27
|
+
return "#unknown"
|
argus/backend/util/common.py
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from itertools import islice
|
|
1
2
|
import logging
|
|
2
|
-
from typing import Callable
|
|
3
|
+
from typing import Callable, Iterable
|
|
3
4
|
from uuid import UUID
|
|
4
5
|
|
|
5
|
-
from flask import Request, Response
|
|
6
|
+
from flask import Request, Response, g
|
|
7
|
+
|
|
8
|
+
from argus.backend.models.web import User
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
LOGGER = logging.getLogger(__name__)
|
|
@@ -20,6 +23,11 @@ def first(iterable, value, key: Callable = None, predicate: Callable = None):
|
|
|
20
23
|
return None
|
|
21
24
|
|
|
22
25
|
|
|
26
|
+
def chunk(iterable: Iterable, slice_size = 90):
|
|
27
|
+
it = iter(iterable)
|
|
28
|
+
return iter(lambda: list(islice(it, slice_size)), [])
|
|
29
|
+
|
|
30
|
+
|
|
23
31
|
def check_scheduled_test(test, group, testname):
|
|
24
32
|
return testname in (f"{group}/{test}", test)
|
|
25
33
|
|
|
@@ -43,6 +51,10 @@ def get_payload(client_request: Request) -> dict:
|
|
|
43
51
|
return request_payload
|
|
44
52
|
|
|
45
53
|
|
|
54
|
+
def current_user() -> User:
|
|
55
|
+
return g.user
|
|
56
|
+
|
|
57
|
+
|
|
46
58
|
def get_build_number(build_job_url: str) -> int | None:
|
|
47
59
|
build_number = build_job_url.rstrip("/").split("/")[-1] if build_job_url else -1
|
|
48
60
|
if build_number:
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import json
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import click
|
|
5
|
+
import logging
|
|
6
|
+
from argus.backend.util.enums import TestStatus
|
|
7
|
+
|
|
8
|
+
from argus.client.driver_matrix_tests.client import ArgusDriverMatrixClient
|
|
9
|
+
|
|
10
|
+
LOGGER = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group
|
|
14
|
+
def cli():
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _submit_driver_result_internal(api_key: str, base_url: str, run_id: str, metadata_path: str):
|
|
19
|
+
metadata = json.loads(Path(metadata_path).read_text(encoding="utf-8"))
|
|
20
|
+
LOGGER.info("Submitting results for %s [%s/%s] to Argus...", run_id, metadata["driver_name"], metadata["driver_type"])
|
|
21
|
+
raw_xml = Path(metadata["junit_result"]).read_bytes()
|
|
22
|
+
client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
|
|
23
|
+
client.submit_driver_result(driver_name=metadata["driver_name"], driver_type=metadata["driver_type"], raw_junit_data=base64.encodebytes(raw_xml))
|
|
24
|
+
LOGGER.info("Done.")
|
|
25
|
+
|
|
26
|
+
def _submit_driver_failure_internal(api_key: str, base_url: str, run_id: str, metadata_path: str):
|
|
27
|
+
metadata = json.loads(Path(metadata_path).read_text(encoding="utf-8"))
|
|
28
|
+
LOGGER.info("Submitting failure for %s [%s/%s] to Argus...", run_id, metadata["driver_name"], metadata["driver_type"])
|
|
29
|
+
client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
|
|
30
|
+
client.submit_driver_failure(driver_name=metadata["driver_name"], driver_type=metadata["driver_type"], failure_reason=metadata["failure_reason"])
|
|
31
|
+
LOGGER.info("Done.")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@click.command("submit-run")
|
|
35
|
+
@click.option("--api-key", help="Argus API key for authorization", required=True)
|
|
36
|
+
@click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
|
|
37
|
+
@click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
|
|
38
|
+
@click.option("--build-id", required=True, help="Unique job identifier in the build system, e.g. scylla-master/group/job for jenkins (The full path)")
|
|
39
|
+
@click.option("--build-url", required=True, help="Job URL in the build system")
|
|
40
|
+
def submit_driver_matrix_run(api_key: str, base_url: str, run_id: str, build_id: str, build_url: str):
|
|
41
|
+
LOGGER.info("Submitting %s (%s) to Argus...", build_id, run_id)
|
|
42
|
+
client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
|
|
43
|
+
client.submit_driver_matrix_run(job_name=build_id, job_url=build_url)
|
|
44
|
+
LOGGER.info("Done.")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@click.command("submit-driver")
|
|
48
|
+
@click.option("--api-key", help="Argus API key for authorization", required=True)
|
|
49
|
+
@click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
|
|
50
|
+
@click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
|
|
51
|
+
@click.option("--metadata-path", required=True, help="Path to the metadata .json file that contains path to junit xml and other required information")
|
|
52
|
+
def submit_driver_result(api_key: str, base_url: str, run_id: str, metadata_path: str):
|
|
53
|
+
_submit_driver_result_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@click.command("fail-driver")
|
|
57
|
+
@click.option("--api-key", help="Argus API key for authorization", required=True)
|
|
58
|
+
@click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
|
|
59
|
+
@click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
|
|
60
|
+
@click.option("--metadata-path", required=True, help="Path to the metadata .json file that contains path to junit xml and other required information")
|
|
61
|
+
def submit_driver_failure(api_key: str, base_url: str, run_id: str, metadata_path: str):
|
|
62
|
+
_submit_driver_failure_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@click.command("submit-or-fail-driver")
|
|
66
|
+
@click.option("--api-key", help="Argus API key for authorization", required=True)
|
|
67
|
+
@click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
|
|
68
|
+
@click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
|
|
69
|
+
@click.option("--metadata-path", required=True, help="Path to the metadata .json file that contains path to junit xml and other required information")
|
|
70
|
+
def submit_or_fail_driver(api_key: str, base_url: str, run_id: str, metadata_path: str):
|
|
71
|
+
metadata = json.loads(Path(metadata_path).read_text(encoding="utf-8"))
|
|
72
|
+
if metadata.get("failure_reason"):
|
|
73
|
+
_submit_driver_failure_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path)
|
|
74
|
+
else:
|
|
75
|
+
_submit_driver_result_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@click.command("submit-env")
|
|
79
|
+
@click.option("--api-key", help="Argus API key for authorization", required=True)
|
|
80
|
+
@click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
|
|
81
|
+
@click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
|
|
82
|
+
@click.option("--env-path", required=True, help="Path to the Build-00.txt file that contains environment information about Scylla")
|
|
83
|
+
def submit_driver_env(api_key: str, base_url: str, run_id: str, env_path: str):
|
|
84
|
+
LOGGER.info("Submitting environment for run %s to Argus...", run_id)
|
|
85
|
+
raw_env = Path(env_path).read_text()
|
|
86
|
+
client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
|
|
87
|
+
client.submit_env(raw_env)
|
|
88
|
+
LOGGER.info("Done.")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@click.command("finish-run")
|
|
92
|
+
@click.option("--api-key", help="Argus API key for authorization", required=True)
|
|
93
|
+
@click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
|
|
94
|
+
@click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
|
|
95
|
+
@click.option("--status", required=True, help="Resulting job status")
|
|
96
|
+
def finish_driver_matrix_run(api_key: str, base_url: str, run_id: str, status: str):
|
|
97
|
+
client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
|
|
98
|
+
client.finalize_run(run_type=ArgusDriverMatrixClient.test_type, run_id=run_id, body={"status": TestStatus(status)})
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
cli.add_command(submit_driver_matrix_run)
|
|
102
|
+
cli.add_command(submit_driver_result)
|
|
103
|
+
cli.add_command(submit_or_fail_driver)
|
|
104
|
+
cli.add_command(submit_driver_failure)
|
|
105
|
+
cli.add_command(submit_driver_env)
|
|
106
|
+
cli.add_command(finish_driver_matrix_run)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
cli()
|