diff --git a/pkgs/clan-cli/clan_cli/emulate_fastapi.py b/pkgs/clan-cli/clan_cli/emulate_fastapi.py index 7ce274b..496ccb8 100644 --- a/pkgs/clan-cli/clan_cli/emulate_fastapi.py +++ b/pkgs/clan-cli/clan_cli/emulate_fastapi.py @@ -1,9 +1,12 @@ import sys import time import urllib +from datetime import datetime from fastapi import FastAPI -from fastapi.responses import HTMLResponse +from fastapi.responses import HTMLResponse, JSONResponse + +from clan_cli.webui.schemas import Resolution from .config import config @@ -19,13 +22,8 @@ apps = [ (app_c2, config.port_client_base + 1), ] -# bash tests: curl localhost:6600/ap_list_of_services -# curl localhost:7001/consume_service_from_other_entity - - -#### HEALTH - +#### HEALTHCHECK @app_c1.get("/health") async def healthcheck_c1() -> str: return "200 OK" @@ -88,127 +86,74 @@ async def consume_service_from_other_entity_c2() -> HTMLResponse: return HTMLResponse(content=html_content, status_code=200) -#### ap_list_of_services +@app_ap.get("/ap_list_of_services", response_class=JSONResponse) +async def ap_list_of_services() -> JSONResponse: + res = [ + { + "uuid": "98ae4334-6c12-ace8-ae34-0454cac5b68c", + "service_name": "Carlos Printing46", + "service_type": "3D Printing", + "endpoint_url": "127.0.0.1:6600/v1/print_daemon46", + "status": "unknown", + "other": {"action": ["register", "deregister", "delete", "create"]}, + "entity_did": "did:sov:test:6600", + "entity": { + "did": "did:sov:test:6600", + "name": "AP", + "ip": "127.0.0.1:6600", + "network": "255.255.0.0", + "visible": True, + "other": {}, + "attached": False, + "stop_health_task": False, + "roles": ["AP"], + }, + }, + { + "uuid": "988c24c9-61b1-cd22-6280-1c4510435a10", + "service_name": "Carlos Printing47", + "service_type": "3D Printing", + "endpoint_url": "127.0.0.1:6600/v1/print_daemon47", + "status": "unknown", + "other": {"action": ["register", "deregister", "delete", "create"]}, + "entity_did": "did:sov:test:6600", + "entity": { + "did": "did:sov:test:6600", + "name": "AP", + "ip": "127.0.0.1:6600", + "network": "255.255.0.0", + "visible": True, + "other": {}, + "attached": False, + "stop_health_task": False, + "roles": ["AP"], + }, + }, + ] + # resp = json.dumps(obj=res) + return JSONResponse(content=res, status_code=200) -@app_ap.get("/ap_list_of_services", response_class=HTMLResponse) -async def ap_list_of_services() -> HTMLResponse: - html_content = b"""HTTP/1.1 200 OK\r\n\r\n[[ - { - "uuid": "8e285c0c-4e40-430a-a477-26b3b81e30df", - "service_name": "Carlos Printing", - "service_type": "3D Printing", - "endpoint_url": "http://127.0.0.1:8000", - "status": "unknown", - "other": { - "action": [ - "register", - "deregister", - "delete", - "create" - ] - }, - "entity_did": "did:sov:test:1234" - }, - { - "uuid": "8e285c0c-4e40-430a-a477-26b3b81e30d1", - "service_name": "Luiss Fax", - "service_type": "Fax", - "endpoint_url": "http://127.0.0.1:8000", - "status": "unknown", - "other": { - "action": [ - "register", - "deregister", - "delete", - "create" - ] - }, - "entity_did": "did:sov:test:1235" - }, - { - "uuid": "8e285c0c-4e40-430a-a477-26b3b81e30d2", - "service_name": "Erdems VR-Stream", - "service_type": "VR-Stream", - "endpoint_url": "http://127.0.0.1:8000", - "status": "unknown", - "other": { - "action": [ - "register", - "deregister", - "delete", - "create" - ] - }, - "entity_did": "did:sov:test:1236" - }, - { - "uuid": "8e285c0c-4e40-430a-a477-26b3b81e30d3", - "service_name": "Onurs gallary", - "service_type": "gallary", - "endpoint_url": "http://127.0.0.1:8000", - "status": "unknown", - "other": { - "action": [ - "register", - "deregister", - "delete", - "create" - ] - }, - "entity_did": "did:sov:test:1237" - }, - { - "uuid": "8e285c0c-4e40-430a-a477-26b3b81e30d4", - "service_name": "Saras Game-Shop", - "service_type": "Game-Shop", - "endpoint_url": "http://127.0.0.1:8000", - "status": "unknown", - "other": { - "action": [ - "register", - "deregister", - "delete", - "create" - ] - }, - "entity_did": "did:sov:test:1238" - } -]]""" - return HTMLResponse(content=html_content, status_code=200) +@app_dlg.get("/dlg_list_of_did_resolutions", response_model=list[Resolution]) +async def dlg_list_of_did_resolutions() -> list[Resolution]: + res = [] - -@app_dlg.get("/dlg_list_of_did_resolutions", response_class=HTMLResponse) -async def dlg_list_of_did_resolutions() -> HTMLResponse: - html_content = b"""HTTP/1.1 200 OK\r\n\r\n -[ - { - "did": "did:sov:test:1234", - "name": "C1", - "ip": "127.0.0.1:5100", - "attached": false, - "visible": true, - "other": { - "network": "Carlo1's Home Network", - "roles": [ - "service repository", - "service consumer" - ] - } - }, - { - "did": "did:sov:test:1235", - "name": "C2", - "ip": "127.0.0.1:5100", - "attached": false, - "visible": true, - "other": { - "network": "Carlo2's Home Network", - "roles": [ - "service repository", - "service prosumer" - ] - } - } -]""" - return HTMLResponse(content=html_content, status_code=200) + res.append( + Resolution( + timestamp=datetime.fromisoformat("2021-10-12T12:52:00.000Z"), + requester_name="C1", + requester_did="did:sov:test:1122", + resolved_did="did:sov:test:1234", + other={"test": "test"}, + ) + ) + res.append( + Resolution( + timestamp=datetime.fromisoformat("2021-10-12T12:53:00.000Z"), + requester_name="C2", + requester_did="did:sov:test:1123", + resolved_did="did:sov:test:1234", + other={"test": "test"}, + ) + ) + return res diff --git a/pkgs/clan-cli/clan_cli/webui/routers/endpoints.py b/pkgs/clan-cli/clan_cli/webui/routers/endpoints.py index e8d90fe..326682d 100644 --- a/pkgs/clan-cli/clan_cli/webui/routers/endpoints.py +++ b/pkgs/clan-cli/clan_cli/webui/routers/endpoints.py @@ -1,6 +1,5 @@ import logging import time -from datetime import datetime from typing import List, Optional import httpx @@ -49,7 +48,7 @@ def get_all_services( @router.get("/api/v1/service", response_model=List[Service], tags=[Tags.services]) def get_service_by_did( - entity_did: str = "did:sov:test:1234", + entity_did: str = "did:sov:test:120", skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db), @@ -64,7 +63,7 @@ def get_service_by_did( tags=[Tags.services], ) def get_services_without_entity( - entity_did: str = "did:sov:test:1234", + entity_did: str = "did:sov:test:120", skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db), @@ -75,7 +74,7 @@ def get_services_without_entity( @router.delete("/api/v1/service", tags=[Tags.services]) def delete_service( - entity_did: str = "did:sov:test:1234", + entity_did: str = "did:sov:test:120", db: Session = Depends(sql_db.get_db), ) -> dict[str, str]: sql_crud.delete_service_by_entity_did(db, entity_did) @@ -126,7 +125,7 @@ def get_all_entities( @router.get("/api/v1/entity", response_model=Optional[Entity], tags=[Tags.entities]) def get_entity_by_did( - entity_did: str = "did:sov:test:1234", + entity_did: str = "did:sov:test:120", db: Session = Depends(sql_db.get_db), ) -> Optional[sql_models.Entity]: entity = sql_crud.get_entity_by_did(db, did=entity_did) @@ -148,7 +147,7 @@ def get_attached_entities( @router.put("/api/v1/detach", tags=[Tags.entities]) def detach_entity( background_tasks: BackgroundTasks, - entity_did: str = "did:sov:test:1234", + entity_did: str = "did:sov:test:120", skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db), @@ -163,7 +162,7 @@ def detach_entity( @router.put("/api/v1/attach", tags=[Tags.entities]) def attach_entity( background_tasks: BackgroundTasks, - entity_did: str = "did:sov:test:1234", + entity_did: str = "did:sov:test:120", skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db), @@ -180,7 +179,7 @@ def attach_entity( @router.get("/api/v1/is_attached", tags=[Tags.entities]) def is_attached( - entity_did: str = "did:sov:test:1234", db: Session = Depends(sql_db.get_db) + entity_did: str = "did:sov:test:120", db: Session = Depends(sql_db.get_db) ) -> dict[str, str]: entity = sql_crud.get_entity_by_did(db, did=entity_did) @@ -229,8 +228,8 @@ def attach_entity_loc(db: Session, entity_did: str) -> None: @router.delete("/api/v1/entity", tags=[Tags.entities]) -async def delete_entity( - entity_did: str = "did:sov:test:1234", +def delete_entity( + entity_did: str = "did:sov:test:120", db: Session = Depends(sql_db.get_db), ) -> dict[str, str]: sql_crud.delete_entity_by_did_recursive(db, did=entity_did) @@ -245,21 +244,27 @@ async def delete_entity( @router.get( "/api/v1/resolutions", response_model=List[Resolution], tags=[Tags.resolutions] ) -async def get_all_resolutions( +def get_all_resolutions( skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db) ) -> List[Resolution]: - # TODO: Get resolutions from DLG entity + matching_entities = sql_crud.get_entity_by_role(db, roles=[Role("DLG")]) + if matching_entities is None: + raise ClanError("No DLG found") + if len(matching_entities) > 1: + raise ClanError("More than one DLG found") + dlg = matching_entities[0] - return [ - Resolution( - requester_name="C1", - requester_did="did:sov:test:1122", - resolved_did="did:sov:test:1234", - other={"test": "test"}, - timestamp=datetime.now(), - id=1, - ) - ] + url = f"http://{dlg.ip}/dlg_list_of_did_resolutions" + try: + response = httpx.get(url, timeout=2) + except httpx.HTTPError as e: + raise ClanError(f"DLG not reachable at {url}") from e + + if response.status_code != 200: + raise ClanError(f"DLG returned {response.status_code}") + + resolutions = response.json() + return resolutions ######################### @@ -267,12 +272,10 @@ async def get_all_resolutions( # Eventmessage # # # ######################### - - @router.post( "/api/v1/event_message", response_model=Eventmessage, tags=[Tags.eventmessages] ) -async def create_eventmessage( +def create_eventmessage( eventmsg: EventmessageCreate, db: Session = Depends(sql_db.get_db) ) -> EventmessageCreate: return sql_crud.create_eventmessage(db, eventmsg) @@ -283,7 +286,7 @@ async def create_eventmessage( response_model=List[Eventmessage], tags=[Tags.eventmessages], ) -async def get_all_eventmessages( +def get_all_eventmessages( skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db) ) -> List[sql_models.Eventmessage]: eventmessages = sql_crud.get_eventmessages(db, skip=skip, limit=limit) diff --git a/pkgs/clan-cli/clan_cli/webui/schemas.py b/pkgs/clan-cli/clan_cli/webui/schemas.py index 169a560..a203d0f 100644 --- a/pkgs/clan-cli/clan_cli/webui/schemas.py +++ b/pkgs/clan-cli/clan_cli/webui/schemas.py @@ -45,7 +45,7 @@ class EntityRoles(EntityRolesBase): class EntityBase(BaseModel): - did: str = Field(..., example="did:sov:test:1234") + did: str = Field(..., example="did:sov:test:120") name: str = Field(..., example="C1") ip: str = Field(..., example="127.0.0.1") network: str = Field(..., example="255.255.0.0") @@ -93,7 +93,7 @@ class ServiceBase(BaseModel): class ServiceCreate(ServiceBase): - entity_did: str = Field(..., example="did:sov:test:1234") + entity_did: str = Field(..., example="did:sov:test:120") class Service(ServiceCreate): @@ -119,7 +119,7 @@ class ServicesByName(BaseModel): class ResolutionBase(BaseModel): requester_name: str = Field(..., example="C1") requester_did: str = Field(..., example="did:sov:test:1122") - resolved_did: str = Field(..., example="did:sov:test:1234") + resolved_did: str = Field(..., example="did:sov:test:120") other: dict = Field(..., example={"test": "test"}) @@ -129,7 +129,6 @@ class ResolutionCreate(ResolutionBase): class Resolution(ResolutionCreate): timestamp: datetime - id: int class Config: orm_mode = True @@ -148,7 +147,7 @@ class EventmessageBase(BaseModel): ) # specific to one group needed to enable visually nested groups msg_type: int = Field(..., example=1) # message type for the label src_did: str = Field(..., example="did:sov:test:2234") - des_did: str = Field(..., example="did:sov:test:1234") + des_did: str = Field(..., example="did:sov:test:120") class EventmessageCreate(EventmessageBase): diff --git a/pkgs/clan-cli/clan_cli/webui/server.py b/pkgs/clan-cli/clan_cli/webui/server.py index ae5b2ab..cfc7ab5 100644 --- a/pkgs/clan-cli/clan_cli/webui/server.py +++ b/pkgs/clan-cli/clan_cli/webui/server.py @@ -135,7 +135,11 @@ def start_server(args: argparse.Namespace) -> None: proc = mp.Process( target=uvicorn.run, args=(app,), - kwargs={"host": args.host, "port": port, "log_level": "info"}, + kwargs={ + "host": args.host, + "port": port, + "log_level": args.log_level, + }, daemon=True, ) proc.start() diff --git a/pkgs/clan-cli/tests/test_db_api.py b/pkgs/clan-cli/tests/test_db_api.py index bcaf160..6961f20 100644 --- a/pkgs/clan-cli/tests/test_db_api.py +++ b/pkgs/clan-cli/tests/test_db_api.py @@ -54,7 +54,7 @@ def create_entities(num: int = 10, role: str = "entity") -> list[EntityCreate]: dlg = EntityCreate( did=f"did:sov:test:{port_dlg}", name="DLG", - ip=f"{host}:{port_dlg}/health", + ip=f"{host}:{port_dlg}", network="255.255.0.0", roles=[Role("DLG")], visible=True, @@ -64,7 +64,7 @@ def create_entities(num: int = 10, role: str = "entity") -> list[EntityCreate]: ap = EntityCreate( did=f"did:sov:test:{port_ap}", name="AP", - ip=f"{host}:{port_ap}/health", + ip=f"{host}:{port_ap}", network="255.255.0.0", roles=[Role("AP")], visible=True,