Skip to content

Commit

Permalink
Allow RemoteButler to be used for cutout backend
Browse files Browse the repository at this point in the history
Create Butlers using LabeledButlerFactory and provide the Gafaelfawr access token.  This allows us to use Butler client/server if the environment is configured to do so.
  • Loading branch information
dhirving committed Feb 14, 2024
1 parent 23e237e commit 953ac00
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Dockerfile.worker
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# are based on stack containers and install any required supporting code
# for the image cutout backend, Dramatiq, and the backend worker definition.

FROM lsstsqre/centos:7-stack-lsst_distrib-w_2022_40
FROM lsstsqre/centos:7-stack-lsst_distrib-w_2024_05

# Reset the user to root since we need to do system install tasks.
USER root
Expand Down
2 changes: 1 addition & 1 deletion scripts/install-worker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ set -x
# alternative (no releases and no tags).
mkdir /backend
cd /backend
git clone --depth 1 https://github.com/lsst-dm/image_cutout_backend.git
git clone --depth 1 -b 0.0.1 https://github.com/lsst-dm/image_cutout_backend.git
cd image_cutout_backend
setup -r .
scons install declare -t current
Expand Down
3 changes: 3 additions & 0 deletions src/vocutouts/actors.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def cutout(
job_id: str,
dataset_ids: list[str],
stencils: list[dict[str, Any]],
access_token: str,
) -> list[dict[str, str]]:
"""Stub for a circle cutout.
Expand All @@ -77,6 +78,8 @@ def cutout(
JSON-serializable (a requirement for Dramatiq) representations of the
`~vocutouts.models.stencils.Stencil` objects corresponding to the
user's request.
access_token
Gafaelfawr access token used to authenticate to Butler server.
Returns
-------
Expand Down
1 change: 1 addition & 0 deletions src/vocutouts/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def dispatch(self, job: Job, access_token: str) -> Message:
job.job_id,
cutout_params.ids,
[s.to_dict() for s in cutout_params.stencils],
access_token,
),
time_limit=job.execution_duration * 1000,
on_success=job_completed,
Expand Down
26 changes: 15 additions & 11 deletions src/vocutouts/workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from dramatiq.middleware import CurrentMessage
from dramatiq.results import Results
from dramatiq.results.backends import RedisBackend
from lsst.daf.butler import Butler
from lsst.daf.butler import LabeledButlerFactory
from lsst.image_cutout_backend import ImageCutoutBackend, projection_finders
from lsst.image_cutout_backend.stencils import (
SkyCircle,
Expand All @@ -37,8 +37,7 @@
)
from safir.logging import configure_logging

BACKENDS: dict[str, ImageCutoutBackend] = {}
"""Cache of image cutout backends by Butler repository label."""
BUTLER_FACTORY = LabeledButlerFactory()

configure_logging(
name=os.getenv("SAFIR_LOGGER", "vocutouts"),
Expand Down Expand Up @@ -86,7 +85,7 @@ class TaskTransientError(Exception):
"""Some transient problem occurred."""


def get_backend(butler_label: str) -> ImageCutoutBackend:
def get_backend(butler_label: str, access_token: str) -> ImageCutoutBackend:
"""Given the Butler label, retrieve or build a backend.
The dataset ID will be a URI of the form ``butler://<label>/<uuid>``.
Expand All @@ -103,15 +102,17 @@ def get_backend(butler_label: str) -> ImageCutoutBackend:
lsst.image_cutout_backend.ImageCutoutBackend
Backend to use.
"""
if butler_label in BACKENDS:
return BACKENDS[butler_label]
butler = Butler(butler_label)

butler = BUTLER_FACTORY.create_butler(
label=butler_label, access_token=access_token
)
# At present, projection finders and image cutout backend have no internal
# caching and are cheap to construct, so we just make a new one for each
# request.
projection_finder = projection_finders.ProjectionFinder.make_default()
output = os.environ["CUTOUT_STORAGE_URL"]
tmpdir = os.environ.get("CUTOUT_TMPDIR", "/tmp")
backend = ImageCutoutBackend(butler, projection_finder, output, tmpdir)
BACKENDS[butler_label] = backend
return backend
return ImageCutoutBackend(butler, projection_finder, output, tmpdir)


def parse_uri(uri: str) -> tuple[str, UUID]:
Expand All @@ -138,6 +139,7 @@ def cutout(
job_id: str,
dataset_ids: list[str],
stencils: list[dict[str, Any]],
access_token: str,
) -> list[dict[str, str]]:
"""Perform a cutout.
Expand All @@ -160,6 +162,8 @@ def cutout(
JSON-serializable (a requirement for Dramatiq) representations of the
`~vocutouts.models.stencils.Stencil` objects corresponding to the
user's request.
access_token
Gafaelfawr access token used to authenticate to Butler server.
Returns
-------
Expand Down Expand Up @@ -189,7 +193,7 @@ def cutout(

# Parse the dataset ID and retrieve an appropriate backend.
butler_label, uuid = parse_uri(dataset_ids[0])
backend = get_backend(butler_label)
backend = get_backend(butler_label, access_token)

# Convert the stencils to SkyStencils.
sky_stencils: list[SkyStencil] = []
Expand Down
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ def cutout_test(
job_id: str,
dataset_ids: list[str],
stencils: list[dict[str, Any]],
access_token: str,
) -> list[dict[str, Any]]:
message = CurrentMessage.get_current_message()
now = isodatetime(datetime.now(tz=timezone.utc))
job_started.send(job_id, message.message_id, now)
assert len(dataset_ids) == 1
assert access_token == "sometoken"
return [
{
"result_id": "cutout",
Expand Down

0 comments on commit 953ac00

Please sign in to comment.