Skip to content

Commit e7674f2

Browse files
committed
admin: Implement admin client infrastructure
- Create AdminClient base class with HTTP request handling and error mapping - Implement DatasetsClient with register/deploy/list/delete operations - Implement JobsClient with get/list/wait/stop/delete operations - Implement SchemaClient for SQL validation and schema inference - Create DeploymentContext for chainable deployment workflows - Add exception hierarchy with 30+ typed error classes mapped from API codes - Support automatic job polling with configurable timeout
1 parent 8080219 commit e7674f2

File tree

7 files changed

+1102
-0
lines changed

7 files changed

+1102
-0
lines changed

src/amp/admin/__init__.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""Admin API client for Amp.
2+
3+
This module provides HTTP client functionality for interacting with the Amp Admin API,
4+
enabling dataset registration, deployment, manifest generation, and job monitoring.
5+
6+
Example:
7+
>>> from amp.admin import AdminClient
8+
>>> client = AdminClient('http://localhost:8080')
9+
>>> datasets = client.datasets.list_all()
10+
"""
11+
12+
from .client import AdminClient
13+
from .datasets import DatasetsClient
14+
from .deployment import DeploymentContext
15+
from .errors import (
16+
AdminAPIError,
17+
CreateProviderError,
18+
DatabaseError,
19+
DatasetNotFoundError,
20+
DeleteLocationError,
21+
DeleteProviderError,
22+
DependencyValidationError,
23+
FileNotFoundError,
24+
GetDatasetVersionError,
25+
GetFileInfoError,
26+
GetManifestError,
27+
GetOutputSchemaError,
28+
InternalServerError,
29+
InvalidManifestError,
30+
InvalidPathError,
31+
InvalidPayloadError,
32+
JobDeleteError,
33+
JobNotFoundError,
34+
JobsDeleteError,
35+
JobStopError,
36+
ListAllDatasetsError,
37+
ListDatasetVersionsError,
38+
ListJobsError,
39+
ListLocationFilesError,
40+
ListLocationsError,
41+
ListProvidersError,
42+
LocationNotFoundError,
43+
ManifestLinkingError,
44+
ManifestNotFoundError,
45+
ManifestRegistrationError,
46+
ProviderNotFoundError,
47+
SchedulerError,
48+
StoreError,
49+
UnlinkDatasetManifestsError,
50+
UnsupportedDatasetKindError,
51+
VersionTaggingError,
52+
)
53+
from .jobs import JobsClient
54+
from .schema import SchemaClient
55+
56+
__all__ = [
57+
# Core clients
58+
'AdminClient',
59+
'DatasetsClient',
60+
'JobsClient',
61+
'SchemaClient',
62+
'DeploymentContext',
63+
# Exceptions
64+
'AdminAPIError',
65+
'InvalidPayloadError',
66+
'InvalidManifestError',
67+
'DatasetNotFoundError',
68+
'DependencyValidationError',
69+
'ManifestRegistrationError',
70+
'ManifestLinkingError',
71+
'ManifestNotFoundError',
72+
'VersionTaggingError',
73+
'UnsupportedDatasetKindError',
74+
'StoreError',
75+
'UnlinkDatasetManifestsError',
76+
'ListAllDatasetsError',
77+
'ListDatasetVersionsError',
78+
'GetDatasetVersionError',
79+
'GetManifestError',
80+
'JobNotFoundError',
81+
'ListJobsError',
82+
'SchedulerError',
83+
'JobStopError',
84+
'JobDeleteError',
85+
'JobsDeleteError',
86+
'LocationNotFoundError',
87+
'ListLocationsError',
88+
'DeleteLocationError',
89+
'ListLocationFilesError',
90+
'FileNotFoundError',
91+
'GetFileInfoError',
92+
'ProviderNotFoundError',
93+
'CreateProviderError',
94+
'ListProvidersError',
95+
'DeleteProviderError',
96+
'GetOutputSchemaError',
97+
'InvalidPathError',
98+
'DatabaseError',
99+
'InternalServerError',
100+
]

src/amp/admin/client.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""Base HTTP client for Amp Admin API.
2+
3+
This module provides the core AdminClient class for communicating
4+
with the Amp Admin API over HTTP.
5+
"""
6+
7+
from typing import Optional
8+
9+
import httpx
10+
11+
from .errors import map_error_response
12+
13+
14+
class AdminClient:
15+
"""HTTP client for Amp Admin API.
16+
17+
Provides access to Admin API endpoints through sub-clients for
18+
datasets, jobs, and schema operations.
19+
20+
Args:
21+
base_url: Base URL for Admin API (e.g., 'http://localhost:8080')
22+
auth_token: Optional Bearer token for authentication
23+
24+
Example:
25+
>>> client = AdminClient('http://localhost:8080')
26+
>>> datasets = client.datasets.list_all()
27+
"""
28+
29+
def __init__(self, base_url: str, auth_token: Optional[str] = None):
30+
"""Initialize Admin API client.
31+
32+
Args:
33+
base_url: Base URL for Admin API (e.g., 'http://localhost:8080')
34+
auth_token: Optional Bearer token for authentication
35+
"""
36+
self.base_url = base_url.rstrip('/')
37+
38+
# Build headers
39+
headers = {}
40+
if auth_token:
41+
headers['Authorization'] = f'Bearer {auth_token}'
42+
43+
# Create HTTP client
44+
self._http = httpx.Client(
45+
base_url=self.base_url,
46+
headers=headers,
47+
timeout=30.0,
48+
follow_redirects=True,
49+
)
50+
51+
def _request(
52+
self, method: str, path: str, json: Optional[dict] = None, params: Optional[dict] = None, **kwargs
53+
) -> httpx.Response:
54+
"""Make HTTP request with error handling.
55+
56+
Args:
57+
method: HTTP method (GET, POST, DELETE, etc.)
58+
path: API endpoint path (e.g., '/datasets')
59+
json: Optional JSON request body
60+
params: Optional query parameters
61+
**kwargs: Additional arguments passed to httpx.request()
62+
63+
Returns:
64+
HTTP response object
65+
66+
Raises:
67+
AdminAPIError: If the API returns an error response
68+
"""
69+
response = self._http.request(method, path, json=json, params=params, **kwargs)
70+
71+
# Handle error responses
72+
if response.status_code >= 400:
73+
try:
74+
error_data = response.json()
75+
raise map_error_response(response.status_code, error_data)
76+
except ValueError:
77+
# Response is not JSON, fall back to generic HTTP error
78+
response.raise_for_status()
79+
80+
return response
81+
82+
@property
83+
def datasets(self):
84+
"""Access datasets client.
85+
86+
Returns:
87+
DatasetsClient for dataset operations
88+
"""
89+
from .datasets import DatasetsClient
90+
91+
return DatasetsClient(self)
92+
93+
@property
94+
def jobs(self):
95+
"""Access jobs client.
96+
97+
Returns:
98+
JobsClient for job operations
99+
"""
100+
from .jobs import JobsClient
101+
102+
return JobsClient(self)
103+
104+
@property
105+
def schema(self):
106+
"""Access schema client.
107+
108+
Returns:
109+
SchemaClient for schema operations
110+
"""
111+
from .schema import SchemaClient
112+
113+
return SchemaClient(self)
114+
115+
def close(self):
116+
"""Close the HTTP client and release resources.
117+
118+
Example:
119+
>>> client = AdminClient('http://localhost:8080')
120+
>>> try:
121+
... datasets = client.datasets.list_all()
122+
... finally:
123+
... client.close()
124+
"""
125+
self._http.close()
126+
127+
def __enter__(self):
128+
"""Context manager entry."""
129+
return self
130+
131+
def __exit__(self, exc_type, exc_val, exc_tb):
132+
"""Context manager exit."""
133+
self.close()

0 commit comments

Comments
 (0)