Config Management Code Recipe (CN)#

示例代码的背景信息请参考 Centralized Multi Environment Config Management (CN).

Declare your Config Schema#

aws_ops_alpha 提供了一些工具方便你定义你的 Multi environment Config 对象. 下面是一个例子.

[5]:
# config/define.py module
import typing as T
import dataclasses
from functools import cached_property

# import aws_ops_alpha
from aws_ops_alpha.api import (
    BaseEnv,
    BaseConfig,
)


# split your config field into groups, declare them in different mixin class,
# then you can assemble them together.
# it can improve your code maintainability.
@dataclasses.dataclass
class AppMixin:
    username: T.Optional[str] = dataclasses.field(default=None)
    password: T.Optional[str] = dataclasses.field(default=None)


@dataclasses.dataclass
class Env(
    AppMixin,
    BaseEnv,
):
    pass


# Create a reference property to access per-environment config data
@dataclasses.dataclass
class Config(BaseConfig[Env]):
    @classmethod
    def get_current_env(cls) -> str:  # pragma: no cover
        return detect_current_env()

    @cached_property
    def sbx(self):  # pragma: no cover
        return self.get_env(env_name="sbx")

    @cached_property
    def tst(self) -> Env:  # pragma: no cover
        return self.get_env(env_name="tst")

    @cached_property
    def prd(self) -> Env:  # pragma: no cover
        return self.get_env(env_name="prd")

    @cached_property
    def env(self) -> Env:
        return self.get_env(env_name=self.get_current_env())

Load Your Config Data.#

aws_ops_alpha 提供了一套储存 Config 数据的最佳实践. 如果你使用了这套最佳实践, 你可以直接用 Config.smart_load 方法来读取 config 对象.

这套储存 Config 数据的最佳实践的详细规则如下.

  1. 如果是在 local 本地开发 Runtime 下, 则从 path_config_json (储存了非敏感 Config 数据, 通常就在 git repo 里面), path_config_secret_json (储存了敏感数据, 通常在 ${HOME} 目录下).

  2. 如果是在 CI Runtime 下, 则会先从 Git repo 中的 path_config_json 读取一部分数据. 目的是为了根据 project_name 计算出 parameter_name 的值, 然后根据这个值到 AWS Parameter Store 获得 Config 数据. 因为 project_name 不是敏感数据, 所以这里我们不需要 path_config_secret_json, 并且我们也不允许将敏感数据放在 CI 环境中.

  3. 如果是在 App 的 Runtime 下, 则先读取 PARAMETER_NAME 环境变量的值, 然后根据这个值到 AWS Parameter Store 获得 Config 数据.

以下是一个使用了这套最佳实践的真实项目的代码示例.

[ ]:
# config/load.py module
config = Config.smart_load(
    runtime=runtime,
    env_name_enum_class=EnvNameEnum,
    env_class=Env,
    path_config_json=paths.path_config_json,
    path_config_secret_json=paths.path_config_secret_json,
    boto_ses_factory=boto_ses_factory,
)

如果你希望自定义 Config loading 的方式, 你可以自己手动实现. 下面是一段手动实现 Config 读取的示例代码.

[13]:
from aws_ops_alpha.api import (
    BaseEnvNameEnum,
)

class EnvNameEnum(BaseEnvNameEnum):
    devops = "devops"
    sbx = "sbx"
    tst = "tst"
    prd = "prd"


config = Config(
    data={
        "_shared": {
            "*.project_name": "simple_lambda",
            "*.s3uri_artifacts": "s3://bmt-app-devops-us-east-1-artifacts/projects/monorepo_aws/simple_lambda/",
            "*.s3uri_docs": "s3://bmt-app-devops-us-east-1-doc-host/projects/monorepo_aws/",
        },
        "devops": {
            "s3uri_data": "s3://bmt-app-devops-us-east-1-data/projects/simple_lambda/"
        },
        "sbx": {
            "username": "sbx.user",
            "s3uri_data": "s3://bmt-app-dev-us-east-1-data/projects/simple_lambda/"
        },
        "tst": {
            "username": "tst.user",
            "s3uri_data": "s3://bmt-app-test-us-east-1-data/projects/simple_lambda/"
        },
        "prd": {
            "username": "prd.user",
            "s3uri_data": "s3://bmt-app-prod-us-east-1-data/projects/simple_lambda/"
        }
    },
    secret_data={
        "_shared": {},
        "devops": {},
        "sbx": {
            "password": "sbx.password"
        },
        "tst": {
            "password": "tst.password"
        },
        "prd": {
            "password": "prd.password"
        }
    },
    Env=Env,
    EnvEnum=EnvNameEnum,
    version="1",
)
[16]:
config.sbx.username
[16]:
'sbx.user'
[17]:
config.sbx.password
[17]:
'sbx.password'
[19]:
config.sbx.s3uri_artifacts
[19]:
's3://bmt-app-devops-us-east-1-artifacts/projects/monorepo_aws/simple_lambda/'
[ ]: