From 1fbdb77fa74a7ddf3a030c77fb1bb52aa0ee13f5 Mon Sep 17 00:00:00 2001 From: Gabor Torok Date: Fri, 1 May 2026 11:11:54 -0700 Subject: [PATCH 1/2] compute/filesystem report their supported resources --- app/demo_adapter.py | 6 ++++++ app/routers/compute/compute.py | 18 +++++++++++++++++- app/routers/filesystem/filesystem.py | 19 ++++++++++++++++++- app/routers/status/facility_adapter.py | 8 ++++++-- app/routers/status/models.py | 6 ++++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/app/demo_adapter.py b/app/demo_adapter.py index fa9a23ae..2d30c0eb 100644 --- a/app/demo_adapter.py +++ b/app/demo_adapter.py @@ -180,6 +180,7 @@ def _init_state(self): current_status=status_models.Status.degraded, last_modified=day_ago, resource_type=status_models.ResourceType.compute, + supported_endpoints=[status_models.Endpoint.compute], ) hpss = status_models.Resource( @@ -192,6 +193,7 @@ def _init_state(self): current_status=status_models.Status.up, last_modified=day_ago, resource_type=status_models.ResourceType.storage, + supported_endpoints=[status_models.Endpoint.filesystem], ) cfs = status_models.Resource( @@ -204,6 +206,7 @@ def _init_state(self): current_status=status_models.Status.up, last_modified=day_ago, resource_type=status_models.ResourceType.storage, + supported_endpoints=[status_models.Endpoint.filesystem], ) login = status_models.Resource( @@ -413,6 +416,9 @@ async def get_resources( async def get_resource(self: "DemoAdapter", id_: str) -> status_models.Resource: return status_models.Resource.find_by_id(self.resources, id_) + async def get_resources_for_endpoint(self: "DemoAdapter", endpoint: status_models.Endpoint) -> list[status_models.Resource]: + return [r for r in self.resources if endpoint in r.supported_endpoints] + async def get_events( self: "DemoAdapter", offset: int, diff --git a/app/routers/compute/compute.py b/app/routers/compute/compute.py index 71c80b45..f412c928 100644 --- a/app/routers/compute/compute.py +++ b/app/routers/compute/compute.py @@ -8,7 +8,7 @@ from .. import iri_router from ..error_handlers import DEFAULT_RESPONSES from ..iri_meta import iri_meta_dict -from ..status.status import router as status_router +from ..status.status import router as status_router, models as status_models from . import facility_adapter, models router = iri_router.IriRouter( @@ -18,6 +18,22 @@ ) +@router.get( + "/resources", + response_model=list[status_models.Resource], + response_model_exclude_unset=True, + responses=DEFAULT_RESPONSES, + operation_id="getComputeResources", + openapi_extra=iri_meta_dict("production", "required"), +) +async def get_resources( + request: Request, + _forbid=Depends(forbidExtraQueryParams()), +): + """Get a list of resources that can be used in this endpoint""" + return await status_router.adapter.get_resources_for_endpoint(status_models.Endpoint.compute) + + @router.post( "/job/{resource_id:str}", response_model=models.Job, diff --git a/app/routers/filesystem/filesystem.py b/app/routers/filesystem/filesystem.py index cd6448a3..b41a0ee6 100644 --- a/app/routers/filesystem/filesystem.py +++ b/app/routers/filesystem/filesystem.py @@ -7,6 +7,7 @@ import base64 from typing import Annotated from fastapi import Depends, HTTPException, status, Query, Request, File, UploadFile +from ...types.http import forbidExtraQueryParams from ...types.user import User from .. import iri_router from ..error_handlers import DEFAULT_RESPONSES @@ -24,6 +25,22 @@ ) +@router.get( + "/resources", + response_model=list[status_models.Resource], + response_model_exclude_unset=True, + responses=DEFAULT_RESPONSES, + operation_id="getFilesystemResources", + openapi_extra=iri_meta_dict("production", "required"), +) +async def get_resources( + request: Request, + _forbid=Depends(forbidExtraQueryParams()), +): + """Get a list of resources that can be used in this endpoint""" + return await status_router.adapter.get_resources_for_endpoint(status_models.Endpoint.filesystem) + + async def _user_resource( resource_id: str, user: User, @@ -250,7 +267,7 @@ async def get_ls_async( user=user, resource=resource, task=task_models.TaskCommand( - router=router.get_router_name(), + router=router.get_router_name(), command="ls", args={"path": path, "show_hidden": show_hidden, "numeric_uid": numeric_uid, "recursive": recursive, "dereference": dereference} ), diff --git a/app/routers/status/facility_adapter.py b/app/routers/status/facility_adapter.py index 65b87c4c..d5dd8dde 100644 --- a/app/routers/status/facility_adapter.py +++ b/app/routers/status/facility_adapter.py @@ -21,13 +21,17 @@ async def get_resources( description: str | None = None, group: str | None = None, modified_since: datetime.datetime | None = None, - resource_type: status_models.ResourceType|None = None, - current_status: status_models.Status|None = None, + resource_type: status_models.ResourceType | None = None, + current_status: status_models.Status | None = None, capability: Capability | None = None, site_id: str | None = None, ) -> list[status_models.Resource]: pass + @abstractmethod + async def get_resources_for_endpoint(self: "FacilityAdapter", endpoint: status_models.Endpoint) -> list[status_models.Resource]: + pass + @abstractmethod async def get_resource(self: "FacilityAdapter", id_: str) -> status_models.Resource: pass diff --git a/app/routers/status/models.py b/app/routers/status/models.py index 4fda8015..a8999939 100644 --- a/app/routers/status/models.py +++ b/app/routers/status/models.py @@ -27,6 +27,11 @@ class ResourceType(enum.Enum): unknown = "unknown" +class Endpoint(enum.Enum): + compute = "compute" + filesystem = "filesystem" + + class Resource(NamedObject): """Represents a resource in the system.""" def _self_path(self) -> str: @@ -38,6 +43,7 @@ def _self_path(self) -> str: group: str|None = Field(default=None, description="Logical grouping of the resource", example="frontend") current_status: Status|None = Field(default=None, description="The current status comes from the status of the last event for this resource", example="up") resource_type: ResourceType = Field(..., description="Type of the resource", example="service") + supported_endpoints: list[Endpoint] = Field(default_factory=list, description="a list of endpoints where this resource can be used") @computed_field(description="URI of the site where this resource is located") @property From 5021d493b779d18594924941459b3334ee0a76c5 Mon Sep 17 00:00:00 2001 From: Gabor Torok Date: Fri, 1 May 2026 11:30:58 -0700 Subject: [PATCH 2/2] maturity-level to 'planned' --- app/routers/compute/compute.py | 2 +- app/routers/filesystem/filesystem.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/routers/compute/compute.py b/app/routers/compute/compute.py index f412c928..963d9e34 100644 --- a/app/routers/compute/compute.py +++ b/app/routers/compute/compute.py @@ -24,7 +24,7 @@ response_model_exclude_unset=True, responses=DEFAULT_RESPONSES, operation_id="getComputeResources", - openapi_extra=iri_meta_dict("production", "required"), + openapi_extra=iri_meta_dict("planned"), ) async def get_resources( request: Request, diff --git a/app/routers/filesystem/filesystem.py b/app/routers/filesystem/filesystem.py index b41a0ee6..4742cd45 100644 --- a/app/routers/filesystem/filesystem.py +++ b/app/routers/filesystem/filesystem.py @@ -31,7 +31,7 @@ response_model_exclude_unset=True, responses=DEFAULT_RESPONSES, operation_id="getFilesystemResources", - openapi_extra=iri_meta_dict("production", "required"), + openapi_extra=iri_meta_dict("planned"), ) async def get_resources( request: Request,