Skip to content

Commit 6af44c0

Browse files
committed
Add OpaClient to wrap OPA interactions
1 parent 0e68df4 commit 6af44c0

5 files changed

Lines changed: 57 additions & 0 deletions

File tree

helm/blueapi/config_schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@
340340
"minLength": 1,
341341
"title": "Root",
342342
"type": "string"
343+
},
344+
"audience": {
345+
"default": "account",
346+
"title": "Audience",
347+
"type": "string"
343348
}
344349
},
345350
"title": "OpaConfig",

helm/blueapi/values.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,11 @@
756756
"title": "OpaConfig",
757757
"type": "object",
758758
"properties": {
759+
"audience": {
760+
"title": "Audience",
761+
"default": "account",
762+
"type": "string"
763+
},
759764
"root": {
760765
"title": "Root",
761766
"default": "http://localhost:8181/",

src/blueapi/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ class Tag(StrEnum):
298298

299299
class OpaConfig(BlueapiBaseModel):
300300
root: HttpUrl = HttpUrl("http://localhost:8181")
301+
audience: str = "account"
301302

302303

303304
class ApplicationConfig(BlueapiBaseModel):
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import logging
2+
from collections.abc import Mapping
3+
from contextlib import AbstractAsyncContextManager, aclosing, nullcontext
4+
from typing import Any, Self
5+
6+
from aiohttp import ClientSession
7+
8+
from blueapi.config import OpaConfig
9+
10+
LOGGER = logging.getLogger(__name__)
11+
12+
13+
class OpaClient:
14+
def __init__(self, instrument: str, config: OpaConfig):
15+
LOGGER.info("Creating OpaClient for %s with config %s", instrument, config)
16+
self._instrument = instrument
17+
self._config = config
18+
self._session = ClientSession(base_url=config.root.encoded_string())
19+
self._audience = config.audience
20+
21+
async def aclose(self):
22+
LOGGER.info("Closing OPA session")
23+
await self._session.close()
24+
25+
async def _call_opa(self, endpoint: str, data: Mapping[str, Any]) -> bool:
26+
resp = await self._session.post(
27+
endpoint,
28+
json={
29+
"input": {
30+
"beamline": self._instrument,
31+
"audience": self._audience,
32+
**data,
33+
}
34+
},
35+
)
36+
return (await resp.json())["result"]
37+
38+
@classmethod
39+
def for_config(
40+
cls, instrument: str, config: OpaConfig | None
41+
) -> AbstractAsyncContextManager[Self | None]:
42+
if config:
43+
return aclosing(cls(instrument, config))
44+
LOGGER.info("No OPA config provided - not creating OpaClient")
45+
return nullcontext()

tests/unit_tests/test_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ def test_config_yaml_parsed(temp_yaml_config_file):
339339
},
340340
"opa": {
341341
"root": "http://opa.example.com/",
342+
"audience": "account",
342343
},
343344
},
344345
{

0 commit comments

Comments
 (0)