azul-client 9.0.24__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.
- azul_client/__init__.py +4 -0
- azul_client/api/__init__.py +74 -0
- azul_client/api/base_api.py +163 -0
- azul_client/api/binaries_data.py +513 -0
- azul_client/api/binaries_meta.py +510 -0
- azul_client/api/features.py +175 -0
- azul_client/api/plugins.py +49 -0
- azul_client/api/purge.py +71 -0
- azul_client/api/security.py +29 -0
- azul_client/api/sources.py +51 -0
- azul_client/api/statistics.py +23 -0
- azul_client/api/users.py +29 -0
- azul_client/client.py +510 -0
- azul_client/config.py +116 -0
- azul_client/exceptions.py +30 -0
- azul_client/oidc/__init__.py +5 -0
- azul_client/oidc/callback.py +73 -0
- azul_client/oidc/oidc.py +215 -0
- azul_client-9.0.24.dist-info/METADATA +102 -0
- azul_client-9.0.24.dist-info/RECORD +23 -0
- azul_client-9.0.24.dist-info/WHEEL +5 -0
- azul_client-9.0.24.dist-info/entry_points.txt +2 -0
- azul_client-9.0.24.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Mappings for the Azul plugins API."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from http import HTTPMethod
|
|
5
|
+
|
|
6
|
+
from azul_bedrock import models_restapi
|
|
7
|
+
from pydantic import TypeAdapter
|
|
8
|
+
|
|
9
|
+
from azul_client.api.base_api import BaseApiHandler
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
latest_plugin_list_adapter = TypeAdapter(list[models_restapi.LatestPluginWithVersions])
|
|
14
|
+
latest_plugin_status_list_adapter = TypeAdapter(list[models_restapi.PluginStatusSummary])
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Plugins(BaseApiHandler):
|
|
18
|
+
"""API for listing out the plugins currently running in Azul, their configuration and latest statuses."""
|
|
19
|
+
|
|
20
|
+
def get_all_plugins(self) -> list[models_restapi.LatestPluginWithVersions]:
|
|
21
|
+
"""Read names and versions of all registered plugins."""
|
|
22
|
+
return self._request_with_pydantic_model_response(
|
|
23
|
+
url=self.cfg.azul_url + "/api/v0/plugins",
|
|
24
|
+
method=HTTPMethod.GET,
|
|
25
|
+
response_model=latest_plugin_list_adapter,
|
|
26
|
+
get_data_only=True,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def get_all_plugin_statuses(self) -> list[models_restapi.PluginStatusSummary]:
|
|
30
|
+
"""Read names and versions of all registered plugins and count statuses.
|
|
31
|
+
|
|
32
|
+
Note - the status count is inaccurate because it doesn't filter out duplicates.
|
|
33
|
+
A duplicate is where the same binary is submitted to a plugin with a different path.
|
|
34
|
+
"""
|
|
35
|
+
return self._request_with_pydantic_model_response(
|
|
36
|
+
url=self.cfg.azul_url + "/api/v0/plugins/status",
|
|
37
|
+
method=HTTPMethod.GET,
|
|
38
|
+
response_model=latest_plugin_status_list_adapter,
|
|
39
|
+
get_data_only=True,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def get_plugin(self, name: str, version: str) -> models_restapi.PluginInfo:
|
|
43
|
+
"""Get all the configuration information about a specific plugin by name and version."""
|
|
44
|
+
return self._request_with_pydantic_model_response(
|
|
45
|
+
url=self.cfg.azul_url + f"/api/v0/plugins/{name}/versions/{version}",
|
|
46
|
+
method=HTTPMethod.GET,
|
|
47
|
+
response_model=models_restapi.PluginInfo,
|
|
48
|
+
get_data_only=True,
|
|
49
|
+
)
|
azul_client/api/purge.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Mappings for the Azul purge API."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from http import HTTPMethod
|
|
5
|
+
|
|
6
|
+
import pendulum
|
|
7
|
+
from azul_bedrock import models_restapi
|
|
8
|
+
from pendulum.parsing.exceptions import ParserError
|
|
9
|
+
|
|
10
|
+
from azul_client.api.base_api import BaseApiHandler
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Purge(BaseApiHandler):
|
|
16
|
+
"""API for purging files out of Azul, this API requires a user who is an admin to use it.
|
|
17
|
+
|
|
18
|
+
NOTE - Purges should not be scripted as standard practice, they have a high cost to Azul
|
|
19
|
+
and too many purges or frequent re-purging will cause instability in Azul.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def purge_submission(
|
|
23
|
+
self, track_source_references: str, *, timestamp: str, purge: bool = False
|
|
24
|
+
) -> models_restapi.PurgeSimulation | models_restapi.PurgeResults:
|
|
25
|
+
"""Purge a set of submissions (requires admin privileges).
|
|
26
|
+
|
|
27
|
+
:param str source_data_kvs: Unique identifier for the submission set (submission source + all metadata).
|
|
28
|
+
:param str binary: Sha256 Id of the binary to purge from the submission (optional).
|
|
29
|
+
:param str timestamp: Timestamp of the submission to purge (optional).
|
|
30
|
+
:param bool purge: If true, perform the purge instead of a simulation (default False).
|
|
31
|
+
"""
|
|
32
|
+
params = {"purge": purge}
|
|
33
|
+
if not timestamp:
|
|
34
|
+
raise ValueError("Timestamp is required to be set and cannot be None or and empty string.")
|
|
35
|
+
try:
|
|
36
|
+
pendulum.parse(timestamp)
|
|
37
|
+
except ParserError:
|
|
38
|
+
raise ValueError(f"Timestamp has an invalid value '{timestamp}' must be a")
|
|
39
|
+
params["timestamp"] = timestamp
|
|
40
|
+
|
|
41
|
+
if purge:
|
|
42
|
+
response_model = models_restapi.PurgeResults
|
|
43
|
+
else:
|
|
44
|
+
response_model = models_restapi.PurgeSimulation
|
|
45
|
+
|
|
46
|
+
return self._request_with_pydantic_model_response(
|
|
47
|
+
url=self.cfg.azul_url + f"/api/v0/purge/submission/{track_source_references}",
|
|
48
|
+
method=HTTPMethod.DELETE,
|
|
49
|
+
response_model=response_model,
|
|
50
|
+
params=params,
|
|
51
|
+
get_data_only=True,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def purge_link(
|
|
55
|
+
self, track_link: str, *, purge: bool = False
|
|
56
|
+
) -> models_restapi.PurgeSimulation | models_restapi.PurgeResults:
|
|
57
|
+
"""Purge a manually added relationship between binaries."""
|
|
58
|
+
params = {"purge": purge}
|
|
59
|
+
|
|
60
|
+
if purge:
|
|
61
|
+
response_model = models_restapi.PurgeResults
|
|
62
|
+
else:
|
|
63
|
+
response_model = models_restapi.PurgeSimulation
|
|
64
|
+
|
|
65
|
+
return self._request_with_pydantic_model_response(
|
|
66
|
+
url=self.cfg.azul_url + f"/api/v0/purge/link/{track_link}",
|
|
67
|
+
method=HTTPMethod.DELETE,
|
|
68
|
+
response_model=response_model,
|
|
69
|
+
params=params,
|
|
70
|
+
get_data_only=True,
|
|
71
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Module for interacting with security endpoints."""
|
|
2
|
+
|
|
3
|
+
from http import HTTPMethod
|
|
4
|
+
|
|
5
|
+
from azul_client.api.base_api import BaseApiHandler
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Security(BaseApiHandler):
|
|
9
|
+
"""Interact with binary endpoints."""
|
|
10
|
+
|
|
11
|
+
def get_security_settings(self) -> dict:
|
|
12
|
+
"""Get the current Azul security settings."""
|
|
13
|
+
return self._request(method=HTTPMethod.GET, url=self.cfg.azul_url + "/api/v0/security").json()
|
|
14
|
+
|
|
15
|
+
def normalise(self, security: str) -> str:
|
|
16
|
+
"""Validates and normalises a security string."""
|
|
17
|
+
return self._request(
|
|
18
|
+
method=HTTPMethod.POST, url=self.cfg.azul_url + "/api/v1/security/normalise", json={"security": security}
|
|
19
|
+
).json()
|
|
20
|
+
|
|
21
|
+
def get_max_security_string(self, security_strings: list[str]) -> str:
|
|
22
|
+
"""Get the max security from the provided security strings."""
|
|
23
|
+
return self._request(
|
|
24
|
+
method=HTTPMethod.POST, url=self.cfg.azul_url + "/api/v1/security/max", json=security_strings
|
|
25
|
+
).json()
|
|
26
|
+
|
|
27
|
+
def get_is_user_an_admin(self) -> bool:
|
|
28
|
+
"""Get a boolean value indicating if the authenticated user is an admin or not."""
|
|
29
|
+
return self._request(method=HTTPMethod.GET, url=self.cfg.azul_url + "/api/v0/security/is_admin").json()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Mappings for the Azul sources API."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from http import HTTPMethod
|
|
5
|
+
|
|
6
|
+
from azul_bedrock import models_restapi
|
|
7
|
+
from azul_bedrock import models_settings as azs
|
|
8
|
+
from pydantic import TypeAdapter
|
|
9
|
+
|
|
10
|
+
from azul_client.api.base_api import BaseApiHandler
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
source_dict_type_adapter = TypeAdapter(dict[str, azs.Source])
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Sources(BaseApiHandler):
|
|
19
|
+
"""API for accessing information about the sources configured in Azul."""
|
|
20
|
+
|
|
21
|
+
def get_all_sources(self) -> dict[str, azs.Source]:
|
|
22
|
+
"""Get a list of all sources from Azul."""
|
|
23
|
+
return self._request_with_pydantic_model_response(
|
|
24
|
+
url=self.cfg.azul_url + "/api/v0/sources",
|
|
25
|
+
method=HTTPMethod.GET,
|
|
26
|
+
response_model=source_dict_type_adapter,
|
|
27
|
+
get_data_only=True,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def check_source_exists(self, source_id: str) -> bool:
|
|
31
|
+
"""Check if the provided source exists in Azul."""
|
|
32
|
+
return self._generic_head_request(self.cfg.azul_url + f"/api/v0/sources/{source_id}")
|
|
33
|
+
|
|
34
|
+
def read_source(self, source_id: str) -> models_restapi.Source:
|
|
35
|
+
"""Read the information for the requested source."""
|
|
36
|
+
return self._request_with_pydantic_model_response(
|
|
37
|
+
url=self.cfg.azul_url + f"/api/v0/sources/{source_id}",
|
|
38
|
+
method=HTTPMethod.GET,
|
|
39
|
+
response_model=models_restapi.Source,
|
|
40
|
+
get_data_only=True,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def read_source_references(self, source_id: str, *, term: str = "") -> models_restapi.References:
|
|
44
|
+
"""Read source references for a source_id with an optional term query."""
|
|
45
|
+
return self._request_with_pydantic_model_response(
|
|
46
|
+
url=self.cfg.azul_url + f"/api/v0/sources/{source_id}/references",
|
|
47
|
+
method=HTTPMethod.GET,
|
|
48
|
+
response_model=models_restapi.References,
|
|
49
|
+
params={"term": term},
|
|
50
|
+
get_data_only=True,
|
|
51
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Mappings for the Azul statistics API."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from http import HTTPMethod
|
|
5
|
+
|
|
6
|
+
from azul_bedrock import models_restapi
|
|
7
|
+
|
|
8
|
+
from azul_client.api.base_api import BaseApiHandler
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Statistics(BaseApiHandler):
|
|
14
|
+
"""API for accessing statistics about Azul from the Azul restapi."""
|
|
15
|
+
|
|
16
|
+
def get_statistics(self) -> models_restapi.StatisticSummary:
|
|
17
|
+
"""Get statistics about the current state of azul."""
|
|
18
|
+
return self._request_with_pydantic_model_response(
|
|
19
|
+
url=self.cfg.azul_url + "/api/v0/statistics",
|
|
20
|
+
method=HTTPMethod.GET,
|
|
21
|
+
response_model=models_restapi.StatisticSummary,
|
|
22
|
+
get_data_only=True,
|
|
23
|
+
)
|
azul_client/api/users.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Mappings for the Azul user API."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from http import HTTPMethod
|
|
5
|
+
|
|
6
|
+
from azul_bedrock import models_restapi
|
|
7
|
+
from azul_bedrock.models_auth import UserInfo
|
|
8
|
+
|
|
9
|
+
from azul_client.api.base_api import BaseApiHandler
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Users(BaseApiHandler):
|
|
15
|
+
"""API for accessing user information of Azul."""
|
|
16
|
+
|
|
17
|
+
def get_opensearch_user_info(self) -> models_restapi.UserAccess:
|
|
18
|
+
"""Get Opensearch User info through Azul's restapi."""
|
|
19
|
+
return self._request_with_pydantic_model_response(
|
|
20
|
+
url=self.cfg.azul_url + "/api/v0/users/me/opensearch",
|
|
21
|
+
method=HTTPMethod.GET,
|
|
22
|
+
response_model=models_restapi.UserAccess,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def get_user_info(self) -> UserInfo:
|
|
26
|
+
"""Get user information for the current Token that Azul cares about."""
|
|
27
|
+
return self._request_with_pydantic_model_response(
|
|
28
|
+
url=self.cfg.azul_url + "/api/v0/users/me", method=HTTPMethod.GET, response_model=UserInfo
|
|
29
|
+
)
|