Unverified Commit f1abfde8 authored by Jakob Görgen's avatar Jakob Görgen
Browse files

symphony/client: added runner client merhods to send and retrieve runner events

parent 1876a59d
...@@ -26,6 +26,7 @@ import typing ...@@ -26,6 +26,7 @@ import typing
import contextlib import contextlib
import asyncio import asyncio
import json import json
from simbricks.utils import base as utils_base
from rich.console import Console from rich.console import Console
from .auth import TokenProvider from .auth import TokenProvider
from .settings import client_settings from .settings import client_settings
...@@ -65,74 +66,69 @@ class BaseClient: ...@@ -65,74 +66,69 @@ class BaseClient:
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def request( async def request(
self, meth: str, url: str, data: typing.Any = None, retry: bool = True, self, meth: str, url: str, data: typing.Any = None, retry: bool = True, **kwargs: typing.Any
**kwargs: typing.Any
) -> typing.AsyncIterator[aiohttp.ClientResponse]: ) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self.session() as session: async with self.session() as session:
async with session.request( async with session.request(
method=meth, url=self.build_url(url), data=data, **kwargs method=meth, url=self.build_url(url), data=data, **kwargs
) as resp: # TODO: handel connection error ) as resp: # TODO: handel connection error
if resp.status == 401 and 'WWW-Authenticate' in resp.headers \ if resp.status == 401 and "WWW-Authenticate" in resp.headers and retry:
and retry: wwa = resp.headers["WWW-Authenticate"]
wwa = resp.headers['WWW-Authenticate'] parts = wwa.split(",")
parts = wwa.split(',')
ticket = None ticket = None
for p in parts: for p in parts:
p = p.strip() p = p.strip()
if p.startswith("ticket=\""): if p.startswith('ticket="'):
ticket = p[8:-1] ticket = p[8:-1]
if ticket: if ticket:
await self._token_provider.resource_token(ticket) await self._token_provider.resource_token(ticket)
async with self.request( async with self.request(meth, url, data, False, **kwargs) as resp:
meth, url, data, False, **kwargs
) as resp:
yield resp yield resp
else: else:
resp.raise_for_status() # TODO: handel gracefully resp.raise_for_status() # TODO: handel gracefully
yield resp yield resp
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def get( async def get(
self, url: str, data: typing.Any = None, **kwargs: typing.Any, self,
url: str,
data: typing.Any = None,
**kwargs: typing.Any,
) -> typing.AsyncIterator[aiohttp.ClientResponse]: ) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self.request( async with self.request(meth=aiohttp.hdrs.METH_GET, url=url, data=data, **kwargs) as resp:
meth=aiohttp.hdrs.METH_GET, url=url, data=data, **kwargs
) as resp:
yield resp yield resp
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def post( async def post(
self, url: str, data: typing.Any = None, **kwargs: typing.Any, self,
url: str,
data: typing.Any = None,
**kwargs: typing.Any,
) -> typing.AsyncIterator[aiohttp.ClientResponse]: ) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self.request( async with self.request(meth=aiohttp.hdrs.METH_POST, url=url, data=data, **kwargs) as resp:
meth=aiohttp.hdrs.METH_POST, url=url, data=data, **kwargs
) as resp:
yield resp yield resp
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def put( async def put(
self, url: str, data: typing.Any = None, **kwargs: typing.Any, self,
url: str,
data: typing.Any = None,
**kwargs: typing.Any,
) -> typing.AsyncIterator[aiohttp.ClientResponse]: ) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self.request( async with self.request(meth=aiohttp.hdrs.METH_PUT, url=url, data=data, **kwargs) as resp:
meth=aiohttp.hdrs.METH_PUT, url=url, data=data, **kwargs
) as resp:
yield resp yield resp
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def patch( async def patch(
self, url: str, data: typing.Any = None, **kwargs: typing.Any self, url: str, data: typing.Any = None, **kwargs: typing.Any
) -> typing.AsyncIterator[aiohttp.ClientResponse]: ) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self.request( async with self.request(meth=aiohttp.hdrs.METH_PATCH, url=url, data=data, **kwargs) as resp:
meth=aiohttp.hdrs.METH_PATCH, url=url, data=data, **kwargs
) as resp:
yield resp yield resp
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def delete(self, url: str, **kwargs: typing.Any) -> typing.AsyncIterator[aiohttp.ClientResponse]: async def delete(self, url: str, **kwargs: typing.Any) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self.request( async with self.request(meth=aiohttp.hdrs.METH_DELETE, url=url, **kwargs) as resp:
meth=aiohttp.hdrs.METH_DELETE, url=url, **kwargs
) as resp:
yield resp yield resp
async def info(self): async def info(self):
...@@ -187,13 +183,10 @@ class NSClient: ...@@ -187,13 +183,10 @@ class NSClient:
async def put( async def put(
self, self,
url: str, url: str,
overwrite_headers: dict[str, typing.Any] | None = None,
data: typing.Any = None, data: typing.Any = None,
**kwargs: typing.Any, **kwargs: typing.Any,
) -> typing.AsyncIterator[aiohttp.ClientResponse]: ) -> typing.AsyncIterator[aiohttp.ClientResponse]:
async with self._base_client.put( async with self._base_client.put(url=self._build_ns_prefix(url=url), data=data, **kwargs) as resp:
url=self._build_ns_prefix(url=url), overwrite_headers=overwrite_headers, data=data, **kwargs
) as resp:
yield resp yield resp
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
...@@ -244,7 +237,7 @@ class NSClient: ...@@ -244,7 +237,7 @@ class NSClient:
async with self.get(url="/all") as resp: async with self.get(url="/all") as resp:
return await resp.json() return await resp.json()
async def get_members(self) -> dict[str,list[dict]]: async def get_members(self) -> dict[str, list[dict]]:
async with self.get(url="/members") as resp: async with self.get(url="/members") as resp:
return await resp.json() return await resp.json()
...@@ -438,6 +431,33 @@ class RunnerClient: ...@@ -438,6 +431,33 @@ class RunnerClient:
async with self._ns_client.post(url=f"/runners", json=obj) as resp: async with self._ns_client.post(url=f"/runners", json=obj) as resp:
return await resp.json() return await resp.json()
async def create_runner_event(self, runner_id: int, action: str, run_id: int | None) -> dict:
obj = {"runner_id": runner_id, "action": action, "run_id": run_id}
async with self._ns_client.post(url=f"/runners/{runner_id}/events", json=obj) as resp:
return await resp.json()
async def update_runner_event(
self, runner_id: int, event_id: int, action: str | None, run_id: int | None, event_status: str | None
) -> dict:
obj = {
"id": event_id,
"runner_id": runner_id,
"action": action,
"run_id": run_id,
"event_status": event_status,
}
obj = utils_base.filter_None_dict(to_filter=obj)
async with self._ns_client.put(url=f"/runners/{runner_id}/events", json=obj) as resp:
return await resp.json()
async def get_events(
self, runner_id: int, action: str | None, run_id: int | None, limit: int | None, event_status: str | None
) -> dict:
params = {"action": action, "run_id": run_id, "event_status": event_status, "limit": limit}
params = utils_base.filter_None_dict(to_filter=params)
async with self._ns_client.get(url=f"/runners/{runner_id}/events", params=params) as resp:
return await resp.json()
async def update_runner(self, updates: dict[str, typing.Any]) -> dict: async def update_runner(self, updates: dict[str, typing.Any]) -> dict:
async with self.post(url="", json=updates) as resp: async with self.post(url="", json=updates) as resp:
return await resp.json() return await resp.json()
......
...@@ -46,6 +46,11 @@ class IdObj(abc.ABC): ...@@ -46,6 +46,11 @@ class IdObj(abc.ABC):
return instance return instance
def filter_None_dict(to_filter: dict) -> dict:
res = {k: v for k, v in to_filter.items() if v is not None}
return res
def check_type(obj, expected_type) -> bool: def check_type(obj, expected_type) -> bool:
""" """
Checks if obj has type or is a subtype of expected_type Checks if obj has type or is a subtype of expected_type
...@@ -70,9 +75,7 @@ def check_types(obj, *expected_types) -> bool: ...@@ -70,9 +75,7 @@ def check_types(obj, *expected_types) -> bool:
def has_expected_type(obj, expected_type) -> None: def has_expected_type(obj, expected_type) -> None:
if not check_type(obj=obj, expected_type=expected_type): if not check_type(obj=obj, expected_type=expected_type):
raise Exception( raise Exception(f"obj of type {type(obj)} has not the type or is not a subtype of {expected_type}")
f"obj of type {type(obj)} has not the type or is not a subtype of {expected_type}"
)
def has_attribute(obj, attr: str) -> None: def has_attribute(obj, attr: str) -> None:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment