Exemple #1
0
def fetch_data_sources():
    # type: () -> DataSourceConfig
    global DATA_SOURCES  # pylint: disable=W0603,global-statement

    if DATA_SOURCES:
        return DATA_SOURCES

    settings = get_settings()
    data_source_config = settings.get("weaver.data_sources", "")
    if data_source_config:
        data_source_config = get_weaver_config_file(
            str(data_source_config), WEAVER_DEFAULT_DATA_SOURCES_CONFIG)
        if not os.path.isabs(data_source_config):
            data_source_config = os.path.normpath(
                os.path.join(WEAVER_ROOT_DIR, data_source_config))
        try:
            with open(data_source_config, mode="r", encoding="utf-8") as f:
                DATA_SOURCES = yaml.safe_load(f)  # both JSON/YAML
        except Exception as exc:
            raise ValueError(
                f"Data sources file [{data_source_config}] cannot be loaded due to error: [{exc!r}]."
            )
    if not DATA_SOURCES:
        raise ValueError(
            "No data sources found in setting 'weaver.data_sources'. Data source required for EMS."
        )
    return DATA_SOURCES
Exemple #2
0
def get_wps_output_context(request):
    # type: (AnyRequestType) -> Optional[str]
    """
    Obtains and validates allowed values for sub-directory context of WPS outputs in header ``X-WPS-Output-Context``.

    :raises HTTPUnprocessableEntity: if the header was provided an contains invalid or illegal value.
    :returns: validated context or None if not specified.
    """
    headers = getattr(request, "headers", {})
    ctx = get_header(sd.WpsOutputContextHeader.name, headers)
    if not ctx:
        settings = get_settings(request)
        ctx_default = settings.get("weaver.wps_output_context", None)
        if not ctx_default:
            return None
        LOGGER.debug("Using default 'wps.wps_output_context': %s", ctx_default)
        ctx = ctx_default
    cxt_found = re.match(r"^(?=[\w-]+)([\w-]+/?)+$", ctx)
    if cxt_found and cxt_found[0] == ctx:
        ctx_matched = ctx[:-1] if ctx.endswith("/") else ctx
        LOGGER.debug("Using request 'X-WPS-Output-Context': %s", ctx_matched)
        return ctx_matched
    raise HTTPUnprocessableEntity(
        json={
            "code": "InvalidHeaderValue",
            "name": sd.WpsOutputContextHeader.name,
            "description":
            "Provided value for 'X-WPS-Output-Context' request header is invalid.",
            "cause":
            "Value must be an alphanumeric context directory or tree hierarchy of sub-directory names.",
            "value": str(ctx)
        })
Exemple #3
0
def includeme(config):
    from weaver.wps.app import pywps_view

    settings = get_settings(config)
    logger = logging.getLogger(__name__)
    if not asbool(settings.get("weaver.wps", True)):
        logger.debug(
            "Weaver WPS disable. WPS KVP/XML endpoint will not be available.")
    else:
        logger.debug("Weaver WPS enabled.")
        wps_path = get_wps_path(settings)
        wps_service = Service(name="wps", path=wps_path)
        logger.debug("Adding WPS KVP/XML schemas.")
        wps_tags = [
            sd.TAG_GETCAPABILITIES, sd.TAG_DESCRIBEPROCESS, sd.TAG_EXECUTE,
            sd.TAG_WPS
        ]
        wps_service.add_view("GET",
                             pywps_view,
                             tags=wps_tags,
                             renderer=OUTPUT_FORMAT_XML,
                             schema=sd.WPSEndpoint(),
                             response_schemas=sd.wps_responses)
        wps_service.add_view("POST",
                             pywps_view,
                             tags=wps_tags,
                             renderer=OUTPUT_FORMAT_XML,
                             schema=sd.WPSEndpoint(),
                             response_schemas=sd.wps_responses)
        logger.debug("Adding WPS KVP/XML view.")
        config.add_route(**sd.service_api_route_info(wps_service, settings))
        config.add_view(pywps_view, route_name=wps_service.name)
Exemple #4
0
def get_schema_ref(schema, container=None, ref_type="$schema", ref_name=True):
    # type: (colander.SchemaNode, Optional[AnySettingsContainer], str, True) -> Dict[str, str]
    """
    Generates the JSON OpenAPI schema reference relative to the current `Weaver` instance.

    The provided schema should be one of the items listed in ``#/definitions`` of the ``/json`` endpoint.
    No validation is accomplished to avoid long processing of all references.

    If setting ``weaver.schema_url`` is set, this value will be used direct as fully-defined base URL.
    This could be used to refer to a static endpoint where schemas are hosted.
    Otherwise, the current Web Application resolved location is employed with JSON OpenAPI path.

    :param schema: schema-node instance or type for which to generate the OpenAPI reference.
    :param container: application settings to retrieve the base URL of the schema location.
    :param ref_type: key employed to form the reference (e.g.: "$schema", "$ref", "@schema", etc.)
    :param ref_name: indicate if the plain name should also be included under field ``"schema"``.
    :return: OpenAPI schema reference
    """
    is_instance = isinstance(schema, colander.SchemaNode)
    assert is_instance or (inspect.isclass(schema) and issubclass(schema, colander.SchemaNode))
    if is_instance:
        schema = type(schema)
    schema_name = schema.__name__
    settings = get_settings(container)
    weaver_schema_url = settings.get("weaver.schema_url")
    if not weaver_schema_url:
        restapi_path = get_wps_restapi_base_url(container)
        weaver_schema_url = f"{restapi_path}{sd.openapi_json_service.path}#/definitions"
    weaver_schema_url = weaver_schema_url.rstrip("/").strip()
    schema_ref = {ref_type: f"{weaver_schema_url}/{schema_name}"}
    if ref_name:
        schema_ref.update({"schema": schema_name})
    return schema_ref
Exemple #5
0
def get_pywps_service(environ=None, is_worker=False):
    """
    Generates the PyWPS Service that provides *older* WPS-1/2 XML endpoint.
    """
    environ = environ or {}
    try:
        # get config file
        settings = get_settings(app)
        pywps_cfg = environ.get("PYWPS_CFG") or settings.get(
            "PYWPS_CFG") or os.getenv("PYWPS_CFG")
        if not isinstance(
                pywps_cfg,
                ConfigParser) or not settings.get("weaver.wps_configured"):
            load_pywps_config(app, config=pywps_cfg)

        # call pywps application with processes filtered according to the adapter's definition
        process_store = get_db(app).get_store(StoreProcesses)
        processes_wps = [
            process.wps() for process in process_store.list_processes(
                visibility=VISIBILITY_PUBLIC)
        ]
        service = WorkerService(processes_wps,
                                is_worker=is_worker,
                                settings=settings)
    except Exception as ex:
        LOGGER.exception(
            "Error occurred during PyWPS Service and/or Processes setup.")
        raise OWSNoApplicableCode(
            "Failed setup of PyWPS Service and/or Processes. Error [{!r}]".
            format(ex))
    return service
Exemple #6
0
def get_mongodb_connection(container):
    # type: (AnySettingsContainer) -> Database
    """
    Obtains the basic database connection from settings.
    """
    settings = get_settings(container)
    settings_default = [("mongodb.host", "localhost"), ("mongodb.port", 27017),
                        ("mongodb.db_name", "weaver")]
    for setting, default in settings_default:
        if settings.get(setting, None) is None:
            warnings.warn(
                f"Setting '{setting}' not defined in registry, using default [{default}]."
            )
            settings[setting] = default
    client = pymongo.MongoClient(
        settings["mongodb.host"],
        int(settings["mongodb.port"]),
        connect=False,
        # Must specify representation since PyMongo 4.0 and also to avoid Python 3.6 error
        #  https://pymongo.readthedocs.io/en/stable/examples/uuid.html#unspecified
        uuidRepresentation="pythonLegacy",
        # Require that datetime objects be returned with timezone awareness.
        # This ensures that missing 'tzinfo' does not get misinterpreted as locale time when
        # loading objects from DB, since by default 'datetime.datetime' employs 'tzinfo=None'
        # for locale naive datetime objects, while MongoDB stores Date in ISO-8601 format.
        tz_aware=True)
    return client[settings["mongodb.db_name"]]
Exemple #7
0
def map_wps_output_location(reference,
                            container,
                            url=False,
                            exists=True,
                            file_scheme=False):
    # type: (str, AnySettingsContainer, bool, bool, bool) -> Optional[str]
    """
    Obtains the mapped WPS output location of a file where applicable.

    :param reference: Local file path or file URL to be mapped.
    :param container: Retrieve application settings.
    :param url: Perform URL mapping (local path -> URL endpoint), or map to local path (URL -> local path).
    :param exists: Ensure that the mapped file exists, otherwise don't map it (otherwise ``None``).
    :param file_scheme:
        Ensure that the 'file://' scheme is applied to resulting local file location when mapped from WPS output URL.
        When in 'reverse' mode, 'file://' is always removed if present to form a potential local file path.
    :returns: Mapped reference that corresponds to the local/URL WPS output location.
    """
    settings = get_settings(container)
    wps_out_dir = get_wps_output_dir(settings)
    wps_out_url = get_wps_output_url(settings)
    if url and reference.startswith("file://"):
        reference = reference[7:]
    if url and reference.startswith(wps_out_dir):
        wps_out_ref = reference.replace(wps_out_dir, wps_out_url, 1)
        if not exists or os.path.isfile(reference):
            return wps_out_ref
    elif not url and reference.startswith(wps_out_url):
        wps_out_ref = reference.replace(wps_out_url, wps_out_dir, 1)
        if not exists or os.path.isfile(wps_out_ref):
            if file_scheme:
                return "file://" + wps_out_ref
            return wps_out_ref
    return None
Exemple #8
0
def get_pywps_service(environ=None, is_worker=False):
    # type: (SettingsType, bool) -> WorkerService
    """
    Generates the PyWPS Service that provides WPS-1/2 XML endpoint.
    """
    environ = environ or {}
    try:
        # get config file
        registry = get_registry()
        settings = get_settings(registry)
        pywps_cfg = environ.get("PYWPS_CFG") or settings.get(
            "PYWPS_CFG") or os.getenv("PYWPS_CFG")
        if not isinstance(
                pywps_cfg,
                ConfigParser) or not settings.get("weaver.wps_configured"):
            load_pywps_config(settings, config=pywps_cfg)

        # call pywps application with processes filtered according to the adapter's definition
        process_store = get_db(registry).get_store(
            StoreProcesses)  # type: StoreProcesses
        processes_wps = [
            process.wps() for process in process_store.list_processes(
                visibility=Visibility.PUBLIC)
        ]
        service = WorkerService(processes_wps,
                                is_worker=is_worker,
                                settings=settings)
    except Exception as ex:
        LOGGER.exception(
            "Error occurred during PyWPS Service and/or Processes setup.")
        raise OWSNoApplicableCode(
            f"Failed setup of PyWPS Service and/or Processes. Error [{ex!r}]")
    return service
Exemple #9
0
def raise_job_dismissed(job, container=None):
    # type: (Job, Optional[AnySettingsContainer]) -> None
    """
    Raise the appropriate messages for dismissed :term:`Job` status.
    """
    if job.status == Status.DISMISSED:
        # provide the job status links since it is still available for reference
        settings = get_settings(container)
        job_links = job.links(settings)
        job_links = [
            link for link in job_links
            if link["rel"] in ["status", "alternate", "collection", "up"]
        ]
        raise JobGone(
            json={
                "title": "JobDismissed",
                "type": "JobDismissed",
                "status": JobGone.code,
                "detail": "Job was dismissed and artifacts have been removed.",
                "cause": {
                    "status": job.status
                },
                "value": str(job.id),
                "links": job_links
            })
Exemple #10
0
def get_providers(request):
    """
    Lists registered providers.
    """
    store = get_db(request).get_store(StoreServices)
    providers = []

    for service in store.list_services():
        try:
            if service.type.lower() != "wps":
                continue

            wps = WebProcessingService(url=service.url,
                                       headers=get_cookie_headers(
                                           request.headers))
            providers.append(
                dict(id=service.name,
                     title=getattr(wps.identification, "title", ""),
                     abstract=getattr(wps.identification, "abstract", ""),
                     url="{base_url}/providers/{provider_id}".format(
                         base_url=get_wps_restapi_base_url(
                             get_settings(request)),
                         provider_id=service.name),
                     public=service.public))
        except Exception as exc:
            warnings.warn(
                "Exception occurred while fetching wps {0} : {1!r}".format(
                    service.url, exc), NonBreakingExceptionWarning)

    return HTTPOk(json={"providers": providers})
Exemple #11
0
    def json(self, container=None):     # pylint: disable=W0221,arguments-differ
        # type: (Optional[AnySettingsContainer]) -> JSON
        """Obtain the JSON data representation for response body.

        .. note::
            Settings are required to update API shortcut URLs to job additional information.
            Without them, paths will not include the API host, which will not resolve to full URI.
        """
        settings = get_settings(container) if container else {}
        job_json = {
            "jobID": self.id,
            "status": self.status,
            "message": self.status_message,
            "duration": self.duration_str,
            "percentCompleted": self.progress,
        }
        job_url = self._job_url(settings)
        # TODO: use links (https://github.com/crim-ca/weaver/issues/58)
        if self.status in JOB_STATUS_CATEGORIES[STATUS_CATEGORY_FINISHED]:
            job_status = map_status(self.status)
            if job_status == STATUS_SUCCEEDED:
                resource_type = "result"
            else:
                resource_type = "exceptions"
            job_json[resource_type] = "{job_url}/{res}".format(job_url=job_url, res=resource_type.lower())
        job_json["logs"] = "{job_url}/logs".format(job_url=job_url)
        return sd.JobStatusInfo().deserialize(job_json)
Exemple #12
0
def _get_settings_or_wps_config(
        container,  # type: AnySettingsContainer
        weaver_setting_name,  # type: str
        config_setting_section,  # type: str
        config_setting_name,  # type: str
        default_not_found,  # type: str
        message_not_found,  # type: str
        load=False,  # type: bool
):  # type: (...) -> str

    settings = get_settings(container)
    found = settings.get(weaver_setting_name)
    if not found:
        if not settings.get("weaver.wps_configured") and load:
            load_pywps_config(container)
        # not yet defined on first load permitted if settings retrieved early on
        if pywps_config.CONFIG:
            found = pywps_config.CONFIG.get(config_setting_section,
                                            config_setting_name)
    if not isinstance(found, str):
        LOGGER.warning(
            "%s not set in settings or WPS configuration, using default value.",
            message_not_found)
        found = default_not_found
    return found.strip()
Exemple #13
0
def main(global_config, **settings):
    """
    Creates a Pyramid WSGI application for Weaver.
    """
    setup_loggers(settings)
    LOGGER.info("Initiating weaver application")

    # validate and fix configuration
    weaver_config = get_weaver_configuration(settings)
    settings.update({"weaver.configuration": weaver_config})

    # Parse extra_options and add each of them in the settings dict
    LOGGER.info("Parsing extra options...")
    settings.update(
        parse_extra_options(settings.get("weaver.extra_options", "")))

    # load requests options if found, otherwise skip
    LOGGER.info("Checking for request options file...")
    req_file = get_weaver_config_file(settings.get("weaver.request_options",
                                                   ""),
                                      WEAVER_DEFAULT_REQUEST_OPTIONS_CONFIG,
                                      generate_default_from_example=False)
    if req_file:
        LOGGER.info("Loading request options...")
        with open(req_file, "r") as f:
            settings.update({"weaver.request_options": yaml.safe_load(f)})
    else:
        LOGGER.warning("No request options found.")

    # add default caching regions if they were omitted in config file
    if settings.get("weaver.celery", False):
        LOGGER.info("Celery runner detected. Skipping cache options setup.")
    else:
        LOGGER.info("Adding default caching options...")
        setup_cache(settings)

    LOGGER.info("Setup celery configuration...")
    local_config = Configurator(settings=settings)
    if global_config.get("__file__") is not None:
        local_config.include("pyramid_celery")
        local_config.configure_celery(global_config["__file__"])
    local_config.include("weaver")

    LOGGER.info("Running database migration...")
    db = get_db(settings)
    db.run_migration()

    if settings.get("weaver.celery", False):
        LOGGER.info("Celery runner detected. Skipping process registration.")
    else:
        LOGGER.info("Registering builtin processes...")
        register_builtin_processes(local_config)

        LOGGER.info("Registering WPS-1 processes from configuration file...")
        wps_processes_file = get_settings(local_config).get(
            "weaver.wps_processes_file")
        register_wps_processes_from_config(wps_processes_file, local_config)

    return local_config.make_wsgi_app()
Exemple #14
0
 def __init__(self, container):
     # type: (AnySettingsContainer) -> None
     super(MongoDatabase, self).__init__(container)
     self._database = get_mongodb_engine(container)
     self._settings = get_settings(container)
     self._stores = dict()
     LOGGER.debug("Database [%s] using versions: {MongoDB: %s, pymongo: %s}",
                  self._database.name, self._database.client.server_info()["version"], pymongo.__version__)
Exemple #15
0
def get_wps_output_path(container):
    # type: (AnySettingsContainer) -> str
    """
    Retrieves the WPS output path (without hostname) for staging XML status, logs and process outputs.
    Searches directly in settings, then `weaver.wps_cfg` file, or finally, uses the default values if not found.
    """
    return get_settings(container).get("weaver.wps_output_path") or urlparse(
        get_wps_output_url(container)).path
Exemple #16
0
def get_wps_url(container, load=True):
    # type: (AnySettingsContainer, bool) -> str
    """
    Retrieves the full WPS URL (hostname + WPS path).

    Searches directly in settings, then `weaver.wps_cfg` file, or finally, uses the default values if not found.
    """
    return get_settings(container).get("weaver.wps_url") or get_weaver_url(
        container) + get_wps_path(container, load)
Exemple #17
0
def get_wps_restapi_base_url(container):
    # type: (AnySettingsContainer) -> str
    settings = get_settings(container)
    weaver_rest_url = settings.get("weaver.wps_restapi_url")
    if not weaver_rest_url:
        weaver_url = get_weaver_url(settings)
        restapi_path = wps_restapi_base_path(settings)
        weaver_rest_url = weaver_url + restapi_path
    return weaver_rest_url.rstrip("/").strip()
Exemple #18
0
def submit_job(request, reference, tags=None):
    # type: (Request, Union[Service, Process], Optional[List[str]]) -> JSON
    """
    Generates the job submission from details retrieved in the request.

    .. seealso::
        :func:`submit_job_handler` to provide elements pre-extracted from requests or from other parsing.
    """
    # validate body with expected JSON content and schema
    if CONTENT_TYPE_APP_JSON not in request.content_type:
        raise HTTPBadRequest(
            "Request 'Content-Type' header other than '{}' not supported.".
            format(CONTENT_TYPE_APP_JSON))
    try:
        json_body = request.json_body
    except Exception as ex:
        raise HTTPBadRequest(
            "Invalid JSON body cannot be decoded for job submission. [{}]".
            format(ex))
    provider_id = None  # None OK if local
    process_id = None  # None OK if remote, but can be found as well if available from WPS-REST path
    tags = tags or []
    if isinstance(reference, Process):
        service_url = reference.processEndpointWPS1
        process_id = reference.id
        visibility = reference.visibility
        is_workflow = reference.type == PROCESS_WORKFLOW
        is_local = True
        tags += "local"
    elif isinstance(reference, Service):
        service_url = reference.url
        provider_id = reference.id
        process_id = request.matchdict.get("process_id")
        visibility = VISIBILITY_PUBLIC
        is_workflow = False
        is_local = False
        tags += "remote"
    else:
        LOGGER.error("Expected process/service, got: %s", type(reference))
        raise TypeError("Invalid process or service reference to execute job.")
    tags = request.params.get("tags", "").split(",") + tags
    user = request.authenticated_userid
    lang = request.accept_language.header_value
    headers = dict(request.headers)
    settings = get_settings(request)
    return submit_job_handler(json_body,
                              settings,
                              service_url,
                              provider_id,
                              process_id,
                              is_workflow,
                              is_local,
                              visibility,
                              language=lang,
                              auth=headers,
                              tags=tags,
                              user=user)
Exemple #19
0
def includeme(config):
    # type: (Configurator) -> None
    settings = get_settings(config)
    if asbool(settings.get("weaver.vault", True)):
        LOGGER.info("Adding file vault...")
        config.add_route(**sd.service_api_route_info(sd.vault_service, settings))
        config.add_route(**sd.service_api_route_info(sd.vault_file_service, settings))
        config.add_view(v.upload_file, route_name=sd.vault_service.name, request_method="POST")
        config.add_view(v.describe_file, route_name=sd.vault_file_service.name, request_method="HEAD")
        config.add_view(v.download_file, route_name=sd.vault_file_service.name, request_method="GET")
Exemple #20
0
def api_frontpage(request):
    """Frontpage of weaver."""

    # import here to avoid circular import errors
    from weaver.config import get_weaver_configuration

    settings = get_settings(request)
    weaver_url = get_weaver_url(settings)
    weaver_config = get_weaver_configuration(settings)

    weaver_api = asbool(settings.get("weaver.wps_restapi"))
    weaver_api_url = get_wps_restapi_base_url(settings) if weaver_api else None
    weaver_api_def = weaver_api_url + sd.api_swagger_ui_uri if weaver_api else None
    weaver_api_doc = settings.get("weaver.wps_restapi_doc", None) if weaver_api else None
    weaver_api_ref = settings.get("weaver.wps_restapi_ref", None) if weaver_api else None
    weaver_wps = asbool(settings.get("weaver.wps"))
    weaver_wps_url = get_wps_url(settings) if weaver_wps else None
    weaver_conform_url = weaver_url + sd.api_conformance_uri
    weaver_process_url = weaver_url + sd.processes_uri
    weaver_links = [
        {"href": weaver_url, "rel": "self", "type": CONTENT_TYPE_APP_JSON, "title": "This document"},
        {"href": weaver_conform_url, "rel": "conformance", "type": CONTENT_TYPE_APP_JSON,
         "title": "WPS 2.0/3.0 REST-JSON Binding Extension conformance classes implemented by this service."},
    ]
    if weaver_api_def:
        weaver_links.append({"href": weaver_api_def, "rel": "service", "type": CONTENT_TYPE_APP_JSON,
                             "title": "API definition of this service."})
    if isinstance(weaver_api_doc, str):
        if "." in weaver_api_doc:   # pylint: disable=E1135,unsupported-membership-test
            ext_type = weaver_api_doc.split(".")[-1]
            doc_type = "application/{}".format(ext_type)
        else:
            doc_type = CONTENT_TYPE_TEXT_PLAIN  # default most basic type
        weaver_links.append({"href": weaver_api_doc, "rel": "documentation", "type": doc_type,
                             "title": "API documentation about this service."})
    if weaver_api_ref:
        weaver_links.append({"href": weaver_api_ref, "rel": "reference", "type": CONTENT_TYPE_APP_JSON,
                             "title": "API reference specification of this service."})
    weaver_links.append({"href": weaver_process_url, "rel": "processes", "type": CONTENT_TYPE_APP_JSON,
                         "title": "Processes offered by this service."})

    return {
        "message": "Weaver Information",
        "configuration": weaver_config,
        "parameters": [
            {"name": "api", "enabled": weaver_api,
             "url": weaver_api_url,
             "doc": weaver_api_doc,
             "api": weaver_api_def,
             "ref": weaver_api_ref},
            {"name": "wps", "enabled": weaver_wps,
             "url": weaver_wps_url},
        ],
        "links": weaver_links,
    }
Exemple #21
0
def submit_job(request, reference, tags=None):
    # type: (Request, Union[Service, Process], Optional[List[str]]) -> JSON
    """
    Generates the job submission from details retrieved in the request.

    .. seealso::
        :func:`submit_job_handler` to provide elements pre-extracted from requests or from other parsing.
    """
    # validate body with expected JSON content and schema
    if CONTENT_TYPE_APP_JSON not in request.content_type:
        raise HTTPBadRequest(json={
            "code": "InvalidHeaderValue",
            "name": "Content-Type",
            "description": "Request 'Content-Type' header other than '{}' not supported.".format(CONTENT_TYPE_APP_JSON),
            "value": str(request.content_type)
        })
    try:
        json_body = request.json_body
    except Exception as ex:
        raise HTTPBadRequest("Invalid JSON body cannot be decoded for job submission. [{}]".format(ex))
    # validate context if needed later on by the job for early failure
    context = get_wps_output_context(request)

    provider_id = None  # None OK if local
    process_id = None   # None OK if remote, but can be found as well if available from WPS-REST path
    tags = tags or []
    lang = request.accept_language.header_value  # can only preemptively check if local process
    if isinstance(reference, Process):
        service_url = reference.processEndpointWPS1
        process_id = reference.id
        visibility = reference.visibility
        is_workflow = reference.type == PROCESS_WORKFLOW
        is_local = True
        tags += "local"
        if lang and request.accept_language.best_match(ACCEPT_LANGUAGES) is None:
            raise HTTPNotAcceptable("Requested language [{}] is not in supported languages [{}].".format(
                lang, ", ".join(ACCEPT_LANGUAGES)
            ))
    elif isinstance(reference, Service):
        service_url = reference.url
        provider_id = reference.id
        process_id = request.matchdict.get("process_id")
        visibility = VISIBILITY_PUBLIC
        is_workflow = False
        is_local = False
        tags += "remote"
    else:
        LOGGER.error("Expected process/service, got: %s", type(reference))
        raise TypeError("Invalid process or service reference to execute job.")
    tags = request.params.get("tags", "").split(",") + tags
    user = request.authenticated_userid
    headers = dict(request.headers)
    settings = get_settings(request)
    return submit_job_handler(json_body, settings, service_url, provider_id, process_id, is_workflow, is_local,
                              visibility, language=lang, auth=headers, tags=tags, user=user, context=context)
Exemple #22
0
 def __init__(self, request):
     # type: (WPSRequest) -> None
     self.request = request
     self.cookies = get_cookie_headers(self.request.http_request.headers)
     self.headers = {
         "Accept": CONTENT_TYPE_APP_JSON,
         "Content-Type": CONTENT_TYPE_APP_JSON
     }
     self.settings = get_settings(app)
     self.verify = asbool(
         self.settings.get("weaver.ows_proxy_ssl_verify", True))
Exemple #23
0
 def __init__(self, request, update_status):
     # type: (WorkerRequest, UpdateStatusPartialFunction) -> None
     self.request = request
     self.headers = {
         "Accept": ContentType.APP_JSON,
         "Content-Type": ContentType.APP_JSON
     }
     self.settings = get_settings()
     self.update_status = update_status  # type: UpdateStatusPartialFunction
     self.temp_staging = set()
     self.stage_output_id_nested = False
Exemple #24
0
    def host_file(file_name):
        settings = get_settings(app)
        weaver_output_url = get_wps_output_url(settings)
        weaver_output_dir = get_wps_output_dir(settings)
        file_name = file_name.replace("file://", "")

        if not file_name.startswith(weaver_output_dir):
            raise Exception(
                "Cannot host files outside of the output path : {0}".format(
                    file_name))
        return file_name.replace(weaver_output_dir, weaver_output_url)
Exemple #25
0
def retrieve_data_source_url(data_source):
    # type: (Optional[Text]) -> str
    """
    Finds the data source URL using the provided data source identifier.

    :returns: found URL, 'default' data source if not found, or current weaver WPS Rest API base URL if `None`.
    """
    if data_source is None:
        # get local data source
        return get_wps_restapi_base_url(get_settings())
    data_sources = fetch_data_sources()
    return data_sources[data_source if data_source in data_sources else get_default_data_source(data_sources)]["ades"]
Exemple #26
0
def redoc_ui_cached(request):
    settings = get_settings(request)
    weaver_server_url = get_weaver_url(settings)
    spec = openapi_json_cached(base_url=weaver_server_url,
                               settings=settings,
                               use_docstring_summary=True,
                               use_refs=False)
    data_mako = {"openapi_spec": json.dumps(spec, ensure_ascii=False)}
    resp = render_to_response("templates/redoc_ui.mako",
                              data_mako,
                              request=request)
    return resp
Exemple #27
0
def includeme(config):
    settings = get_settings(config)
    if asbool(settings.get("weaver.build_docs", False)):
        LOGGER.info("Skipping database when building docs...")
        return

    LOGGER.info("Adding database...")

    def _add_db(request):
        return MongoDatabase(request.registry)

    config.add_request_method(_add_db, "db", reify=True)
Exemple #28
0
def get_processes(request):
    """
    List registered processes (GetCapabilities). Optionally list both local and provider processes.
    """
    detail = asbool(request.params.get("detail", True))
    try:
        # get local processes and filter according to schema validity
        # (previously deployed process schemas can become invalid because of modified schema definitions
        processes, invalid_processes = get_processes_filtered_by_valid_schemas(
            request)
        if invalid_processes:
            raise HTTPServiceUnavailable(
                "Previously deployed processes are causing invalid schema integrity errors. "
                "Manual cleanup of following processes is required: {}".format(
                    invalid_processes))
        response_body = {
            "processes":
            processes if detail else [get_any_id(p) for p in processes]
        }

        # if 'EMS' and '?providers=True', also fetch each provider's processes
        settings = get_settings(request)
        if get_weaver_configuration(settings) == WEAVER_CONFIGURATION_EMS:
            queries = parse_request_query(request)
            if "providers" in queries and asbool(
                    queries["providers"][0]) is True:
                prov_url = "{host}/providers".format(host=request.host_url)
                providers_response = request_extra("GET",
                                                   prov_url,
                                                   settings=settings,
                                                   headers=request.headers,
                                                   cookies=request.cookies)
                providers = providers_response.json()
                response_body.update({"providers": providers})
                for i, provider in enumerate(providers):
                    provider_id = get_any_id(provider)
                    proc_url = "{host}/providers/{prov}/processes".format(
                        host=request.host_url, prov=provider_id)
                    response = request_extra("GET",
                                             proc_url,
                                             settings=settings,
                                             headers=request.headers,
                                             cookies=request.cookies)
                    processes = response.json().get("processes", [])
                    response_body["providers"][i].update({
                        "processes":
                        processes
                        if detail else [get_any_id(p) for p in processes]
                    })
        return HTTPOk(json=response_body)
    except colander.Invalid as ex:
        raise HTTPBadRequest("Invalid schema: [{!s}]".format(ex))
Exemple #29
0
def get_vault_url(file, container=None):
    # type: (Union[VaultFile, uuid.UUID, str], Optional[AnySettingsContainer]) -> str
    """
    Obtain the vault link corresponding to the file.
    """
    if isinstance(file, uuid.UUID) or is_uuid(file):
        file_id = str(file)
    else:
        file_id = file.id
    settings = get_settings(container)
    base_url = get_weaver_url(settings)
    vault_url = base_url + sd.vault_file_service.path.format(file_id=file_id)
    return vault_url
Exemple #30
0
def openapi_json(request):  # noqa: F811
    # type: (Request) -> dict
    """
    Weaver OpenAPI schema definitions.
    """
    # obtain 'server' host and api-base-path, which doesn't correspond necessarily to the app's host and path
    # ex: 'server' adds '/weaver' with proxy redirect before API routes
    settings = get_settings(request)
    weaver_server_url = get_weaver_url(settings)
    LOGGER.debug("Request app URL:   [%s]", request.url)
    LOGGER.debug("Weaver config URL: [%s]", weaver_server_url)
    return openapi_json_cached(base_url=weaver_server_url,
                               use_docstring_summary=True,
                               settings=settings)