Sitri = Vault + Pydantic: 사가의 연속, 지역 개발.



배경



이전 기사에서 Sitri을 사용하여 애플리케이션을 구성하는 방법에 대해 썼지만 로컬 개발에 대한 요점을 놓쳤습니다. Vault는 특히 여러 사람이 프로젝트를 진행하는 경우 두 배로 불편합니다.

Sitri에서 이 문제는 매우 간단하게 해결됩니다. 설정 클래스에 로컬 모드를 사용합니다. 즉, 아무 것도 다시 작성하거나 코드를 복제할 필요가 없으며 로컬 모드의 구조 json 파일은 다음 구조를 거의 완전히 반복합니다. 비밀.

이제 project에 문자 그대로 두 줄의 코드를 추가해 보겠습니다. + 프로젝트가 docker-compose에서 로컬로 실행되는 경우 이 모든 작업을 수행할 수 있는 방법을 보여 드리겠습니다.

코드 준비



먼저 ENV = "local"일 때 local_mode가 참이라는 데 동의합시다 :)

다음으로, provider_config.py를 약간 편집하고 구성 설정 클래스에서 상속할 BaseConfig 클래스를 생성할 것을 제안합니다. 코드를 복제하지 않기 위해 이 작업을 수행합니다. 즉, 설정 클래스 자체에는 고유한 항목만 포함됩니다.

import hvac
from sitri.providers.contrib.system import SystemConfigProvider
from sitri.providers.contrib.vault import VaultKVConfigProvider
from sitri.settings.contrib.vault import VaultKVSettings

configurator = SystemConfigProvider(prefix="superapp")
ENV = configurator.get("env")

is_local_mode = ENV == "local"
local_mode_file_path = configurator.get("local_mode_file_path")


def vault_client_factory() -> hvac.Client:
    client = hvac.Client(url=configurator.get("vault_api"))

    client.auth_approle(
        role_id=configurator.get("role_id"),
        secret_id=configurator.get("secret_id"),
    )

    return client


provider = VaultKVConfigProvider(
    vault_connector=vault_client_factory,
    mount_point=f"{configurator.get('app_name')}/{ENV}",
)


class BaseConfig(VaultKVSettings.VaultKVSettingsConfig):
    provider = provider
    local_mode = is_local_mode
    local_provider_args = {"json_path": local_mode_file_path}


이 필드에서 local_provider_args에 대해 약간은 JsonConfigProvider의 인스턴스를 생성하기 위한 인수를 지정합니다. 유효성이 검사되고 이 사전이 스키마와 일치해야 하므로 걱정하지 마세요. 더러운 속임수가 아닙니다. 그러나 로컬 공급자의 인스턴스를 직접 만들려면 선택적 local_provider 필드에 넣기만 하면 됩니다.

이제 기본 클래스에서 구성 클래스를 쉽게 상속할 수 있습니다. 예를 들어 Kafka에 연결하기 위한 설정 클래스는 다음과 같습니다.

from typing import Any, Dict

from pydantic import Field
from sitri.settings.contrib.vault import VaultKVSettings

from superapp.config.provider_config import BaseConfig, configurator


class KafkaSettings(VaultKVSettings):
    mechanism: str = Field(..., vault_secret_key="auth_mechanism")
    brokers: str = Field(...)
    auth_data: Dict[str, Any] = Field(...)

    class Config(BaseConfig):
        default_secret_path = "kafka"
        default_mount_point = f"{configurator.get('app_name')}/common"

        local_mode_path_prefix = "kafka"


보시다시피 필요한 변경 사항은 최소화됩니다. local_mode_path_prefix 일반 구성의 구조가 json 파일에 저장되도록 지정합니다. 이제 로컬 구성에 대해 이 json 파일을 작성해 보겠습니다.

{
    "db":
    {
        "host": "testhost",
        "password": "testpassword",
        "port": 1234,
        "user": "testuser"
    },
    "faust":
    {
        "agents":
        {
            "X":
            {
                "concurrency": 2,
                "partitions": 5
            }
        },
        "app_name": "superapp-workers",
        "default_concurrency": 5,
        "default_partitions_count": 10
    },
    "kafka":
    {
        "auth_data":
        {
            "password": "testpassword",
            "username": "testuser"
        },
        "brokers": "kafka://test",
        "mechanism": "SASL_PLAINTEXT"
    }
}


... 글쎄, 아니면 지난 기사의 끝에서 복사하여 붙여 넣으십시오. 보시다시피 여기에서는 모든 것이 매우 간단합니다. 추가 조사를 위해 docker-compose의 명령으로 패키지를 실행할 수 있도록 프로젝트 루트에 있는 main.py의 이름을 __main__.py로 바꿉니다.

애플리케이션을 컨테이너에 넣고 빌드를 즐기십시오.



가장 먼저 해야 할 일은 작은 Dockerfile을 작성하는 것입니다.

FROM python:3.8.3-buster

ENV PYTHONUNBUFFERED=1 \
    POETRY_VIRTUALENVS_CREATE=false \
    POETRY_VIRTUALENVS_IN_PROJECT=false \
    POETRY_NO_INTERACTION=1


RUN pip install poetry

RUN mkdir /superapp/
WORKDIR /superapp/

COPY ./pyproject.toml ./poetry.lock /superapp/
RUN poetry install --no-ansi

WORKDIR /


여기서는 종속성을 설치하기만 하면 됩니다. 로컬 개발용이므로 프로젝트 코드를 복사하지 않습니다.

다음으로 로컬 모드에 필요한 변수가 포함된 env 파일이 필요합니다.

SUPERAPP_ENV=local
SUPERAPP_LOCAL_MODE_FILE_PATH=/config.json
SUPERAPP_APP_NAME=superapp


보시다시피 로컬 모드에서는 응용 프로그램이 Vault를 "노크"하려고 시도하지 않기 때문에 Vault에 불필요한 구성 정보가 필요하지 않습니다.

마지막으로 작성해야 하는 것은 docker-compose.yml 파일 자체입니다.

# docker-compose config for local development
version: '3'
services:
  superapp:
    command: python3 -m superapp
    restart: always
    build:
      context: ./
      dockerfile: Dockerfile
    volumes:
      - ./superapp:/superapp
      - ./config.json:/config.json
    env_file:
      - .env.local


여기에서도 모든 것이 간단합니다. 위에서 컨테이너의 환경 변수에 쓴 것처럼 json 파일을 루트에 넣습니다.

이제 다음을 시작합니다.

docker-compose up



Creating article_sitri_vault_pydantic_superapp_1 ... done
Attaching to article_sitri_vault_pydantic_superapp_1

superapp_1  | db=DBSettings(user='testuser', password='testpassword', host='testhost', port=1234) faust=FaustSettings(app_name='superapp-workers', default_partitions_count=10, default_concurrency=5, agents={'X': AgentConfig(partitions=5, concurrency=2)}) kafka=KafkaSettings(mechanism='SASL_PLAINTEXT', brokers='kafka://test', auth_data={'password': 'testpassword', 'username': 'testuser'})

superapp_1  | {'db': {'user': 'testuser', 'password': 'testpassword', 'host': 'testhost', 'port': 1234}, 'faust': {'app_name': 'superapp-workers', 'default_partitions_count': 10, 'default_concurrency': 5, 'agents': {'X': {'partitions': 5, 'concurrency': 2}}}, 'kafka': {'mechanism': 'SASL_PLAINTEXT', 'brokers': 'kafka://test', 'auth_data': {'password': 'testpassword', 'username': 'testuser'}}}


보시다시피 모든 것이 성공적으로 시작되었고 json 파일의 정보가 모든 검사를 성공적으로 통과했으며 애플리케이션의 로컬 버전인 yuhhu!

이 "계속"의 코드는 리포지토리의 별도 분기에 넣었으므로 변경 후 모든 것이 어떻게 보이는지 확인할 수 있습니다. branch

좋은 웹페이지 즐겨찾기