Skip to content

Commit

Permalink
Redirect calls to TES server + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
paulineribeyre committed Sep 24, 2024
1 parent 9a8ef0d commit 36826ce
Show file tree
Hide file tree
Showing 18 changed files with 2,393 additions and 1 deletion.
137 changes: 137 additions & 0 deletions .secrets.baseline
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"version": "1.5.0",
"plugins_used": [
{
"name": "ArtifactoryDetector"
},
{
"name": "AWSKeyDetector"
},
{
"name": "AzureStorageKeyDetector"
},
{
"name": "Base64HighEntropyString",
"limit": 4.5
},
{
"name": "BasicAuthDetector"
},
{
"name": "CloudantDetector"
},
{
"name": "DiscordBotTokenDetector"
},
{
"name": "GitHubTokenDetector"
},
{
"name": "GitLabTokenDetector"
},
{
"name": "HexHighEntropyString",
"limit": 3.0
},
{
"name": "IbmCloudIamDetector"
},
{
"name": "IbmCosHmacDetector"
},
{
"name": "IPPublicDetector"
},
{
"name": "JwtTokenDetector"
},
{
"name": "KeywordDetector",
"keyword_exclude": ""
},
{
"name": "MailchimpDetector"
},
{
"name": "NpmDetector"
},
{
"name": "OpenAIDetector"
},
{
"name": "PrivateKeyDetector"
},
{
"name": "PypiTokenDetector"
},
{
"name": "SendGridDetector"
},
{
"name": "SlackDetector"
},
{
"name": "SoftlayerDetector"
},
{
"name": "SquareOAuthDetector"
},
{
"name": "StripeDetector"
},
{
"name": "TelegramBotTokenDetector"
},
{
"name": "TwilioKeyDetector"
}
],
"filters_used": [
{
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
},
{
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
"min_level": 2
},
{
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
},
{
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
},
{
"path": "detect_secrets.filters.heuristic.is_lock_file"
},
{
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
},
{
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
},
{
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
},
{
"path": "detect_secrets.filters.heuristic.is_sequential_string"
},
{
"path": "detect_secrets.filters.heuristic.is_swagger_file"
},
{
"path": "detect_secrets.filters.heuristic.is_templated_secret"
}
],
"results": {
".github/workflows/ci.yml": [
{
"type": "Secret Keyword",
"filename": ".github/workflows/ci.yml",
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
"is_verified": false,
"line_number": 15
}
]
},
"generated_at": "2024-09-24T21:21:11Z"
}
51 changes: 51 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM quay.io/cdis/amazonlinux:python3.9-master AS build-deps

USER root

ENV appname=gen3workflow

RUN pip3 install --no-cache-dir --upgrade poetry

RUN yum update -y && yum install -y --setopt install_weak_deps=0 \
kernel-devel libffi-devel libxml2-devel libxslt-devel postgresql-devel python3-devel \
git && yum clean all

WORKDIR /$appname

# copy ONLY poetry artifact, install the dependencies but not gen3workflow
# this will make sure that the dependencies are cached
COPY poetry.lock pyproject.toml /$appname/
RUN poetry config virtualenvs.in-project true \
&& poetry install -vv --no-root --only main --no-interaction \
&& poetry show -v

# copy source code ONLY after installing dependencies
COPY . /$appname

# install gen3workflow
RUN poetry config virtualenvs.in-project true \
&& poetry install -vv --only main --no-interaction \
&& poetry show -v

# Creating the runtime image
FROM quay.io/cdis/amazonlinux:python3.9-master

ENV appname=gen3workflow

USER root

RUN pip3 install --no-cache-dir --upgrade poetry

RUN yum update -y && yum install -y --setopt install_weak_deps=0 \
postgresql-devel shadow-utils\
bash && yum clean all

RUN useradd -ms /bin/bash appuser

COPY --from=build-deps --chown=appuser:appuser /$appname /$appname

WORKDIR /$appname

USER appuser

CMD ["poetry", "run", "gunicorn", "gen3workflow.app:app", "-k", "uvicorn.workers.UvicornWorker", "-c", "gunicorn.conf.py", "--user", "appuser", "--group", "appuser"]
2 changes: 1 addition & 1 deletion docs/local_installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Run the server with auto-reloading:
```bash
python run.py
OR
uvicorn gen3workflow.asgi:app --reload
uvicorn gen3workflow.app:app --reload
```

Try out the API at <http://localhost:8000/_status> or <http://localhost:8000/docs> (you might have to set `DOCS_URL_PREFIX` to `""` in your configuration file for the docs endpoint to work).
Expand Down
6 changes: 6 additions & 0 deletions gen3workflow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from cdislogging import get_logger


# Can't read config yet. Just set to debug for now.
# Later, in app.get_app(), will actually set level based on config
logger = get_logger("gen3workflow", log_level="debug")
49 changes: 49 additions & 0 deletions gen3workflow/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from fastapi import FastAPI
import httpx
from importlib.metadata import version
# import os
# from gen3authz.client.arborist.async_client import ArboristClient

from gen3workflow import logger
from gen3workflow.config import config
from gen3workflow.routes.system import router as system_router
from gen3workflow.routes.ga4gh_tes import router as ga4gh_tes_router


def get_app(httpx_client=None) -> FastAPI:
logger.info("Initializing app")
config.validate()

debug = config["DEBUG"]
app = FastAPI(
title="Gen3Workflow",
version=version("gen3workflow"),
debug=debug,
root_path=config["DOCS_URL_PREFIX"],
)
app.async_client = httpx_client or httpx.AsyncClient()
app.include_router(system_router, tags=["System"])
app.include_router(ga4gh_tes_router, tags=["GA4GH TES"])

# Following will update logger level, propagate, and handlers
# TODO test that
# get_logger("gen3workflow", log_level="debug" if debug == True else "info")

logger.info("Initializing Arborist client")
# custom_arborist_url = os.environ.get("ARBORIST_URL", config["ARBORIST_URL"])
# if custom_arborist_url:
# app.arborist_client = ArboristClient(
# arborist_base_url=custom_arborist_url,
# authz_provider="requestor",
# logger=get_logger("requestor.gen3authz", log_level="debug"),
# )
# else:
# app.arborist_client = ArboristClient(
# authz_provider="requestor",
# logger=get_logger("requestor.gen3authz", log_level="debug"),
# )

return app


app = get_app()
23 changes: 23 additions & 0 deletions gen3workflow/config-default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
####################
# SERVER #
####################

DEBUG: true
# TEST_KEEP_DB: false
DOCS_URL_PREFIX: /gen3workflow

# # ignored if already set as an environment variable
# ARBORIST_URL:

# DB_DRIVER: postgresql
# DB_HOST: localhost
# DB_PORT: 5432
# DB_USER: postgres
# DB_PASSWORD: postgres
# DB_DATABASE: gen3workflow

####################
# GA4GH TES #
####################

TES_SERVER_URL: https://pauline.planx-pla.net/funnel #http://funnel-service
82 changes: 82 additions & 0 deletions gen3workflow/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from itertools import chain
# from jsonschema import validate
import os
from sqlalchemy.engine.url import make_url, URL

from gen3config import Config

from . import logger

DEFAULT_CFG_PATH = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "config-default.yaml"
)

NON_EMPTY_STRING_SCHEMA = {"type": "string", "minLength": 1}


class Gen3WorkflowConfig(Config):
def __init__(self, *args, **kwargs):
super(Gen3WorkflowConfig, self).__init__(*args, **kwargs)

# def post_process(self) -> None:
# # generate DB_URL from DB configs or env vars
# self["DB_URL"] = make_url(
# URL(
# drivername=os.environ.get("DB_DRIVER", self["DB_DRIVER"]),
# host=os.environ.get("DB_HOST", self["DB_HOST"]),
# port=os.environ.get("DB_PORT", self["DB_PORT"]),
# username=os.environ.get("DB_USER", self["DB_USER"]),
# password=os.environ.get("DB_PASSWORD", self["DB_PASSWORD"]),
# database=os.environ.get("DB_DATABASE", self["DB_DATABASE"]),
# ),
# )

def validate(self) -> None:
"""
Perform a series of sanity checks on a loaded config.
"""
logger.info("Validating configuration")
# self.validate_redirect_configs()

# def validate_redirect_configs(self):
# """
# Example:
# REDIRECT_CONFIGS:
# my_redirect:
# redirect_url: http://url.com
# params:
# - request_id
# """
# schema = {
# "type": "object",
# "patternProperties": {
# ".*": { # unique ID
# "type": "object",
# "additionalProperties": False,
# "required": ["redirect_url"],
# "properties": {
# "redirect_url": NON_EMPTY_STRING_SCHEMA,
# "params": {
# "type": "array",
# "items": {"enum": self.allowed_params_from_db},
# },
# },
# }
# },
# }
# validate(instance=self["REDIRECT_CONFIGS"], schema=schema)


config = Gen3WorkflowConfig(DEFAULT_CFG_PATH)
try:
if os.environ.get("GEN3WORKFLOW_CONFIG_PATH"):
config.load(config_path=os.environ["GEN3WORKFLOW_CONFIG_PATH"])
else:
CONFIG_SEARCH_FOLDERS = [
"/src",
"{}/.gen3/gen3workflow".format(os.path.expanduser("~")),
]
config.load(search_folders=CONFIG_SEARCH_FOLDERS)
except Exception:
logger.warning("Unable to load config, using default config...", exc_info=True)
config.load(config_path=DEFAULT_CFG_PATH)
Empty file added gen3workflow/routes/__init__.py
Empty file.
Loading

0 comments on commit 36826ce

Please sign in to comment.