Skip to content

Commit

Permalink
Merge pull request #21 from lsst-sqre/tickets/DM-41830
Browse files Browse the repository at this point in the history
[DM-41830] Add SIAv2 server function
  • Loading branch information
cbanek authored Dec 11, 2023
2 parents 6fe107d + 83f6a7a commit 543e69a
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 65 deletions.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ install_requires =
kubernetes
maproxy
notebook
pyvo
pyvo @ git+https://github.com/astropy/pyvo.git@7682a1809cb2169cc2ffd9313feb6a4abd7f7e37
requests
tornado

Expand Down
74 changes: 14 additions & 60 deletions src/lsst/rsp/catalog.py
Original file line number Diff line number Diff line change
@@ -1,71 +1,24 @@
import os
import warnings
from typing import Optional

import pyvo
import pyvo.auth.authsession
import requests
from deprecated import deprecated

from .utils import get_access_token


def _get_tap_url(env_var: str, url: str) -> str:
tapurl = os.getenv("EXTERNAL_" + env_var + "_URL")
if not tapurl:
tapurl = (os.getenv("EXTERNAL_INSTANCE_URL") or "") + (
os.getenv(env_var + "_ROUTE") or "/api/" + url
)
return tapurl


def _get_datalink_url() -> str:
return os.getenv("EXTERNAL_INSTANCE_URL", "") + "/api/datalink"


def _get_cutout_url() -> str:
return os.getenv("EXTERNAL_INSTANCE_URL", "") + "/api/cutout"


def _get_auth() -> Optional[pyvo.auth.authsession.AuthSession]:
tap_url = _get_tap_url("TAP", "tap")
obstap_url = _get_tap_url("OBSTAP", "obstap")
ssotap_url = _get_tap_url("SSOTAP", "ssotap")
s = requests.Session()
tok = get_access_token()
if not tok:
return None
s.headers["Authorization"] = "Bearer " + tok
auth = pyvo.auth.authsession.AuthSession()
auth.credentials.set("lsst-token", s)
auth.add_security_method_for_url(_get_datalink_url(), "lsst-token")
auth.add_security_method_for_url(_get_cutout_url(), "lsst-token")
auth.add_security_method_for_url(tap_url, "lsst-token")
auth.add_security_method_for_url(tap_url + "/sync", "lsst-token")
auth.add_security_method_for_url(tap_url + "/async", "lsst-token")
auth.add_security_method_for_url(tap_url + "/tables", "lsst-token")
auth.add_security_method_for_url(obstap_url, "lsst-token")
auth.add_security_method_for_url(obstap_url + "/sync", "lsst-token")
auth.add_security_method_for_url(obstap_url + "/async", "lsst-token")
auth.add_security_method_for_url(obstap_url + "/tables", "lsst-token")
auth.add_security_method_for_url(ssotap_url, "lsst-token")
auth.add_security_method_for_url(ssotap_url + "/sync", "lsst-token")
auth.add_security_method_for_url(ssotap_url + "/async", "lsst-token")
auth.add_security_method_for_url(ssotap_url + "/tables", "lsst-token")
return auth
from .utils import get_pyvo_auth, get_service_url


@deprecated(reason='Please use get_tap_service("tap")')
def get_catalog() -> pyvo.dal.TAPService:
return get_tap_service("tap")


@deprecated(reason='Please use get_tap_service("obstap")')
@deprecated(reason='Please use get_tap_service("live")')
def get_obstap_service() -> pyvo.dal.TAPService:
return get_tap_service("obstap")
return get_tap_service("live")


def get_tap_service(*args: str) -> pyvo.dal.TAPService:
"""Returns a TAP service instance to interact with the
requested TAP service."""
if len(args) == 0:
warnings.warn(
'get_tap_service() is deprecated, use get_tap_service("tap")',
Expand All @@ -76,12 +29,13 @@ def get_tap_service(*args: str) -> pyvo.dal.TAPService:
else:
database = args[0]

if database == "tap":
tap_url = _get_tap_url("TAP", "tap")
elif database == "obstap":
tap_url = _get_tap_url("OBSTAP", "obstap")
elif database == "ssotap":
tap_url = _get_tap_url("SSOTAP", "ssotap")
# We renamed the name of the TAP service from obstap
# to live
if database == "obstap":
database = "live"

if database in ["live", "tap", "ssotap"]:
tap_url = get_service_url(database)
else:
raise Exception(database + " is not a valid tap service")

Expand All @@ -95,7 +49,7 @@ def get_tap_service(*args: str) -> pyvo.dal.TAPService:
#
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=UserWarning)
ts = pyvo.dal.TAPService(tap_url, _get_auth())
ts = pyvo.dal.TAPService(tap_url, get_pyvo_auth())
return ts


Expand All @@ -110,5 +64,5 @@ def retrieve_query(query_url: str) -> pyvo.dal.AsyncTAPJob:
#
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=UserWarning)
atj = pyvo.dal.AsyncTAPJob(query_url, _get_auth())
atj = pyvo.dal.AsyncTAPJob(query_url, get_pyvo_auth())
return atj
13 changes: 13 additions & 0 deletions src/lsst/rsp/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from pyvo.dal import SIA2Service

from .utils import get_pyvo_auth, get_service_url


def get_siav2_service(label: str) -> SIA2Service:
"""Return a configured SIA2Service object that is ready to use."""
if label != "staff":
raise Exception(label + " data not available at your location")

# No matter what, we've only got one sia server per environment
# so for now just do some checking.
return SIA2Service(get_service_url("siav2"), get_pyvo_auth())
52 changes: 48 additions & 4 deletions src/lsst/rsp/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from typing import Any, Optional, Union

import bokeh.io
import pyvo.auth.authsession
import requests

_NO_K8S = False

Expand Down Expand Up @@ -53,6 +55,51 @@ def get_hostname() -> str:
return os.environ.get("HOSTNAME") or "localhost"


def get_service_url(name: str, env_name: Optional[str] = None) -> str:
if not env_name:
env_name = name.upper()

url = os.getenv(f"EXTERNAL_{env_name}_URL")
if url:
return url

fqdn = os.getenv("EXTERNAL_INSTANCE_URL") or ""
path = os.getenv(f"{env_name}_ROUTE") or f"/api/{name}"
return f"{fqdn}/{path}"


def get_pyvo_auth() -> Optional[pyvo.auth.authsession.AuthSession]:
"""Utility function to create a pyvo compatible auth object."""
tap_url = get_service_url("tap")
obstap_url = get_service_url("obstap")
ssotap_url = get_service_url("ssotap")
siav2_url = get_service_url("siav2")
s = requests.Session()
tok = get_access_token()
if not tok:
return None
s.headers["Authorization"] = "Bearer " + tok
auth = pyvo.auth.authsession.AuthSession()
auth.credentials.set("lsst-token", s)
auth.add_security_method_for_url(get_service_url("cutout"), "lsst-token")
auth.add_security_method_for_url(get_service_url("datalink"), "lsst-token")
auth.add_security_method_for_url(siav2_url, "lsst-token")
auth.add_security_method_for_url(siav2_url + "/query", "lsst-token")
auth.add_security_method_for_url(tap_url, "lsst-token")
auth.add_security_method_for_url(tap_url + "/sync", "lsst-token")
auth.add_security_method_for_url(tap_url + "/async", "lsst-token")
auth.add_security_method_for_url(tap_url + "/tables", "lsst-token")
auth.add_security_method_for_url(obstap_url, "lsst-token")
auth.add_security_method_for_url(obstap_url + "/sync", "lsst-token")
auth.add_security_method_for_url(obstap_url + "/async", "lsst-token")
auth.add_security_method_for_url(obstap_url + "/tables", "lsst-token")
auth.add_security_method_for_url(ssotap_url, "lsst-token")
auth.add_security_method_for_url(ssotap_url + "/sync", "lsst-token")
auth.add_security_method_for_url(ssotap_url + "/async", "lsst-token")
auth.add_security_method_for_url(ssotap_url + "/tables", "lsst-token")
return auth


def show_with_bokeh_server(obj: Any) -> None:
"""Method to wrap bokeh with proxy URL"""

Expand Down Expand Up @@ -81,10 +128,7 @@ def jupyter_proxy_url(port: Optional[int] = None) -> str:
full_url = urllib.parse.urljoin(user_url, proxy_url_path)
return full_url

# The type: ignore is needed because the alternate form of notebook_url
# (https://docs.bokeh.org/en/latest/docs/reference/io.html#bokeh.io.show)
# isn't in bokeh's type hints.
bokeh.io.show(obj=obj, notebook_url=jupyter_proxy_url) # type:ignore
bokeh.io.show(obj=obj, notebook_url=jupyter_proxy_url)


def get_pod() -> Optional[client.V1Pod]:
Expand Down

0 comments on commit 543e69a

Please sign in to comment.