Skip to content

Commit 8d41f65

Browse files
committed
Revert stomp config changes
1 parent 60cf3c9 commit 8d41f65

15 files changed

Lines changed: 96 additions & 280 deletions

File tree

docs/reference/openapi.yaml

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,5 @@
11
components:
22
schemas:
3-
BasicAuthentication:
4-
additionalProperties: false
5-
description: User credentials for basic authentication
6-
properties:
7-
password:
8-
description: Password to verify user's identity
9-
title: Password
10-
type: string
11-
username:
12-
description: Unique identifier for user
13-
title: Username
14-
type: string
15-
required:
16-
- username
17-
- password
18-
title: BasicAuthentication
19-
type: object
203
DeviceModel:
214
additionalProperties: false
225
description: Representation of a device
@@ -241,28 +224,6 @@ components:
241224
- new_state
242225
title: StateChangeRequest
243226
type: object
244-
StompConfig:
245-
additionalProperties: false
246-
description: Config for connecting to stomp broker
247-
properties:
248-
auth:
249-
$ref: '#/components/schemas/BasicAuthentication'
250-
description: Auth information for communicating with STOMP broker, if required
251-
title: Auth
252-
enabled:
253-
default: false
254-
description: True if blueapi should connect to stomp for asynchronous event
255-
publishing
256-
title: Enabled
257-
type: boolean
258-
url:
259-
default: tcp://localhost:61613
260-
format: uri
261-
minLength: 1
262-
title: Url
263-
type: string
264-
title: StompConfig
265-
type: object
266227
Task:
267228
additionalProperties: false
268229
description: Task that will run a plan
@@ -472,7 +433,7 @@ info:
472433
name: Apache 2.0
473434
url: https://www.apache.org/licenses/LICENSE-2.0.html
474435
title: BlueAPI Control
475-
version: 1.3.0
436+
version: 1.2.0
476437
openapi: 3.1.0
477438
paths:
478439
/config/oidc:
@@ -491,22 +452,6 @@ paths:
491452
summary: Get Oidc Config
492453
tags:
493454
- Meta
494-
/config/stomp:
495-
get:
496-
description: Retrieve the stomp configuration for the server.
497-
operationId: get_stomp_config_config_stomp_get
498-
responses:
499-
'200':
500-
content:
501-
application/json:
502-
schema:
503-
$ref: '#/components/schemas/StompConfig'
504-
description: Successful Response
505-
'204':
506-
description: No Stomp configured
507-
summary: Get Stomp Config
508-
tags:
509-
- Meta
510455
/devices:
511456
get:
512457
description: Retrieve information about all available devices.

helm/blueapi/config_schema.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,16 @@
480480
"type": "string"
481481
},
482482
"auth": {
483-
"$ref": "BasicAuthentication",
483+
"anyOf": [
484+
{
485+
"$ref": "BasicAuthentication"
486+
},
487+
{
488+
"type": "null"
489+
}
490+
],
484491
"default": null,
485-
"description": "Auth information for communicating with STOMP broker, if required",
486-
"title": "Auth"
492+
"description": "Auth information for communicating with STOMP broker, if required"
487493
}
488494
},
489495
"title": "StompConfig",

helm/blueapi/values.schema.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,9 +901,15 @@
901901
"type": "object",
902902
"properties": {
903903
"auth": {
904-
"title": "Auth",
905904
"description": "Auth information for communicating with STOMP broker, if required",
906-
"$ref": "BasicAuthentication"
905+
"anyOf": [
906+
{
907+
"$ref": "BasicAuthentication"
908+
},
909+
{
910+
"type": "null"
911+
}
912+
]
907913
},
908914
"enabled": {
909915
"title": "Enabled",

src/blueapi/client/client.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@
88
from pathlib import Path
99
from typing import Self
1010

11-
from bluesky_stomp.messaging import MessageContext
12-
from observability_utils.tracing import get_tracer, start_as_current_span
11+
from bluesky_stomp.messaging import MessageContext, StompClient
12+
from bluesky_stomp.models import Broker
13+
from observability_utils.tracing import (
14+
get_tracer,
15+
start_as_current_span,
16+
)
1317

1418
from blueapi.config import (
1519
ApplicationConfig,
@@ -197,7 +201,7 @@ class BlueapiClient:
197201
"""Unified client for controlling blueapi"""
198202

199203
_rest: BlueapiRestClient
200-
_event_bus_client: EventBusClient | None
204+
_events: EventBusClient | None
201205
_instrument_session: str | None = None
202206
_callbacks: dict[int, OnAnyEvent]
203207
_callback_id: itertools.count
@@ -208,7 +212,7 @@ def __init__(
208212
events: EventBusClient | None = None,
209213
):
210214
self._rest = rest
211-
self._event_bus_client = events
215+
self._events = events
212216
self._callbacks = {}
213217
self._callback_id = itertools.count()
214218

@@ -226,8 +230,20 @@ def from_config(cls, config: ApplicationConfig) -> Self:
226230
except Exception:
227231
... # Swallow exceptions
228232
rest = BlueapiRestClient(config.api, session_manager=session_manager)
229-
event_bus = EventBusClient.from_stomp_config(config.stomp)
230-
return cls(rest, event_bus)
233+
if config.stomp.enabled:
234+
assert config.stomp.url.host is not None, "Stomp URL missing host"
235+
assert config.stomp.url.port is not None, "Stomp URL missing port"
236+
client = StompClient.for_broker(
237+
broker=Broker(
238+
host=config.stomp.url.host,
239+
port=config.stomp.url.port,
240+
auth=config.stomp.auth,
241+
)
242+
)
243+
events = EventBusClient(client)
244+
return cls(rest, events)
245+
else:
246+
return cls(rest)
231247

232248
@cached_property
233249
@start_as_current_span(TRACER)
@@ -444,7 +460,7 @@ def run_task(
444460
of task execution.
445461
"""
446462

447-
if (event_bus := self._event_bus()) is None:
463+
if self._events is None:
448464
raise MissingStompConfigurationError(
449465
"Stomp configuration required to run plans is missing or disabled"
450466
)
@@ -488,8 +504,8 @@ def inner_on_event(event: AnyEvent, ctx: MessageContext) -> None:
488504
else:
489505
complete.set_result(event.task_status)
490506

491-
with event_bus:
492-
event_bus.subscribe_to_all_events(inner_on_event)
507+
with self._events:
508+
self._events.subscribe_to_all_events(inner_on_event)
493509
self._rest.update_worker_task(WorkerTask(task_id=task_id))
494510
return complete.result(timeout=timeout)
495511

@@ -728,10 +744,3 @@ def login(self, token_path: Path | None = None):
728744
auth.start_device_flow()
729745
else:
730746
print("Server is not configured to use authentication!")
731-
732-
def _event_bus(self) -> EventBusClient | None:
733-
if not self._event_bus_client:
734-
if stomp_config := self._rest.get_stomp_config():
735-
self._event_bus_client = EventBusClient.from_stomp_config(stomp_config)
736-
737-
return self._event_bus_client

src/blueapi/client/event_bus.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from collections.abc import Callable
2-
from typing import Self
32

4-
from bluesky_stomp.messaging import Broker, MessageContext, StompClient
3+
from bluesky_stomp.messaging import MessageContext, StompClient
54
from bluesky_stomp.models import MessageTopic
65

7-
from blueapi.config import StompConfig
86
from blueapi.core import DataEvent
97
from blueapi.worker import ProgressEvent, WorkerEvent
108

@@ -47,15 +45,3 @@ def subscribe_to_all_events(
4745
raise BlueskyStreamingError(
4846
"Unable to subscribe to messages from blueapi"
4947
) from err
50-
51-
@classmethod
52-
def from_stomp_config(cls, config: StompConfig) -> Self | None:
53-
if config.enabled:
54-
assert config.url.host is not None, "Stomp URL missing host"
55-
assert config.url.port is not None, "Stomp URL missing port"
56-
client = StompClient.for_broker(
57-
broker=Broker(
58-
host=config.url.host, port=config.url.port, auth=config.auth
59-
)
60-
)
61-
return cls(client)

src/blueapi/client/rest.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
)
1111
from pydantic import BaseModel, TypeAdapter, ValidationError
1212

13-
from blueapi.config import RestConfig, StompConfig
13+
from blueapi.config import RestConfig
1414
from blueapi.service.authentication import JWTAuth, SessionManager
1515
from blueapi.service.model import (
1616
DeviceModel,
@@ -233,14 +233,6 @@ def get_oidc_config(self) -> OIDCConfig | None:
233233
# Server is not using authentication
234234
return None
235235

236-
def get_stomp_config(self) -> StompConfig | None:
237-
try:
238-
return self._request_and_deserialize("/config/stomp", StompConfig)
239-
except (NoContentError, KeyError):
240-
# Older versions of the server may not have the endpoint implemented so
241-
# treat 404s as no configuration.
242-
return None
243-
244236
def get_python_environment(
245237
self, name: str | None = None, source: SourceInfo | None = None
246238
) -> PythonEnvironmentResponse:

src/blueapi/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class StompConfig(BlueapiBaseModel):
102102
default=False,
103103
)
104104
url: TcpUrl = TcpUrl("tcp://localhost:61613")
105-
auth: BasicAuthentication | SkipJsonSchema[None] = Field(
105+
auth: BasicAuthentication | None = Field(
106106
description="Auth information for communicating with STOMP broker, if required",
107107
default=None,
108108
)
@@ -300,7 +300,7 @@ class ApplicationConfig(BlueapiBaseModel):
300300
"""
301301

302302
#: API version to publish in OpenAPI schema
303-
REST_API_VERSION: ClassVar[str] = "1.3.0"
303+
REST_API_VERSION: ClassVar[str] = "1.2.0"
304304

305305
LICENSE_INFO: ClassVar[dict[str, str]] = {
306306
"name": "Apache 2.0",

src/blueapi/service/interface.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,6 @@ def get_oidc_config() -> OIDCConfig | None:
272272
return config().oidc
273273

274274

275-
def get_stomp_config() -> StompConfig | None:
276-
return config().stomp
277-
278-
279275
def get_python_env(
280276
name: str | None = None, source: SourceInfo | None = None
281277
) -> PythonEnvironmentResponse:

src/blueapi/service/main.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from starlette.responses import JSONResponse
3535
from super_state_machine.errors import TransitionError
3636

37-
from blueapi.config import ApplicationConfig, OIDCConfig, StompConfig, Tag
37+
from blueapi.config import ApplicationConfig, OIDCConfig, Tag
3838
from blueapi.service import interface
3939
from blueapi.worker import TrackableTask, WorkerState
4040
from blueapi.worker.event import TaskStatusEnum
@@ -226,22 +226,6 @@ def get_oidc_config(
226226
return config
227227

228228

229-
@open_router.get(
230-
"/config/stomp",
231-
tags=[Tag.META],
232-
responses={status.HTTP_204_NO_CONTENT: {"description": "No Stomp configured"}},
233-
)
234-
@start_as_current_span(TRACER)
235-
def get_stomp_config(
236-
runner: Annotated[WorkerDispatcher, Depends(_runner)],
237-
) -> StompConfig:
238-
"""Retrieve the stomp configuration for the server."""
239-
config = runner.run(interface.get_stomp_config)
240-
if config is None:
241-
raise HTTPException(status_code=status.HTTP_204_NO_CONTENT)
242-
return config
243-
244-
245229
@secure_router.get("/plans", tags=[Tag.PLAN])
246230
@start_as_current_span(TRACER)
247231
def get_plans(runner: Annotated[WorkerDispatcher, Depends(_runner)]) -> PlanResponse:

tests/system_tests/test_blueapi_system.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -169,21 +169,16 @@ def expected_devices() -> DeviceResponse:
169169
)
170170

171171

172-
def authenticated_get_methods() -> list[str]:
173-
# Get a list of methods that take only one argument (self) and require
174-
# authentication. This will currently return
175-
# ['get_plans', 'get_devices', 'get_state', 'get_all_tasks',
176-
# 'get_active_task','get_environment','resume', 'stop']
172+
@pytest.fixture
173+
def blueapi_rest_client_get_methods() -> list[str]:
174+
# Get a list of methods that take only one argument (self)
177175
return [
178-
method
179-
for method in BlueapiRestClient.__dict__
180-
if callable(getattr(BlueapiRestClient, method))
181-
and not method.startswith("__")
182-
and len(inspect.signature(getattr(BlueapiRestClient, method)).parameters) == 1
183-
and "self" in inspect.signature(getattr(BlueapiRestClient, method)).parameters
184-
# oidc_config and stomp config can be accessed without auth
185-
and method != "get_oidc_config"
186-
and method != "get_stomp_config"
176+
name
177+
for name, method in BlueapiRestClient.__dict__.items()
178+
if not name.startswith("__")
179+
and callable(method)
180+
and len(params := inspect.signature(method).parameters) == 1
181+
and "self" in params
187182
]
188183

189184

@@ -215,10 +210,15 @@ def reset_numtracker():
215210
yield
216211

217212

218-
@pytest.mark.parametrize("method_name", authenticated_get_methods())
219-
def test_cannot_access_endpoints(client_without_auth: BlueapiClient, method_name: str):
220-
with pytest.raises(BlueskyRemoteControlError, match=r"<Response \[401\]>"):
221-
getattr(client_without_auth._rest, method_name)()
213+
def test_cannot_access_endpoints(
214+
client_without_auth: BlueapiClient, blueapi_rest_client_get_methods: list[str]
215+
):
216+
blueapi_rest_client_get_methods.remove(
217+
"get_oidc_config"
218+
) # get_oidc_config can be accessed without auth
219+
for get_method in blueapi_rest_client_get_methods:
220+
with pytest.raises(BlueskyRemoteControlError, match=r"<Response \[401\]>"):
221+
getattr(client_without_auth._rest, get_method)()
222222

223223

224224
def test_can_get_oidc_config_without_auth(client_without_auth: BlueapiClient):

0 commit comments

Comments
 (0)