Start introducing RequestResponse

This commit is contained in:
Marek Wolan
2024-03-08 12:42:22 +00:00
parent 59bbc0e733
commit d331224b45
5 changed files with 47 additions and 11 deletions

View File

@@ -1,12 +1,13 @@
# flake8: noqa
"""Core of the PrimAITE Simulator."""
from abc import abstractmethod
from typing import Callable, Dict, List, Optional, Union
from typing import Callable, Dict, List, Literal, Optional, Union
from uuid import uuid4
from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, ConfigDict, Field, validate_call
from primaite import getLogger
from primaite.interface.request import RequestResponse
_LOGGER = getLogger(__name__)
@@ -22,7 +23,7 @@ class RequestPermissionValidator(BaseModel):
@abstractmethod
def __call__(self, request: List[str], context: Dict) -> bool:
"""Use the request and context paramters to decide whether the request should be permitted."""
"""Use the request and context parameters to decide whether the request should be permitted."""
pass
@@ -42,7 +43,7 @@ class RequestType(BaseModel):
the request can be performed or not.
"""
func: Callable[[List[str], Dict], None]
func: Callable[[List[str], Dict], RequestResponse]
"""
``func`` is a function that accepts a request and a context dict. Typically this would be a lambda function
that invokes a class method of your SimComponent. For example if the component is a node and the request type is for
@@ -71,7 +72,8 @@ class RequestManager(BaseModel):
request_types: Dict[str, RequestType] = {}
"""maps request name to an RequestType object."""
def __call__(self, request: Callable[[List[str], Dict], None], context: Dict) -> None:
@validate_call
def __call__(self, request: List[str], context: Dict) -> RequestResponse:
"""
Process an request request.
@@ -84,23 +86,25 @@ class RequestManager(BaseModel):
:raises RuntimeError: If the request parameter does not have a valid request name as the first item.
"""
request_key = request[0]
request_options = request[1:]
if request_key not in self.request_types:
msg = (
f"Request {request} could not be processed because {request_key} is not a valid request name",
"within this RequestManager",
)
_LOGGER.error(msg)
raise RuntimeError(msg)
# _LOGGER.error(msg)
# raise RuntimeError(msg)
_LOGGER.debug(msg)
return RequestResponse(status="failure", data={"reason": msg})
request_type = self.request_types[request_key]
request_options = request[1:]
if not request_type.validator(request_options, context):
_LOGGER.debug(f"Request {request} was denied due to insufficient permissions")
return
return RequestResponse(status="failure", data={"reason": "request validation failed"})
request_type.func(request_options, context)
return request_type.func(request_options, context)
def add_request(self, name: str, request_type: RequestType) -> None:
"""

View File

@@ -87,6 +87,7 @@ class DomainController(SimComponent):
"account",
RequestType(
func=lambda request, context: self.accounts[request.pop(0)].apply_request(request, context),
# TODO: not sure what should get returned here, revisit
validator=GroupMembershipValidator(allowed_groups=[AccountGroup.DOMAIN_ADMIN]),
),
)

View File

@@ -1,5 +1,6 @@
from typing import Dict
from primaite.interface.request import RequestResponse
from primaite.simulator.core import RequestManager, RequestType, SimComponent
from primaite.simulator.domain.controller import DomainController
from primaite.simulator.network.container import Network
@@ -31,7 +32,8 @@ class Simulation(SimComponent):
rm.add_request("network", RequestType(func=self.network._request_manager))
# pass through domain requests to the domain object
rm.add_request("domain", RequestType(func=self.domain._request_manager))
rm.add_request("do_nothing", RequestType(func=lambda request, context: ()))
# if 'do_nothing' is requested, just return a success
rm.add_request("do_nothing", RequestType(func=lambda request, context: RequestResponse(status="success")))
return rm
def describe_state(self) -> Dict: