argus-alm 0.13.1__tar.gz → 0.14.1__tar.gz

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.
@@ -1,14 +1,16 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: argus-alm
3
- Version: 0.13.1
3
+ Version: 0.14.1
4
4
  Summary: Argus
5
5
  Home-page: https://github.com/scylladb/argus
6
6
  License: Apache-2.0
7
7
  Author: Alexey Kartashov
8
8
  Author-email: alexey.kartashov@scylladb.com
9
- Requires-Python: >=3.12,<4.0
9
+ Requires-Python: >=3.10,<4.0
10
10
  Classifier: License :: OSI Approved :: Apache Software License
11
11
  Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
12
14
  Classifier: Programming Language :: Python :: 3.12
13
15
  Requires-Dist: click (>=8.1.3,<9.0.0)
14
16
  Requires-Dist: requests (>=2.26.0,<3.0.0)
@@ -34,15 +34,20 @@ class ArgusClient:
34
34
  FETCH_RESULTS = "/testrun/$type/$id/fetch_results"
35
35
  FINALIZE = "/testrun/$type/$id/finalize"
36
36
 
37
- def __init__(self, auth_token: str, base_url: str, api_version="v1") -> None:
37
+ def __init__(self, auth_token: str, base_url: str, api_version="v1", extra_headers: dict | None = None) -> None:
38
38
  self._auth_token = auth_token
39
39
  self._base_url = base_url
40
40
  self._api_ver = api_version
41
+ self._extra_headers = extra_headers or {}
41
42
 
42
43
  @property
43
44
  def auth_token(self) -> str:
44
45
  return self._auth_token
45
46
 
47
+ @property
48
+ def extra_headers(self) -> dict:
49
+ return self._extra_headers
50
+
46
51
  def verify_location_params(self, endpoint: str, location_params: dict[str, str]) -> bool:
47
52
  required_params: list[str] = re.findall(r"\$[\w_]+", endpoint)
48
53
  for param in required_params:
@@ -88,6 +93,7 @@ class ArgusClient:
88
93
  "Authorization": f"token {self.auth_token}",
89
94
  "Accept": "application/json",
90
95
  "Content-Type": "application/json",
96
+ **self.extra_headers,
91
97
  }
92
98
 
93
99
  def get(self, endpoint: str, location_params: dict[str, str] = None, params: dict = None) -> requests.Response:
@@ -6,6 +6,7 @@ import logging
6
6
  from argus.common.enums import TestStatus
7
7
 
8
8
  from argus.client.driver_matrix_tests.client import ArgusDriverMatrixClient
9
+ from argus.client.generic.cli import validate_extra_headers
9
10
 
10
11
  LOGGER = logging.getLogger(__name__)
11
12
 
@@ -15,81 +16,87 @@ def cli():
15
16
  pass
16
17
 
17
18
 
18
- def _submit_driver_result_internal(api_key: str, base_url: str, run_id: str, metadata_path: str):
19
+ def _submit_driver_result_internal(api_key: str, base_url: str, run_id: str, metadata_path: str, extra_headers: dict):
19
20
  metadata = json.loads(Path(metadata_path).read_text(encoding="utf-8"))
20
21
  LOGGER.info("Submitting results for %s [%s/%s] to Argus...", run_id, metadata["driver_name"], metadata["driver_type"])
21
22
  raw_xml = (Path(metadata_path).parent / metadata["junit_result"]).read_bytes()
22
- client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
23
+ client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
23
24
  client.submit_driver_result(driver_name=metadata["driver_name"], driver_type=metadata["driver_type"], raw_junit_data=base64.encodebytes(raw_xml))
24
25
  LOGGER.info("Done.")
25
26
 
26
- def _submit_driver_failure_internal(api_key: str, base_url: str, run_id: str, metadata_path: str):
27
+ def _submit_driver_failure_internal(api_key: str, base_url: str, run_id: str, metadata_path: str, extra_headers: dict):
27
28
  metadata = json.loads(Path(metadata_path).read_text(encoding="utf-8"))
28
29
  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 = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
30
31
  client.submit_driver_failure(driver_name=metadata["driver_name"], driver_type=metadata["driver_type"], failure_reason=metadata["failure_reason"])
31
32
  LOGGER.info("Done.")
32
33
 
33
34
 
34
35
  @click.command("submit-run")
35
- @click.option("--api-key", help="Argus API key for authorization", required=True)
36
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
37
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
36
38
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
37
39
  @click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
38
40
  @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
41
  @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):
42
+ def submit_driver_matrix_run(api_key: str, base_url: str, run_id: str, build_id: str, build_url: str, extra_headers: dict):
41
43
  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)
44
+ client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
43
45
  client.submit_driver_matrix_run(job_name=build_id, job_url=build_url)
44
46
  LOGGER.info("Done.")
45
47
 
46
48
 
47
49
  @click.command("submit-driver")
48
- @click.option("--api-key", help="Argus API key for authorization", required=True)
50
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
51
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
49
52
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
50
53
  @click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
51
54
  @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)
55
+ def submit_driver_result(api_key: str, base_url: str, run_id: str, metadata_path: str, extra_headers: dict):
56
+ _submit_driver_result_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path, extra_headers=extra_headers)
54
57
 
55
58
 
56
59
  @click.command("fail-driver")
57
- @click.option("--api-key", help="Argus API key for authorization", required=True)
60
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
61
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
58
62
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
59
63
  @click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
60
64
  @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)
65
+ def submit_driver_failure(api_key: str, base_url: str, run_id: str, metadata_path: str, extra_headers: dict):
66
+ _submit_driver_failure_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path, extra_headers=extra_headers)
63
67
 
64
68
 
65
69
  @click.command("submit-or-fail-driver")
66
- @click.option("--api-key", help="Argus API key for authorization", required=True)
70
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
71
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
67
72
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
68
73
  @click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
69
74
  @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):
75
+ def submit_or_fail_driver(api_key: str, base_url: str, run_id: str, metadata_path: str, extra_headers: dict):
71
76
  metadata = json.loads(Path(metadata_path).read_text(encoding="utf-8"))
72
77
  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)
78
+ _submit_driver_failure_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path, extra_headers=extra_headers)
74
79
  else:
75
- _submit_driver_result_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path)
80
+ _submit_driver_result_internal(api_key=api_key, base_url=base_url, run_id=run_id, metadata_path=metadata_path, extra_headers=extra_headers)
76
81
 
77
82
 
78
83
  @click.command("submit-env")
79
- @click.option("--api-key", help="Argus API key for authorization", required=True)
84
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
85
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
80
86
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
81
87
  @click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
82
88
  @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):
89
+ def submit_driver_env(api_key: str, base_url: str, run_id: str, env_path: str, extra_headers: dict):
84
90
  LOGGER.info("Submitting environment for run %s to Argus...", run_id)
85
91
  raw_env = Path(env_path).read_text()
86
- client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url)
92
+ client = ArgusDriverMatrixClient(run_id=run_id, auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
87
93
  client.submit_env(raw_env)
88
94
  LOGGER.info("Done.")
89
95
 
90
96
 
91
97
  @click.command("finish-run")
92
- @click.option("--api-key", help="Argus API key for authorization", required=True)
98
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
99
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
93
100
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
94
101
  @click.option("--id", "run_id", required=True, help="UUID (v4 or v1) unique to the job")
95
102
  @click.option("--status", required=True, help="Resulting job status")
@@ -12,8 +12,8 @@ class ArgusDriverMatrixClient(ArgusClient):
12
12
  SUBMIT_DRIVER_FAILURE = "/driver_matrix/result/fail"
13
13
  SUBMIT_ENV = "/driver_matrix/env/submit"
14
14
 
15
- def __init__(self, run_id: UUID, auth_token: str, base_url: str, api_version="v1") -> None:
16
- super().__init__(auth_token, base_url, api_version)
15
+ def __init__(self, run_id: UUID, auth_token: str, base_url: str, api_version="v1", extra_headers: dict | None = None) -> None:
16
+ super().__init__(auth_token, base_url, api_version, extra_headers=extra_headers)
17
17
  self.run_id = run_id
18
18
 
19
19
  def submit_driver_matrix_run(self, job_name: str, job_url: str) -> None:
@@ -1,4 +1,5 @@
1
1
  import json
2
+ from json.decoder import JSONDecodeError
2
3
  from pathlib import Path
3
4
  import click
4
5
  import logging
@@ -8,6 +9,15 @@ from argus.client.generic.client import ArgusGenericClient
8
9
 
9
10
  LOGGER = logging.getLogger(__name__)
10
11
 
12
+ def validate_extra_headers(ctx, param, value):
13
+ if isinstance(value, dict):
14
+ return value
15
+
16
+ try:
17
+ return json.loads(value)
18
+ except JSONDecodeError as ex:
19
+ raise click.BadParameter(f"--extra-headers should be in json format:\n\n{value}\n\n{ex}")
20
+
11
21
 
12
22
  @click.group
13
23
  def cli():
@@ -15,41 +25,44 @@ def cli():
15
25
 
16
26
 
17
27
  @click.command("submit")
18
- @click.option("--api-key", help="Argus API key for authorization", required=True)
28
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
19
29
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
20
30
  @click.option("--id", required=True, help="UUID (v4 or v1) unique to the job")
21
31
  @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)")
22
32
  @click.option("--build-url", required=True, help="Job URL in the build system")
23
33
  @click.option("--started-by", required=True, help="Username of the user who started the job")
24
34
  @click.option("--scylla-version", required=False, default=None, help="Version of Scylla used for this job")
25
- def submit_run(api_key: str, base_url: str, id: str, build_id: str, build_url: str, started_by: str, scylla_version: str = None):
35
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
36
+ def submit_run(api_key: str, base_url: str, id: str, build_id: str, build_url: str, started_by: str, scylla_version: str = None, extra_headers: dict | None = None):
26
37
  LOGGER.info("Submitting %s (%s) to Argus...", build_id, id)
27
- client = ArgusGenericClient(auth_token=api_key, base_url=base_url)
38
+ client = ArgusGenericClient(auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
28
39
  client.submit_generic_run(build_id=build_id, run_id=id, started_by=started_by, build_url=build_url, scylla_version=scylla_version)
29
40
  LOGGER.info("Done.")
30
41
 
31
42
 
32
43
  @click.command("finish")
33
- @click.option("--api-key", help="Argus API key for authorization", required=True)
44
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
34
45
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
35
46
  @click.option("--id", required=True, help="UUID (v4 or v1) unique to the job")
36
47
  @click.option("--status", required=True, help="Resulting job status")
37
48
  @click.option("--scylla-version", required=False, default=None, help="Version of Scylla used for this job")
38
- def finish_run(api_key: str, base_url: str, id: str, status: str, scylla_version: str = None):
39
- client = ArgusGenericClient(auth_token=api_key, base_url=base_url)
49
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
50
+ def finish_run(api_key: str, base_url: str, id: str, status: str, scylla_version: str = None, extra_headers: dict | None = None):
51
+ client = ArgusGenericClient(auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
40
52
  status = TestStatus(status)
41
53
  client.finalize_generic_run(run_id=id, status=status, scylla_version=scylla_version)
42
54
 
43
55
 
44
56
  @click.command("trigger-jobs")
45
- @click.option("--api-key", help="Argus API key for authorization", required=True)
57
+ @click.option("--api-key", help="Argus API key for authorization", required=True, envvar='ARGUS_AUTH_TOKEN')
46
58
  @click.option("--base-url", default="https://argus.scylladb.com", help="Base URL for argus instance")
47
59
  @click.option("--version", help="Scylla version to filter plans by", default=None, required=False)
48
60
  @click.option("--plan-id", help="Specific plan id for filtering", default=None, required=False)
49
61
  @click.option("--release", help="Release name to filter plans by", default=None, required=False)
50
62
  @click.option("--job-info-file", required=True, help="JSON file with trigger information (see detailed docs)")
51
- def trigger_jobs(api_key: str, base_url: str, job_info_file: str, version: str, plan_id: str, release: str):
52
- client = ArgusGenericClient(auth_token=api_key, base_url=base_url)
63
+ @click.option("--extra-headers", default={}, type=click.UNPROCESSED, callback=validate_extra_headers, help="extra headers to pass to argus, should be in json format", envvar='ARGUS_EXTRA_HEADERS')
64
+ def trigger_jobs(api_key: str, base_url: str, job_info_file: str, version: str, plan_id: str, release: str, extra_headers: dict | None = None):
65
+ client = ArgusGenericClient(auth_token=api_key, base_url=base_url, extra_headers=extra_headers)
53
66
  path = Path(job_info_file)
54
67
  if not path.exists():
55
68
  LOGGER.error("File not found: %s", job_info_file)
@@ -11,8 +11,8 @@ class ArgusGenericClient(ArgusClient):
11
11
  class Routes(ArgusClient.Routes):
12
12
  TRIGGER_JOBS = "/planning/plan/trigger"
13
13
 
14
- def __init__(self, auth_token: str, base_url: str, api_version="v1") -> None:
15
- super().__init__(auth_token, base_url, api_version)
14
+ def __init__(self, auth_token: str, base_url: str, api_version="v1", extra_headers: dict | None = None) -> None:
15
+ super().__init__(auth_token, base_url, api_version, extra_headers=extra_headers)
16
16
 
17
17
  def submit_generic_run(self, build_id: str, run_id: str, started_by: str, build_url: str, scylla_version: str | None = None):
18
18
  request_body = {
@@ -50,4 +50,4 @@ class ArgusGenericClient(ArgusClient):
50
50
  "status": status,
51
51
  "scylla_version": scylla_version,
52
52
  })
53
- self.check_response(response)
53
+ self.check_response(response)
@@ -27,8 +27,8 @@ class ArgusSCTClient(ArgusClient):
27
27
  SUBMIT_EVENTS = "/sct/$id/events/submit"
28
28
  SUBMIT_JUNIT_REPORT = "/sct/$id/junit/submit"
29
29
 
30
- def __init__(self, run_id: UUID, auth_token: str, base_url: str, api_version="v1") -> None:
31
- super().__init__(auth_token, base_url, api_version)
30
+ def __init__(self, run_id: UUID, auth_token: str, base_url: str, api_version="v1", extra_headers: dict | None = None) -> None:
31
+ super().__init__(auth_token, base_url, api_version, extra_headers=extra_headers)
32
32
  self.run_id = run_id
33
33
 
34
34
  def submit_sct_run(self, job_name: str, job_url: str, started_by: str, commit_id: str,
@@ -43,9 +43,9 @@ class ArgusSirenadaClient(ArgusClient):
43
43
  "skipped": "skipped"
44
44
  }
45
45
 
46
- def __init__(self, auth_token: str, base_url: str, api_version="v1") -> None:
46
+ def __init__(self, auth_token: str, base_url: str, api_version="v1", extra_headers: dict | None = None) -> None:
47
47
  self.results_path: Path | None = None
48
- super().__init__(auth_token, base_url, api_version)
48
+ super().__init__(auth_token, base_url, api_version, extra_headers=extra_headers)
49
49
 
50
50
  def _verify_required_files_exist(self, results_path: Path):
51
51
  assert (results_path / self._junit_xml_filename).exists(), "Missing jUnit XML results file!"
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "argus-alm"
3
- version = "0.13.1"
3
+ version = "0.14.1"
4
4
  description = "Argus"
5
5
  authors = ["Alexey Kartashov <alexey.kartashov@scylladb.com>", "Łukasz Sójka <lukasz.sojka@scylladb.com>"]
6
6
  license = "Apache-2.0"
@@ -21,7 +21,7 @@ optional = true
21
21
 
22
22
  [tool.poetry.dependencies]
23
23
  requests = "^2.26.0"
24
- python = "^3.12"
24
+ python = "^3.10"
25
25
  click = "^8.1.3"
26
26
 
27
27
  [tool.poetry.scripts]
@@ -58,4 +58,4 @@ build-backend = "poetry.core.masonry.api"
58
58
 
59
59
  [tool.black]
60
60
  line-length = 110
61
- target-version = ["py312"]
61
+ target-version = ["py310"]
File without changes
File without changes
File without changes