Source code for globus_sdk.config.environments

from __future__ import annotations

import logging
import os
import typing as t

from .env_vars import get_environment_name

log = logging.getLogger(__name__)
# the format string for a service URL pulled out of the environment
# these are handled with uppercased service names, e.g.
#   `GLOBUS_SDK_SERVICE_URL_SEARCH=...`
_SERVICE_URL_VAR_FORMAT = "GLOBUS_SDK_SERVICE_URL_{}"


class EnvConfig:
    envname: str
    domain: str
    no_dotapi: list[str] = ["app", "auth"]
    automate_services: list[str] = ["actions", "flows", "timer"]

    # this same dict is inherited (and therefore shared!) by all subclasses
    _registry: dict[str, type[EnvConfig]] = {}

    # this is an easier hook to use than metaclass definition -- register every subclass
    # in this dict automatically
    #
    # as a result, anyone can define
    #
    #       class BetaEnv(EnvConfig):
    #           domain = "beta.foo.bar.example.com"
    #           envname = "beta"
    #
    # and retrieve it with get_config_by_name("beta")
    def __init_subclass__(cls, **kwargs: t.Any):
        super().__init_subclass__(**kwargs)
        cls._registry[cls.envname] = cls

    @classmethod
    def get_service_url(cls, service: str) -> str:
        # you can override any name with a config attribute
        service_url_attr = f"{service}_url"
        if hasattr(cls, service_url_attr):
            return t.cast(str, getattr(cls, service_url_attr))

        # the typical pattern for a service hostname is X.api.Y
        # X=transfer, Y=preview.globus.org => transfer.api.preview.globus.org
        # check `no_dotapi` for services which don't have `.api` in their names
        if service in cls.no_dotapi:
            return f"https://{service}.{cls.domain}/"
        if service in cls.automate_services:
            return f"https://{cls.envname}.{service}.automate.globus.org/"
        return f"https://{service}.api.{cls.domain}/"

    @classmethod
    def get_by_name(cls, env: str) -> type[EnvConfig] | None:
        return cls._registry.get(env)


[docs] def get_service_url(service: str, environment: str | None = None) -> str: """ Return the base URL for the given service in this environment. For example: >>> from globus_sdk.config import get_service_url >>> get_service_url("auth", environment="preview") 'https://auth.preview.globus.org/' >>> get_service_url("search", environment="production") 'https://search.api.globus.org/' :param service: The short name of the service to get the URL for :param environment: The name of the environment to use. If unspecified, this will use the ``GLOBUS_SDK_ENVIRONMENT`` environment variable. """ log.debug(f'Service URL Lookup for "{service}" under env "{environment}"') environment = environment or get_environment_name() # check for an environment variable of the form # GLOBUS_SDK_SERVICE_URL_* # and use it ahead of any env config if set varname = _SERVICE_URL_VAR_FORMAT.format(service.upper()) from_env = os.getenv(varname) if from_env: log.debug(f"Got URL from env var, {varname}={from_env}") return from_env conf = EnvConfig.get_by_name(environment) if not conf: raise ValueError(f'Unrecognized environment "{environment}"') url = conf.get_service_url(service) log.debug(f'Service URL Lookup Result: "{service}" is at "{url}"') return url
[docs] def get_webapp_url(environment: str | None = None) -> str: """ Return the URL to access the Globus web app in the given environment. For example: >>> get_webapp_url("preview") 'https://app.preview.globus.org/' :param environment: The name of the environment to use. If unspecified, this will use the ``GLOBUS_SDK_ENVIRONMENT`` environment variable. """ environment = environment or get_environment_name() return get_service_url("app", environment=environment)
# # public environments # class ProductionEnvConfig(EnvConfig): envname = "production" domain = "globus.org" nexus_url = "https://nexus.api.globusonline.org/" timer_url = "https://timer.automate.globus.org/" flows_url = "https://flows.automate.globus.org/" actions_url = "https://actions.automate.globus.org/" class PreviewEnvConfig(EnvConfig): envname = "preview" domain = "preview.globus.org" # # environments for internal use only # for envname in ["sandbox", "integration", "test", "staging"]: # use `type()` rather than the `class` syntax to control classnames type( f"{envname.title()}EnvConfig", (EnvConfig,), { "envname": envname, "domain": f"{envname}.globuscs.info", }, )