Compare commits
4
Commits
v2.1.0
...
4f68bf0f9a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f68bf0f9a | ||
|
|
11a152bab8 | ||
|
|
7b3ea2922c | ||
|
|
b438ead6ae |
No files matched your search
@@ -68,6 +68,7 @@ from .types import (
|
|||||||
AuthLoginResponse,
|
AuthLoginResponse,
|
||||||
GetMeResponse,
|
GetMeResponse,
|
||||||
IssueApiTokenResponse,
|
IssueApiTokenResponse,
|
||||||
|
IssueTokenResponse,
|
||||||
RotateApiTokenResponse,
|
RotateApiTokenResponse,
|
||||||
HealthResponse,
|
HealthResponse,
|
||||||
DeepHealthResponse,
|
DeepHealthResponse,
|
||||||
@@ -142,6 +143,7 @@ __all__ = [
|
|||||||
"AuthLoginResponse",
|
"AuthLoginResponse",
|
||||||
"GetMeResponse",
|
"GetMeResponse",
|
||||||
"IssueApiTokenResponse",
|
"IssueApiTokenResponse",
|
||||||
|
"IssueTokenResponse",
|
||||||
"RotateApiTokenResponse",
|
"RotateApiTokenResponse",
|
||||||
"HealthResponse",
|
"HealthResponse",
|
||||||
"DeepHealthResponse",
|
"DeepHealthResponse",
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
"""Canonical Elydora package version."""
|
"""Canonical Elydora package version."""
|
||||||
|
|
||||||
__version__ = "2.1.0"
|
__version__ = "2.1.1"
|
||||||
+21
-8
@@ -3,6 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
from urllib.parse import quote
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@@ -130,9 +131,11 @@ class AsyncElydoraClient:
|
|||||||
headers=build_headers(self.token),
|
headers=build_headers(self.token),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _get_public(self, path: str) -> Any:
|
async def _get_public(self, path: str, *, accept_status: Optional[int] = None) -> Any:
|
||||||
session = await self._get_session()
|
session = await self._get_session()
|
||||||
async with session.get(f"{self.base_url}{path}", timeout=TIMEOUT) as response:
|
async with session.get(f"{self.base_url}{path}", timeout=TIMEOUT) as response:
|
||||||
|
if accept_status is not None and response.status == accept_status:
|
||||||
|
return await response.json()
|
||||||
return await self._handle_response(response)
|
return await self._handle_response(response)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -193,6 +196,15 @@ class AsyncElydoraClient:
|
|||||||
"POST", "/v1/auth/token", json_body=api_token_body(ttl_seconds)
|
"POST", "/v1/auth/token", json_body=api_token_body(ttl_seconds)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def issue_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse:
|
||||||
|
"""Deprecated alias for issue_api_token()."""
|
||||||
|
warnings.warn(
|
||||||
|
"AsyncElydoraClient.issue_token() is deprecated. Use issue_api_token().",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return await self.issue_api_token(ttl_seconds=ttl_seconds)
|
||||||
|
|
||||||
async def rotate_api_token(self) -> RotateApiTokenResponse:
|
async def rotate_api_token(self) -> RotateApiTokenResponse:
|
||||||
return await self._request("POST", "/v1/auth/rotate", json_body={})
|
return await self._request("POST", "/v1/auth/rotate", json_body={})
|
||||||
|
|
||||||
@@ -201,19 +213,19 @@ class AsyncElydoraClient:
|
|||||||
return await self._request("POST", "/v1/agents/register", json_body=request)
|
return await self._request("POST", "/v1/agents/register", json_body=request)
|
||||||
|
|
||||||
async def get_agent(self, agent_id: str) -> GetAgentResponse:
|
async def get_agent(self, agent_id: str) -> GetAgentResponse:
|
||||||
return await self._request("GET", f"/v1/agents/{agent_id}")
|
return await self._request("GET", f"/v1/agents/{quote(agent_id, safe='')}")
|
||||||
|
|
||||||
async def list_agents(self) -> ListAgentsResponse:
|
async def list_agents(self) -> ListAgentsResponse:
|
||||||
return await self._request("GET", "/v1/agents")
|
return await self._request("GET", "/v1/agents")
|
||||||
|
|
||||||
async def freeze_agent(self, agent_id: str, reason: str) -> FreezeAgentResponse:
|
async def freeze_agent(self, agent_id: str, reason: str) -> FreezeAgentResponse:
|
||||||
return await self._request(
|
return await self._request(
|
||||||
"POST", f"/v1/agents/{agent_id}/freeze", json_body={"reason": reason}
|
"POST", f"/v1/agents/{quote(agent_id, safe='')}/freeze", json_body={"reason": reason}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def unfreeze_agent(self, agent_id: str, reason: str) -> UnfreezeAgentResponse:
|
async def unfreeze_agent(self, agent_id: str, reason: str) -> UnfreezeAgentResponse:
|
||||||
return await self._request(
|
return await self._request(
|
||||||
"POST", f"/v1/agents/{agent_id}/unfreeze", json_body={"reason": reason}
|
"POST", f"/v1/agents/{quote(agent_id, safe='')}/unfreeze", json_body={"reason": reason}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def update_agent(
|
async def update_agent(
|
||||||
@@ -221,15 +233,15 @@ class AsyncElydoraClient:
|
|||||||
) -> UpdateAgentResponse:
|
) -> UpdateAgentResponse:
|
||||||
require_integration_type(integration_type)
|
require_integration_type(integration_type)
|
||||||
return await self._request(
|
return await self._request(
|
||||||
"PATCH", f"/v1/agents/{agent_id}", json_body={"integration_type": integration_type}
|
"PATCH", f"/v1/agents/{quote(agent_id, safe='')}", json_body={"integration_type": integration_type}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def delete_agent(self, agent_id: str) -> DeleteAgentResponse:
|
async def delete_agent(self, agent_id: str) -> DeleteAgentResponse:
|
||||||
return await self._request("DELETE", f"/v1/agents/{agent_id}")
|
return await self._request("DELETE", f"/v1/agents/{quote(agent_id, safe='')}")
|
||||||
|
|
||||||
async def revoke_key(self, agent_id: str, kid: str, reason: str) -> None:
|
async def revoke_key(self, agent_id: str, kid: str, reason: str) -> None:
|
||||||
await self._request(
|
await self._request(
|
||||||
"POST", f"/v1/agents/{agent_id}/revoke", json_body={"kid": kid, "reason": reason}
|
"POST", f"/v1/agents/{quote(agent_id, safe='')}/revoke", json_body={"kid": kid, "reason": reason}
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_operation(
|
def create_operation(
|
||||||
@@ -349,4 +361,5 @@ class AsyncElydoraClient:
|
|||||||
return await self._get_public("/v1/health")
|
return await self._get_public("/v1/health")
|
||||||
|
|
||||||
async def deep_health(self) -> DeepHealthResponse:
|
async def deep_health(self) -> DeepHealthResponse:
|
||||||
return await self._get_public("/v1/health/deep")
|
"""503 carries the degraded report, not an error."""
|
||||||
|
return await self._get_public("/v1/health/deep", accept_status=503)
|
||||||
+21
-8
@@ -3,6 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
from urllib.parse import quote
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@@ -119,8 +120,10 @@ class ElydoraClient:
|
|||||||
headers=build_headers(self.token),
|
headers=build_headers(self.token),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_public(self, path: str) -> Any:
|
def _get_public(self, path: str, *, accept_status: Optional[int] = None) -> Any:
|
||||||
response = self._session.get(f"{self.base_url}{path}", timeout=REQUEST_TIMEOUT_SECONDS)
|
response = self._session.get(f"{self.base_url}{path}", timeout=REQUEST_TIMEOUT_SECONDS)
|
||||||
|
if accept_status is not None and response.status_code == accept_status:
|
||||||
|
return response.json()
|
||||||
return self._handle_response(response)
|
return self._handle_response(response)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -179,6 +182,15 @@ class ElydoraClient:
|
|||||||
def issue_api_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse:
|
def issue_api_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse:
|
||||||
return self._request("POST", "/v1/auth/token", json_body=api_token_body(ttl_seconds))
|
return self._request("POST", "/v1/auth/token", json_body=api_token_body(ttl_seconds))
|
||||||
|
|
||||||
|
def issue_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse:
|
||||||
|
"""Deprecated alias for issue_api_token()."""
|
||||||
|
warnings.warn(
|
||||||
|
"ElydoraClient.issue_token() is deprecated. Use issue_api_token().",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return self.issue_api_token(ttl_seconds=ttl_seconds)
|
||||||
|
|
||||||
def rotate_api_token(self) -> RotateApiTokenResponse:
|
def rotate_api_token(self) -> RotateApiTokenResponse:
|
||||||
return self._request("POST", "/v1/auth/rotate", json_body={})
|
return self._request("POST", "/v1/auth/rotate", json_body={})
|
||||||
|
|
||||||
@@ -187,29 +199,29 @@ class ElydoraClient:
|
|||||||
return self._request("POST", "/v1/agents/register", json_body=request)
|
return self._request("POST", "/v1/agents/register", json_body=request)
|
||||||
|
|
||||||
def get_agent(self, agent_id: str) -> GetAgentResponse:
|
def get_agent(self, agent_id: str) -> GetAgentResponse:
|
||||||
return self._request("GET", f"/v1/agents/{agent_id}")
|
return self._request("GET", f"/v1/agents/{quote(agent_id, safe='')}")
|
||||||
|
|
||||||
def list_agents(self) -> ListAgentsResponse:
|
def list_agents(self) -> ListAgentsResponse:
|
||||||
return self._request("GET", "/v1/agents")
|
return self._request("GET", "/v1/agents")
|
||||||
|
|
||||||
def freeze_agent(self, agent_id: str, reason: str) -> FreezeAgentResponse:
|
def freeze_agent(self, agent_id: str, reason: str) -> FreezeAgentResponse:
|
||||||
return self._request("POST", f"/v1/agents/{agent_id}/freeze", json_body={"reason": reason})
|
return self._request("POST", f"/v1/agents/{quote(agent_id, safe='')}/freeze", json_body={"reason": reason})
|
||||||
|
|
||||||
def unfreeze_agent(self, agent_id: str, reason: str) -> UnfreezeAgentResponse:
|
def unfreeze_agent(self, agent_id: str, reason: str) -> UnfreezeAgentResponse:
|
||||||
return self._request("POST", f"/v1/agents/{agent_id}/unfreeze", json_body={"reason": reason})
|
return self._request("POST", f"/v1/agents/{quote(agent_id, safe='')}/unfreeze", json_body={"reason": reason})
|
||||||
|
|
||||||
def update_agent(self, agent_id: str, integration_type: IntegrationType) -> UpdateAgentResponse:
|
def update_agent(self, agent_id: str, integration_type: IntegrationType) -> UpdateAgentResponse:
|
||||||
require_integration_type(integration_type)
|
require_integration_type(integration_type)
|
||||||
return self._request(
|
return self._request(
|
||||||
"PATCH", f"/v1/agents/{agent_id}", json_body={"integration_type": integration_type}
|
"PATCH", f"/v1/agents/{quote(agent_id, safe='')}", json_body={"integration_type": integration_type}
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete_agent(self, agent_id: str) -> DeleteAgentResponse:
|
def delete_agent(self, agent_id: str) -> DeleteAgentResponse:
|
||||||
return self._request("DELETE", f"/v1/agents/{agent_id}")
|
return self._request("DELETE", f"/v1/agents/{quote(agent_id, safe='')}")
|
||||||
|
|
||||||
def revoke_key(self, agent_id: str, kid: str, reason: str) -> None:
|
def revoke_key(self, agent_id: str, kid: str, reason: str) -> None:
|
||||||
self._request(
|
self._request(
|
||||||
"POST", f"/v1/agents/{agent_id}/revoke", json_body={"kid": kid, "reason": reason}
|
"POST", f"/v1/agents/{quote(agent_id, safe='')}/revoke", json_body={"kid": kid, "reason": reason}
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_operation(
|
def create_operation(
|
||||||
@@ -324,4 +336,5 @@ class ElydoraClient:
|
|||||||
return self._get_public("/v1/health")
|
return self._get_public("/v1/health")
|
||||||
|
|
||||||
def deep_health(self) -> DeepHealthResponse:
|
def deep_health(self) -> DeepHealthResponse:
|
||||||
return self._get_public("/v1/health/deep")
|
"""503 carries the degraded report, not an error."""
|
||||||
|
return self._get_public("/v1/health/deep", accept_status=503)
|
||||||
@@ -351,10 +351,15 @@ class IssueApiTokenResponse(TypedDict):
|
|||||||
token_id: str
|
token_id: str
|
||||||
|
|
||||||
|
|
||||||
|
# Deprecated alias for IssueApiTokenResponse.
|
||||||
|
IssueTokenResponse = IssueApiTokenResponse
|
||||||
|
|
||||||
|
|
||||||
class RotateApiTokenResponse(TypedDict):
|
class RotateApiTokenResponse(TypedDict):
|
||||||
token: str
|
token: str
|
||||||
expires_at: Optional[int]
|
expires_at: Optional[int]
|
||||||
token_id: str
|
token_id: str
|
||||||
|
previous_token_grace_until: int
|
||||||
|
|
||||||
|
|
||||||
class HealthResponse(TypedDict):
|
class HealthResponse(TypedDict):
|
||||||
|
|||||||
Reference in new issue
Block a user