Skip to content

Commit 6047041

Browse files
huansharehuansharelaipz8200
authored andcommitted
feat:add apollo configuration to load env file (#11210)
Signed-off-by: -LAN- <[email protected]> Co-authored-by: huanshare <[email protected]> Co-authored-by: -LAN- <[email protected]>
1 parent 062a575 commit 6047041

17 files changed

+578
-24
lines changed

api/configs/app_config.py

+66-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,51 @@
1-
from pydantic_settings import SettingsConfigDict
1+
import logging
2+
from typing import Any
23

3-
from configs.deploy import DeploymentConfig
4-
from configs.enterprise import EnterpriseFeatureConfig
5-
from configs.extra import ExtraServiceConfig
6-
from configs.feature import FeatureConfig
7-
from configs.middleware import MiddlewareConfig
8-
from configs.packaging import PackagingInfo
4+
from pydantic.fields import FieldInfo
5+
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict
6+
7+
from .deploy import DeploymentConfig
8+
from .enterprise import EnterpriseFeatureConfig
9+
from .extra import ExtraServiceConfig
10+
from .feature import FeatureConfig
11+
from .middleware import MiddlewareConfig
12+
from .packaging import PackagingInfo
13+
from .remote_settings_sources import RemoteSettingsSource, RemoteSettingsSourceConfig, RemoteSettingsSourceName
14+
from .remote_settings_sources.apollo import ApolloSettingsSource
15+
16+
logger = logging.getLogger(__name__)
17+
18+
19+
class RemoteSettingsSourceFactory(PydanticBaseSettingsSource):
20+
def __init__(self, settings_cls: type[BaseSettings]):
21+
super().__init__(settings_cls)
22+
23+
def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
24+
raise NotImplementedError
25+
26+
def __call__(self) -> dict[str, Any]:
27+
current_state = self.current_state
28+
remote_source_name = current_state.get("REMOTE_SETTINGS_SOURCE_NAME")
29+
if not remote_source_name:
30+
return {}
31+
32+
remote_source: RemoteSettingsSource | None = None
33+
match remote_source_name:
34+
case RemoteSettingsSourceName.APOLLO:
35+
remote_source = ApolloSettingsSource(current_state)
36+
case _:
37+
logger.warning(f"Unsupported remote source: {remote_source_name}")
38+
return {}
39+
40+
d: dict[str, Any] = {}
41+
42+
for field_name, field in self.settings_cls.model_fields.items():
43+
field_value, field_key, value_is_complex = remote_source.get_field_value(field, field_name)
44+
field_value = remote_source.prepare_field_value(field_name, field, field_value, value_is_complex)
45+
if field_value is not None:
46+
d[field_key] = field_value
47+
48+
return d
949

1050

1151
class DifyConfig(
@@ -19,6 +59,8 @@ class DifyConfig(
1959
MiddlewareConfig,
2060
# Extra service configs
2161
ExtraServiceConfig,
62+
# Remote source configs
63+
RemoteSettingsSourceConfig,
2264
# Enterprise feature configs
2365
# **Before using, please contact [email protected] by email to inquire about licensing matters.**
2466
EnterpriseFeatureConfig,
@@ -35,3 +77,20 @@ class DifyConfig(
3577
# please consider to arrange it in the proper config group of existed or added
3678
# for better readability and maintainability.
3779
# Thanks for your concentration and consideration.
80+
81+
@classmethod
82+
def settings_customise_sources(
83+
cls,
84+
settings_cls: type[BaseSettings],
85+
init_settings: PydanticBaseSettingsSource,
86+
env_settings: PydanticBaseSettingsSource,
87+
dotenv_settings: PydanticBaseSettingsSource,
88+
file_secret_settings: PydanticBaseSettingsSource,
89+
) -> tuple[PydanticBaseSettingsSource, ...]:
90+
return (
91+
init_settings,
92+
env_settings,
93+
RemoteSettingsSourceFactory(settings_cls),
94+
dotenv_settings,
95+
file_secret_settings,
96+
)

api/configs/middleware/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class KeywordStoreConfig(BaseSettings):
7373
)
7474

7575

76-
class DatabaseConfig:
76+
class DatabaseConfig(BaseSettings):
7777
DB_HOST: str = Field(
7878
description="Hostname or IP address of the database server.",
7979
default="localhost",

api/configs/middleware/storage/baidu_obs_storage_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
45

56

6-
class BaiduOBSStorageConfig(BaseModel):
7+
class BaiduOBSStorageConfig(BaseSettings):
78
"""
89
Configuration settings for Baidu Object Storage Service (OBS)
910
"""

api/configs/middleware/storage/huawei_obs_storage_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
45

56

6-
class HuaweiCloudOBSStorageConfig(BaseModel):
7+
class HuaweiCloudOBSStorageConfig(BaseSettings):
78
"""
89
Configuration settings for Huawei Cloud Object Storage Service (OBS)
910
"""

api/configs/middleware/storage/supabase_storage_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
45

56

6-
class SupabaseStorageConfig(BaseModel):
7+
class SupabaseStorageConfig(BaseSettings):
78
"""
89
Configuration settings for Supabase Object Storage Service
910
"""

api/configs/middleware/storage/volcengine_tos_storage_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
45

56

6-
class VolcengineTOSStorageConfig(BaseModel):
7+
class VolcengineTOSStorageConfig(BaseSettings):
78
"""
89
Configuration settings for Volcengine Tinder Object Storage (TOS)
910
"""

api/configs/middleware/vdb/analyticdb_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field, PositiveInt
3+
from pydantic import Field, PositiveInt
4+
from pydantic_settings import BaseSettings
45

56

6-
class AnalyticdbConfig(BaseModel):
7+
class AnalyticdbConfig(BaseSettings):
78
"""
89
Configuration for connecting to Alibaba Cloud AnalyticDB for PostgreSQL.
910
Refer to the following documentation for details on obtaining credentials:

api/configs/middleware/vdb/couchbase_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
45

56

6-
class CouchbaseConfig(BaseModel):
7+
class CouchbaseConfig(BaseSettings):
78
"""
89
Couchbase configs
910
"""

api/configs/middleware/vdb/myscale_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from pydantic import BaseModel, Field, PositiveInt
1+
from pydantic import Field, PositiveInt
2+
from pydantic_settings import BaseSettings
23

34

4-
class MyScaleConfig(BaseModel):
5+
class MyScaleConfig(BaseSettings):
56
"""
67
Configuration settings for MyScale vector database
78
"""

api/configs/middleware/vdb/vikingdb_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from pydantic import BaseModel, Field
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
45

56

6-
class VikingDBConfig(BaseModel):
7+
class VikingDBConfig(BaseSettings):
78
"""
89
Configuration for connecting to Volcengine VikingDB.
910
Refer to the following documentation for details on obtaining credentials:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from typing import Optional
2+
3+
from pydantic import Field
4+
5+
from .apollo import ApolloSettingsSourceInfo
6+
from .base import RemoteSettingsSource
7+
from .enums import RemoteSettingsSourceName
8+
9+
10+
class RemoteSettingsSourceConfig(ApolloSettingsSourceInfo):
11+
REMOTE_SETTINGS_SOURCE_NAME: Optional[RemoteSettingsSourceName] = Field(
12+
description="name of remote config source",
13+
default=None,
14+
)
15+
16+
17+
__all__ = ["RemoteSettingsSource", "RemoteSettingsSourceConfig", "RemoteSettingsSourceName"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from collections.abc import Mapping
2+
from typing import Any, Optional
3+
4+
from pydantic import Field
5+
from pydantic.fields import FieldInfo
6+
from pydantic_settings import BaseSettings
7+
8+
from configs.remote_settings_sources.base import RemoteSettingsSource
9+
10+
from .client import ApolloClient
11+
12+
13+
class ApolloSettingsSourceInfo(BaseSettings):
14+
"""
15+
Packaging build information
16+
"""
17+
18+
APOLLO_APP_ID: Optional[str] = Field(
19+
description="apollo app_id",
20+
default=None,
21+
)
22+
23+
APOLLO_CLUSTER: Optional[str] = Field(
24+
description="apollo cluster",
25+
default=None,
26+
)
27+
28+
APOLLO_CONFIG_URL: Optional[str] = Field(
29+
description="apollo config url",
30+
default=None,
31+
)
32+
33+
APOLLO_NAMESPACE: Optional[str] = Field(
34+
description="apollo namespace",
35+
default=None,
36+
)
37+
38+
39+
class ApolloSettingsSource(RemoteSettingsSource):
40+
def __init__(self, configs: Mapping[str, Any]):
41+
self.client = ApolloClient(
42+
app_id=configs["APOLLO_APP_ID"],
43+
cluster=configs["APOLLO_CLUSTER"],
44+
config_url=configs["APOLLO_CONFIG_URL"],
45+
start_hot_update=False,
46+
_notification_map={configs["APOLLO_NAMESPACE"]: -1},
47+
)
48+
self.namespace = configs["APOLLO_NAMESPACE"]
49+
self.remote_configs = self.client.get_all_dicts(self.namespace)
50+
51+
def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
52+
if not isinstance(self.remote_configs, dict):
53+
raise ValueError(f"remote configs is not dict, but {type(self.remote_configs)}")
54+
field_value = self.remote_configs.get(field_name)
55+
return field_value, field_name, False

0 commit comments

Comments
 (0)