Skip to content

Commit de15f43

Browse files
authored
Replace trafaret by pydantic for services config (iteration 1/2) (#1890)
- storage service updated - EXTRA: adds .env-devel and Makefile recipe for local development - EXTRA: adds swagger UI at /dev/doc - webserver keeps for the moment both More details in PR#1890
1 parent 80f7da4 commit de15f43

File tree

112 files changed

+1613
-1105
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+1613
-1105
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from enum import Enum
2+
3+
from pydantic import conint, constr, confloat
4+
5+
PortInt = conint(gt=0, lt=65535)
6+
7+
VersionTag = constr(regex=r"^v\d$")
8+
9+
NonNegativeFloat = confloat(ge=0) # NOTE: = 0.0 + PositiveFloat
10+
11+
12+
class LogLevel(str, Enum):
13+
DEBUG = "DEBUG"
14+
INFO = "INFO"
15+
WARNING = "WARNING"
16+
ERROR = "ERROR"
17+
18+
19+
class BootModeEnum(str, Enum):
20+
"""
21+
Values taken by SC_BOOT_MODE environment variable
22+
set in Dockerfile and used during docker/boot.sh
23+
"""
24+
25+
DEFAULT = "default"
26+
LOCAL = "local-development"
27+
DEBUG = "debug-ptvsd"
28+
PRODUCTION = "production"
29+
DEVELOPMENT = "development"
30+
31+
32+
class BuildTargetEnum(str, Enum):
33+
"""
34+
Values taken by SC_BUILD_TARGET environment variable
35+
set in Dockerfile that defines the stage targeted in the
36+
docker image build
37+
"""
38+
39+
BUILD = "build"
40+
CACHE = "cache"
41+
PRODUCTION = "production"
42+
DEVELOPMENT = "development"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Common settings
3+
"""
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
Bases to build ApplicationSettings
3+
4+
TODO: when py 3.7 the use https://pydantic-docs.helpmanual.io/usage/models/#generic-models
5+
"""
6+
import logging
7+
from typing import Optional
8+
from pydantic import Field, BaseSettings, validator, AnyHttpUrl
9+
from ..basic_types import PortInt, BootModeEnum, LogLevel, VersionTag
10+
11+
12+
class BaseFastApiAppSettings(BaseSettings):
13+
# DOCKER
14+
boot_mode: Optional[BootModeEnum] = Field(..., env="SC_BOOT_MODE")
15+
16+
# LOGGING
17+
log_level: LogLevel = Field("DEBUG", env=["LOG_LEVEL", "LOGLEVEL"])
18+
19+
@property
20+
def logging_level(self) -> int:
21+
return getattr(logging, self.log_level)
22+
23+
# SERVER (see : https://www.uvicorn.org/settings/)
24+
host: str = "0.0.0.0" # nosec
25+
port: PortInt = 8000
26+
debug: bool = False # If True, debug tracebacks should be returned on errors.
27+
28+
# DEBUGGING
29+
remote_debug_port: PortInt = 3000
30+
31+
32+
class BaseAiohttpAppSettings(BaseFastApiAppSettings):
33+
port: PortInt = 8080
34+
35+
36+
class BaseServiceAPISettings(BaseSettings):
37+
host: str
38+
port: PortInt
39+
vtag: VersionTag = Field("v0", description="Service API's version tag")
40+
41+
url: Optional[AnyHttpUrl] = None
42+
43+
@validator("url", pre=True)
44+
@classmethod
45+
def autofill_url(cls, v, values):
46+
if v is None:
47+
return AnyHttpUrl.build(
48+
scheme="http",
49+
host=values["host"],
50+
port=f"{values['port']}",
51+
path=f"/{values['vtag']}",
52+
)
53+
return v

packages/models-library/src/models_library/celery.py renamed to packages/models-library/src/models_library/settings/celery.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55

66
class CeleryConfig(BaseSettings):
77
@classmethod
8-
def create_from_env(cls) -> "CeleryConfig":
8+
def create_from_env(cls, **override) -> "CeleryConfig":
99
# this calls trigger env parsers
10-
return cls(rabbit=RabbitConfig(), redis=RedisConfig())
10+
return cls(rabbit=RabbitConfig(), redis=RedisConfig(), **override)
1111

12+
# NOTE: Defaults are evaluated at import time, use create_from_env to build instances
1213
rabbit: RabbitConfig = RabbitConfig()
1314
redis: RedisConfig = RedisConfig()
15+
1416
task_name: str = "simcore.comp.task"
17+
1518
publication_timeout: PositiveInt = 60
1619

1720
@property
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from typing import Optional
2+
3+
from pydantic import BaseSettings, Field, PostgresDsn, SecretStr, conint, validator
4+
5+
from ..basic_types import PortInt
6+
7+
8+
class PostgresSettings(BaseSettings):
9+
dns: Optional[PostgresDsn] = None
10+
11+
# entrypoint
12+
host: str
13+
port: PortInt = 5432
14+
15+
# auth
16+
user: str
17+
password: SecretStr
18+
19+
# database
20+
db: str
21+
22+
# pool connection limits
23+
minsize: conint(ge=1) = 10
24+
maxsize: conint(ge=1) = 10
25+
26+
dsn: Optional[PostgresDsn] = Field(None, description="Database Source Name")
27+
28+
@validator("maxsize")
29+
@classmethod
30+
def check_size(cls, v, values):
31+
if not (values["minsize"] <= v):
32+
raise ValueError(f"assert minsize={values['minsize']} <= maxsize={v}")
33+
return v
34+
35+
@validator("dsn", pre=True)
36+
@classmethod
37+
def autofill_dsn(cls, v, values):
38+
if v is None:
39+
return PostgresDsn.build(
40+
scheme="postgresql",
41+
user=values["user"],
42+
password=values["password"].get_secret_value(),
43+
host=values["host"],
44+
port=f"{values['port']}",
45+
path=f"/{values['db']}",
46+
)
47+
return v
48+
49+
class Config:
50+
case_sensitive = False
51+
env_prefix = "POSTGRES_"

packages/models-library/src/models_library/rabbit.py renamed to packages/models-library/src/models_library/settings/rabbit.py

File renamed without changes.

packages/models-library/src/models_library/redis.py renamed to packages/models-library/src/models_library/settings/redis.py

File renamed without changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from pydantic import BaseSettings
2+
3+
4+
class S3Config(BaseSettings):
5+
endpoint: str = "minio:9000"
6+
access_key: str = "12345678"
7+
secret_key: str = "12345678"
8+
bucket_name: str = "simcore"
9+
secure: bool = False
10+
11+
class Config:
12+
case_sensitive = False
13+
env_prefix = "S3_"

packages/pytest-simcore/src/pytest_simcore/rabbit_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import pytest
1313
import tenacity
1414

15-
from models_library.rabbit import RabbitConfig
15+
from models_library.settings.rabbit import RabbitConfig
1616

1717
from .helpers.utils_docker import get_service_published_port
1818

packages/pytest-simcore/src/pytest_simcore/redis_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import aioredis
99
import pytest
1010
import tenacity
11-
from models_library.redis import RedisConfig
11+
from models_library.settings.redis import RedisConfig
1212
from servicelib.redis_utils import RedisRetryPolicyUponInitialization
1313
from yarl import URL
1414

0 commit comments

Comments
 (0)