dts-dance 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {dts_dance-0.2.0 → dts_dance-0.2.2}/PKG-INFO +2 -2
  2. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/bytecloud.py +20 -12
  3. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/dflow.py +61 -6
  4. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/dsyncer.py +7 -7
  5. dts_dance-0.2.0/dtsdance/spacex.py → dts_dance-0.2.2/dtsdance/spacex_bytedts.py +8 -3
  6. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/tcc_inner.py +1 -1
  7. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/tcc_open.py +8 -2
  8. {dts_dance-0.2.0 → dts_dance-0.2.2}/pyproject.toml +2 -2
  9. dts_dance-0.2.2/tests/config.py +51 -0
  10. dts_dance-0.2.2/tests/test_dflow.py +17 -0
  11. {dts_dance-0.2.0 → dts_dance-0.2.2}/tests/test_spacex.py +6 -9
  12. {dts_dance-0.2.0 → dts_dance-0.2.2}/tests/test_tcc.py +7 -5
  13. {dts_dance-0.2.0 → dts_dance-0.2.2}/uv.lock +8 -8
  14. dts_dance-0.2.0/tests/config.py +0 -30
  15. dts_dance-0.2.0/tests/test_dflow.py +0 -14
  16. {dts_dance-0.2.0 → dts_dance-0.2.2}/.gitignore +0 -0
  17. {dts_dance-0.2.0 → dts_dance-0.2.2}/.python-version +0 -0
  18. {dts_dance-0.2.0 → dts_dance-0.2.2}/CLAUDE.md +0 -0
  19. {dts_dance-0.2.0 → dts_dance-0.2.2}/DEV.md +0 -0
  20. {dts_dance-0.2.0 → dts_dance-0.2.2}/README.md +0 -0
  21. {dts_dance-0.2.0 → dts_dance-0.2.2}/config.yaml +0 -0
  22. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/__init__.py +0 -0
  23. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/feishu_base.py +0 -0
  24. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/feishu_table.py +0 -0
  25. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/metrics_fe.py +0 -0
  26. {dts_dance-0.2.0 → dts_dance-0.2.2}/dtsdance/s3.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dts-dance
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: dts dance lib
5
5
  Keywords: observation,tools
6
6
  Requires-Python: >=3.12
7
- Requires-Dist: boto3<2.0.0,>=1.42.27
7
+ Requires-Dist: boto3<2.0.0,>=1.42.29
8
8
  Requires-Dist: loguru<0.8.0,>=0.7.3
9
9
  Requires-Dist: pyyaml<7.0.0,>=6.0.3
10
10
  Requires-Dist: requests<3.0.0,>=2.32.5
@@ -22,13 +22,14 @@ class ByteCloudClient:
22
22
  # 每小时刷新一次,单位为秒
23
23
  _REFRESH_INTERVAL = 1 * 60 * 60
24
24
 
25
- def __init__(self, sites: dict[str, SiteConfig]):
25
+ def __init__(self, enable_jwt_cache: bool, sites: dict[str, SiteConfig] | None = None) -> None:
26
26
  """
27
27
  初始化 ByteCloud Client
28
28
  从配置文件加载所有环境的信息,并为每个环境初始化 JWT 令牌
29
29
  sites 中保存内容 list[(name, endpoint, svc_account, svc_secret)]
30
30
  """
31
- self.sites = sites
31
+ self.enable_jwt_cache = enable_jwt_cache
32
+ self.sites = sites if sites is not None else {}
32
33
 
33
34
  # 初始化线程锁,用于保护 jwt_tokens 的并发访问
34
35
  self.token_lock = threading.Lock()
@@ -36,11 +37,14 @@ class ByteCloudClient:
36
37
  # 初始化 JWT 令牌缓存,按环境名称索引
37
38
  self.jwt_tokens: Dict[str, str] = {}
38
39
 
39
- # 更新所有环境的 JWT 令牌
40
- self._refresh_tokens()
40
+ if enable_jwt_cache:
41
+ logger.info("启用 JWT 令牌缓存")
41
42
 
42
- # 启动 JWT 令牌刷新线程
43
- self._start_refresh_thread()
43
+ # 更新所有环境的 JWT 令牌
44
+ self._refresh_tokens()
45
+
46
+ # 启动 JWT 令牌刷新线程
47
+ self._start_refresh_thread()
44
48
 
45
49
  def _start_refresh_thread(self):
46
50
  """
@@ -131,11 +135,15 @@ class ByteCloudClient:
131
135
  """
132
136
  获取指定站点的 JWT 令牌
133
137
  """
134
- # 使用线程锁保护并发访问
135
- with self.token_lock:
136
- if site not in self.jwt_tokens:
137
- raise KeyError(f"站点 {site} JWT 令牌不存在")
138
- return self.jwt_tokens[site]
138
+ if self.enable_jwt_cache:
139
+ # 使用线程锁保护并发访问
140
+ with self.token_lock:
141
+ if site not in self.jwt_tokens:
142
+ raise KeyError(f"站点 {site} 的 JWT 令牌不存在")
143
+ return self.jwt_tokens[site]
144
+ else:
145
+ site_config = self.get_site_config(site)
146
+ return self._acquire_jwt_token(site_config.endpoint, site_config.svc_secret)
139
147
 
140
148
  def build_request_headers(self, site: str) -> dict[str, str]:
141
149
  """
@@ -150,7 +158,7 @@ class ByteCloudClient:
150
158
  jwt_token = self.get_jwt_token(site)
151
159
  return {"Content-Type": "application/json", "x-jwt-token": jwt_token}
152
160
 
153
- def get_site_info(self, site: str) -> SiteConfig:
161
+ def get_site_config(self, site: str) -> SiteConfig:
154
162
  """
155
163
  获取指定环境的信息
156
164
 
@@ -4,6 +4,14 @@ from .bytecloud import ByteCloudClient
4
4
  import requests
5
5
 
6
6
 
7
+ class TaskNotFound(Exception):
8
+ pass
9
+
10
+
11
+ class DFlowNotFound(Exception):
12
+ pass
13
+
14
+
7
15
  class DFlowClient:
8
16
 
9
17
  def __init__(self, bytecloud_client: ByteCloudClient) -> None:
@@ -44,7 +52,7 @@ class DFlowClient:
44
52
  logger.warning(error_msg)
45
53
  raise
46
54
 
47
- def get_dflow_info(self, site: str, task_id: str) -> dict[str, Any]:
55
+ def get_task_info(self, site: str, task_id: str) -> dict[str, Any]:
48
56
  """
49
57
  获取 DFlow 任务信息
50
58
 
@@ -56,7 +64,7 @@ class DFlowClient:
56
64
  dict[str, Any]: DFlow 任务信息,包含 create_time 等字段
57
65
  """
58
66
  # 构建 API URL
59
- site_info = self.bytecloud_client.get_site_info(site)
67
+ site_info = self.bytecloud_client.get_site_config(site)
60
68
  url = f"{site_info.endpoint}/api/v1/bytedts/api/bytedts/v3/DescribeTaskInfo"
61
69
 
62
70
  # 构建请求数据
@@ -64,7 +72,11 @@ class DFlowClient:
64
72
 
65
73
  response_data = self._make_request("POST", url, self.bytecloud_client.build_request_headers(site), json_data)
66
74
 
67
- logger.info(f"get_dflow_info {site} {task_id}, message: {response_data.get('message')}")
75
+ message = response_data.get("message")
76
+ # logger.debug(f"get_task_info {site} {task_id}, message: {message}")
77
+
78
+ if message == "task not exists":
79
+ raise TaskNotFound(f"获取 DFlow 任务信息失败,站点: {site}, 任务 ID: {task_id} 不存在")
68
80
 
69
81
  try:
70
82
  data = cast(dict, response_data.get("data", {}))
@@ -82,6 +94,49 @@ class DFlowClient:
82
94
  except (KeyError, AttributeError, Exception) as e:
83
95
  raise Exception(f"无法从响应中提取 DFlow 任务信息数据: {str(e)}")
84
96
 
97
+ def get_dflow_info(self, site: str, dflow_id: str) -> dict[str, Any]:
98
+ """
99
+ 获取 DFlow 进程信息
100
+
101
+ Args:
102
+ site: 站点名称
103
+ dflow_id: DFlow 进程 ID
104
+
105
+ Returns:
106
+ dict[str, Any]: DFlow 进程信息,包含 create_time 等字段
107
+ """
108
+ # 构建 API URL
109
+ site_info = self.bytecloud_client.get_site_config(site)
110
+ url = f"{site_info.endpoint}/api/v1/bytedts/api/bytedts/v3/DescribeDFlowDetail"
111
+
112
+ # 构建请求数据
113
+ json_data = {"dflow_id": int(dflow_id)}
114
+
115
+ response_data = self._make_request("POST", url, self.bytecloud_client.build_request_headers(site), json_data)
116
+
117
+ message = response_data.get("message", "")
118
+ # logger.debug(f"get_dflow_info {site} {dflow_id}, message: {message}")
119
+
120
+ if "dflow not found" in message:
121
+ raise DFlowNotFound(f"获取 DFlow 进程信息失败,站点: {site}, 进程 ID: {dflow_id} 不存在")
122
+
123
+ try:
124
+ data = cast(dict, response_data.get("data", {}))
125
+ dflow = cast(dict, data.get("dflow", {}))
126
+ # 提取核心信息
127
+ filtered_data = {
128
+ "dflow_id": dflow.get("id", ""),
129
+ "task_id": dflow.get("task_id", ""),
130
+ "app": dflow.get("app", ""),
131
+ "schedule_plan_name": dflow.get("schedule_plan_name", ""),
132
+ "running_state.healthy_status": dflow.get("running_state", {}).get("healthy_status", ""),
133
+ }
134
+
135
+ return filtered_data
136
+
137
+ except (KeyError, AttributeError, Exception) as e:
138
+ raise Exception(f"无法从响应中提取 DFlow 进程信息数据: {str(e)}")
139
+
85
140
  def generate_task_url(self, site: str, task_id: str) -> str:
86
141
  """
87
142
  获取 DFlow 任务详情页面的 URL
@@ -94,7 +149,7 @@ class DFlowClient:
94
149
  str: DFlow 任务详情页面的 URL
95
150
  """
96
151
  # 根据环境生成对应的 scope 参数
97
- site_info = self.bytecloud_client.get_site_info(site)
152
+ site_info = self.bytecloud_client.get_site_config(site)
98
153
  return f"{site_info.endpoint}/bytedts/datasync/detail/{task_id}?scope={site}"
99
154
 
100
155
  def init_resources(self, site: str, ctrl_env: str) -> bool:
@@ -109,7 +164,7 @@ class DFlowClient:
109
164
  bool: CTRL 环境资源初始化结果
110
165
  """
111
166
  # 构建 API URL
112
- site_info = self.bytecloud_client.get_site_info(site)
167
+ site_info = self.bytecloud_client.get_site_config(site)
113
168
  url = f"{site_info.endpoint}/api/v1/bytedts/api/bytedts/v3/InitSystemResource"
114
169
 
115
170
  # 构建请求数据
@@ -134,7 +189,7 @@ class DFlowClient:
134
189
  list[str]: CTRL 环境资源列表
135
190
  """
136
191
  # 构建 API URL
137
- site_info = self.bytecloud_client.get_site_info(site)
192
+ site_info = self.bytecloud_client.get_site_config(site)
138
193
  url = f"{site_info.endpoint}/api/v1/bytedts/api/bytedts/v3/DescribeResources"
139
194
 
140
195
  # 构建请求数据
@@ -89,7 +89,7 @@ class DSyncerClient:
89
89
  dict[str, str]: DSyncer 任务的 rocket_mq_connection 信息,只包含 cluster、topic 和 group 字段
90
90
  """
91
91
  # 构建 API URL
92
- site_info = self.bytecloud_client.get_site_info(site)
92
+ site_info = self.bytecloud_client.get_site_config(site)
93
93
  url = f"{site_info.endpoint}/api/v1/dsyncer/openapi/taskinfo/{task_id}/"
94
94
 
95
95
  # 准备请求头
@@ -102,7 +102,7 @@ class DSyncerClient:
102
102
  获取迁移后的 DFlow 任务信息
103
103
  """
104
104
  # 构建 API URL
105
- site_info = self.bytecloud_client.get_site_info(site)
105
+ site_info = self.bytecloud_client.get_site_config(site)
106
106
  url = f"{site_info.endpoint}/api/v1/dsyncer/openapi/taskinfo/{task_id}/migrate/"
107
107
 
108
108
  # 准备请求头
@@ -144,7 +144,7 @@ class DSyncerClient:
144
144
  Returns:
145
145
  str: DSyncer 任务详情页面的 URL
146
146
  """
147
- site_info = self.bytecloud_client.get_site_info(site)
147
+ site_info = self.bytecloud_client.get_site_config(site)
148
148
  return DSyncer_Task_Detail_URL.format(endpoint=site_info.endpoint, task_id=task_id)
149
149
 
150
150
  def generate_task_grafana_url(self, task_id: str, change_time: str) -> str:
@@ -208,7 +208,7 @@ class DSyncerClient:
208
208
  bool: 如果任务正在迁移中,返回 True;否则返回 False
209
209
  """
210
210
  # 构建 API URL
211
- site_info = self.bytecloud_client.get_site_info(site)
211
+ site_info = self.bytecloud_client.get_site_config(site)
212
212
  url = f"{site_info.endpoint}/api/v1/dsyncer/secret_api/task/migrate/check"
213
213
 
214
214
  # 准备请求头
@@ -230,7 +230,7 @@ class DSyncerClient:
230
230
  执行回滚
231
231
  """
232
232
  # 构建 API URL
233
- site_info = self.bytecloud_client.get_site_info(site)
233
+ site_info = self.bytecloud_client.get_site_config(site)
234
234
  url = f"{site_info.endpoint}/api/v1/dsyncer/secret_api/task/rollback_migrate2dsyncer/"
235
235
 
236
236
  # 准备请求头
@@ -249,7 +249,7 @@ class DSyncerClient:
249
249
  标记迁移成功
250
250
  """
251
251
  # 构建 API URL
252
- site_info = self.bytecloud_client.get_site_info(site)
252
+ site_info = self.bytecloud_client.get_site_config(site)
253
253
  url = f"{site_info.endpoint}/api/v1/dsyncer/secret_api/task/mark_migrate_success/"
254
254
 
255
255
  # 准备请求头
@@ -271,7 +271,7 @@ class DSyncerClient:
271
271
  Optional[str]: 错误信息,成功时返回None,失败时返回错误信息
272
272
  """
273
273
  # 构建 API URL
274
- site_info = self.bytecloud_client.get_site_info(site)
274
+ site_info = self.bytecloud_client.get_site_config(site)
275
275
  url = f"{site_info.endpoint}/api/v1/dsyncer/secret_api/task/migrate2dflow/single"
276
276
 
277
277
  # 准备请求头
@@ -26,7 +26,7 @@ class SpaceXClient:
26
26
  self.bytecloud_client = bytecloud_client
27
27
 
28
28
  def list_mgr(self, site: str) -> list[Any]:
29
- site_info = self.bytecloud_client.get_site_info(site)
29
+ site_info = self.bytecloud_client.get_site_config(site)
30
30
  url = f"{site_info.endpoint_bytedts_spacex}/bytedts/v1/queryServerMeta"
31
31
 
32
32
  try:
@@ -40,10 +40,11 @@ class SpaceXClient:
40
40
  logger.warning(f"do quest queryServerMeta exception: {e}")
41
41
  raise
42
42
 
43
- def registry_gateway(self, site: str, gateway_info: GatewayInfo) -> bool:
44
- site_info = self.bytecloud_client.get_site_info(site)
43
+ def register_gateway(self, site: str, gateway_info: GatewayInfo) -> bool:
44
+ site_info = self.bytecloud_client.get_site_config(site)
45
45
  url = f"{site_info.endpoint_bytedts_spacex}/bytedts/v1/registryGateway"
46
46
  data_raw = {
47
+ "region": gateway_info.mgr_name,
47
48
  "server_region": gateway_info.mgr_name,
48
49
  "cluster_region": gateway_info.ctrl_name,
49
50
  "cluster_name": gateway_info.ctrl_name,
@@ -55,6 +56,10 @@ class SpaceXClient:
55
56
  "frontend_password": gateway_info.auth_password,
56
57
  "gw_meta_db": gateway_info.gw_meta_db,
57
58
  "gateway_type": "psm",
59
+ "runtime_psm": "bytedts.dflow.rownott",
60
+ "tao_service_name": "inf.bytedts.agent",
61
+ "tao_service_node_id": 1071,
62
+ "unified_tao_service": 1,
58
63
  }
59
64
  try:
60
65
  response = requests.post(url, json=data_raw, headers=self.bytecloud_client.build_request_headers(site))
@@ -24,7 +24,7 @@ class TCCInnerClient:
24
24
  """
25
25
  List TCC configurations.
26
26
  """
27
- site_info = self.bytecloud_client.get_site_info(site)
27
+ site_info = self.bytecloud_client.get_site_config(site)
28
28
  url = f"{site_info.endpoint}/api/v3/tcc/bcc/config/list_v2"
29
29
 
30
30
  data_raw = {
@@ -16,8 +16,10 @@ class TCCConfigItem:
16
16
 
17
17
 
18
18
  class TCCError(Exception):
19
- """TCC API error."""
19
+ pass
20
+
20
21
 
22
+ class TCCItemNotFound(Exception):
21
23
  pass
22
24
 
23
25
 
@@ -229,7 +231,11 @@ class TCCClient:
229
231
  # Check for errors in response
230
232
  base_resp = result.get("base_resp", {})
231
233
  if base_resp.get("error_code", 0) != 0:
232
- raise TCCError(f"TCC API error: {base_resp.get('error_message', 'Unknown error')}")
234
+ error_message = base_resp.get("error_message", "Unknown error")
235
+ if "reason:RESOURCE_NOT_FOUND" in error_message:
236
+ raise TCCItemNotFound(f"TCC Item not found error: {error_message}")
237
+
238
+ raise TCCError(f"TCC API error: {error_message}")
233
239
 
234
240
  return result.get("data", {})
235
241
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dts-dance"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "dts dance lib"
9
9
  readme = "README.md"
10
10
  keywords = ["tools", "observation"]
@@ -12,7 +12,7 @@ requires-python = ">=3.12"
12
12
  dependencies = [
13
13
  "requests>=2.32.5,<3.0.0",
14
14
  "loguru>=0.7.3,<0.8.0",
15
- "boto3>=1.42.27,<2.0.0",
15
+ "boto3>=1.42.29,<2.0.0",
16
16
  "pyyaml>=6.0.3,<7.0.0",
17
17
  ]
18
18
 
@@ -0,0 +1,51 @@
1
+ import os
2
+ import yaml
3
+ from dtsdance.bytecloud import SiteConfig
4
+
5
+
6
+ class ConfigLoader:
7
+
8
+ _instance: "ConfigLoader | None" = None
9
+
10
+ def __init__(self):
11
+ self._site_configs: dict[str, SiteConfig] = {}
12
+
13
+ @classmethod
14
+ def get_instance(cls) -> "ConfigLoader":
15
+ """获取单例实例"""
16
+ if cls._instance is None:
17
+ cls._instance = cls()
18
+
19
+ return cls._instance
20
+
21
+ def load_from_file(self, sites: list[str] | None = None) -> None:
22
+ """从配置文件加载配置"""
23
+ config_path = os.environ.get("CONFIG_PATH", "config.yaml")
24
+
25
+ try:
26
+ with open(config_path, "r", encoding="utf-8") as f:
27
+ configs = yaml.safe_load(f)
28
+ except Exception as e:
29
+ raise ValueError(f"加载配置失败: {e}")
30
+
31
+ self._site_configs.update(
32
+ {
33
+ k: SiteConfig(k, v["endpoint"], v["svc_account"], v["svc_secret"], v.get("endpoint_bytedts_spacex", None))
34
+ for k, v in configs["sites"].items()
35
+ if sites is None or k in sites
36
+ }
37
+ )
38
+
39
+ def get(self, site: str) -> SiteConfig:
40
+ """获取指定站点的配置"""
41
+ if not self._site_configs:
42
+ raise RuntimeError("配置未加载,请先调用 load_from_file()")
43
+
44
+ if site not in self._site_configs:
45
+ raise KeyError(f"站点 {site} 不存在")
46
+
47
+ return self._site_configs[site]
48
+
49
+ def get_site_configs(self) -> dict[str, SiteConfig]:
50
+ """获取所有配置"""
51
+ return self._site_configs
@@ -0,0 +1,17 @@
1
+ from dtsdance.dflow import DFlowClient
2
+ from dtsdance.bytecloud import ByteCloudClient
3
+
4
+ bytecloud_client = ByteCloudClient(False)
5
+ dflow_client = DFlowClient(bytecloud_client)
6
+
7
+
8
+ # pytest tests/test_dflow.py::test_get_task_info -s
9
+ def test_get_task_info():
10
+ info = dflow_client.get_task_info("cn", "106037095986690")
11
+ print(f"DFlow Info: {info}")
12
+
13
+
14
+ # pytest tests/test_dflow.py::test_get_dflow_info -s
15
+ def test_get_dflow_info():
16
+ info = dflow_client.get_dflow_info("cn", "106029334786818")
17
+ print(f"DFlow Info: {info}")
@@ -1,22 +1,19 @@
1
1
  import json
2
2
  from dtsdance.bytecloud import ByteCloudClient
3
- from dtsdance.spacex import GatewayInfo, SpaceXClient
4
- from config import load_site_configs
3
+ from dtsdance.spacex_bytedts import GatewayInfo, SpaceXClient
5
4
 
6
- site = "boe"
7
- site_configs = load_site_configs([site])
8
- bytecloud_client = ByteCloudClient(site_configs)
5
+ bytecloud_client = ByteCloudClient(False)
9
6
  spacex = SpaceXClient(bytecloud_client)
10
7
 
11
8
 
12
9
  # pytest tests/test_spacex.py::test_list_mgr -s
13
10
  def test_list_mgr():
14
- mgr_list = spacex.list_mgr(site)
11
+ mgr_list = spacex.list_mgr("boe")
15
12
  print(f"mgr_list: {json.dumps(mgr_list, indent=2, ensure_ascii=False)}")
16
13
 
17
14
 
18
- # pytest tests/test_spacex.py::test_registry_gateway -s
19
- def test_registry_gateway():
15
+ # pytest tests/test_spacex.py::test_register_gateway -s
16
+ def test_register_gateway():
20
17
  gateway_info = GatewayInfo(
21
18
  mgr_name="boe",
22
19
  ctrl_name="boe_halo_test",
@@ -26,5 +23,5 @@ def test_registry_gateway():
26
23
  root_secret_key="97oscH5k",
27
24
  gw_meta_db="bytedts_sre_halo",
28
25
  )
29
- result = spacex.registry_gateway(site, gateway_info)
26
+ result = spacex.register_gateway("boe", gateway_info)
30
27
  print(f"result: {result}")
@@ -1,11 +1,11 @@
1
- from config import load_site_configs
2
1
  from dtsdance.bytecloud import ByteCloudClient
3
2
  from dtsdance.tcc_open import TCCClient
4
3
  from dtsdance.tcc_inner import TCCInnerClient
4
+ from config import ConfigLoader
5
5
 
6
- site_configs = load_site_configs(["boe", "us-ttp"])
7
- bytecloud_client = ByteCloudClient(site_configs)
8
- client_inner = TCCInnerClient(bytecloud_client)
6
+ loader = ConfigLoader.get_instance()
7
+ loader.load_from_file(["boe"])
8
+ site_configs = loader.get_site_configs()
9
9
 
10
10
 
11
11
  # pytest tests/test_tcc.py::test_get_config -s
@@ -18,5 +18,7 @@ def test_get_config():
18
18
 
19
19
  # pytest tests/test_tcc.py::test_list_configs -s
20
20
  def test_list_configs():
21
- configs = client_inner.list_configs(site="us-ttp", ns_name="bytedts.mgr.api", region="US-TTP", dir="/default", conf_name="ctrl_env")
21
+ bytecloud_client = ByteCloudClient(False, site_configs)
22
+ client_inner = TCCInnerClient(bytecloud_client)
23
+ configs = client_inner.list_configs(site="boe", ns_name="bytedts.mgr.api", region="China-BOE", dir="/default", conf_name="ctrl_env")
22
24
  print(f"configs: {configs}")
@@ -4,30 +4,30 @@ requires-python = ">=3.12"
4
4
 
5
5
  [[package]]
6
6
  name = "boto3"
7
- version = "1.42.27"
7
+ version = "1.42.29"
8
8
  source = { registry = "https://pypi.org/simple" }
9
9
  dependencies = [
10
10
  { name = "botocore" },
11
11
  { name = "jmespath" },
12
12
  { name = "s3transfer" },
13
13
  ]
14
- sdist = { url = "https://files.pythonhosted.org/packages/8d/99/65569052c911160702ad371b0b08b751bb1df29deeef0c5c117528074c29/boto3-1.42.27.tar.gz", hash = "sha256:a8a53abb98ff1a24d9a88d9d8c0285bf02d23189666130456e8951ede2f7db98", size = 112765, upload-time = "2026-01-13T20:35:11.971Z" }
14
+ sdist = { url = "https://files.pythonhosted.org/packages/5c/24/1dd85b64004103c2e60476d0fa8d78435f5fed9db1129cd2cd332784037a/boto3-1.42.29.tar.gz", hash = "sha256:247e54f24116ad6792cfc14b274288383af3ec3433b0547da8a14a8bd6e81950", size = 112810, upload-time = "2026-01-15T20:36:39.404Z" }
15
15
  wheels = [
16
- { url = "https://files.pythonhosted.org/packages/44/9e/9554a8c1d7610ec8ea55bec0dac87ad894c83cada2ea2c05fc45f14d0cde/boto3-1.42.27-py3-none-any.whl", hash = "sha256:39dfec51aff3f9356e8c7331195f324cb498ec75b2601a902fc62aa127b8fd00", size = 140577, upload-time = "2026-01-13T20:35:09.35Z" },
16
+ { url = "https://files.pythonhosted.org/packages/51/30/2c25d7be8418e7f137ffece6097c68199dbd6996da645ec9b5a5a9647123/boto3-1.42.29-py3-none-any.whl", hash = "sha256:6c9c4dece67bf72d82ba7dff48e33a56a87cdf9b16c8887f88ca7789a95d3317", size = 140574, upload-time = "2026-01-15T20:36:37.206Z" },
17
17
  ]
18
18
 
19
19
  [[package]]
20
20
  name = "botocore"
21
- version = "1.42.27"
21
+ version = "1.42.29"
22
22
  source = { registry = "https://pypi.org/simple" }
23
23
  dependencies = [
24
24
  { name = "jmespath" },
25
25
  { name = "python-dateutil" },
26
26
  { name = "urllib3" },
27
27
  ]
28
- sdist = { url = "https://files.pythonhosted.org/packages/65/90/55b003d38f947c90c0d7e306d377dcdfd9cd0dc1e184082b2d1a6adb0eec/botocore-1.42.27.tar.gz", hash = "sha256:c8e1e3ffb6c871622b1c8054f064d60cbc786aa5ca1f97f5f9fd5fa0a9d82d05", size = 14880030, upload-time = "2026-01-13T20:35:00.31Z" }
28
+ sdist = { url = "https://files.pythonhosted.org/packages/70/08/8a8e0255949845f764c5126f97b1bc09a6484077f124c2177b979ecfbbff/botocore-1.42.29.tar.gz", hash = "sha256:0fe869227a1dfe818f691a31b8c1693e39be8056a6dff5d6d4b3fc5b3a5e7d42", size = 14890916, upload-time = "2026-01-15T20:36:28.241Z" }
29
29
  wheels = [
30
- { url = "https://files.pythonhosted.org/packages/bf/32/8a4a0447432425cd2f772c757d988742685f46796cf5d68aeaf6bcb6bc37/botocore-1.42.27-py3-none-any.whl", hash = "sha256:d51fb3b8dd1a944c8d238d2827a0dd6e5528d6da49a3bd9eccad019c533e4c9c", size = 14555236, upload-time = "2026-01-13T20:34:55.918Z" },
30
+ { url = "https://files.pythonhosted.org/packages/94/76/cfa6a934ee5a8a87f626b38275193a046da894d2f9021e001587fc2e8c7d/botocore-1.42.29-py3-none-any.whl", hash = "sha256:b45f8dfc1de5106a9d040c5612f267582e68b2b2c5237477dff85c707c1c5d11", size = 14563947, upload-time = "2026-01-15T20:36:23.828Z" },
31
31
  ]
32
32
 
33
33
  [[package]]
@@ -107,7 +107,7 @@ wheels = [
107
107
 
108
108
  [[package]]
109
109
  name = "dts-dance"
110
- version = "0.2.0"
110
+ version = "0.2.2"
111
111
  source = { editable = "." }
112
112
  dependencies = [
113
113
  { name = "boto3" },
@@ -118,7 +118,7 @@ dependencies = [
118
118
 
119
119
  [package.metadata]
120
120
  requires-dist = [
121
- { name = "boto3", specifier = ">=1.42.27,<2.0.0" },
121
+ { name = "boto3", specifier = ">=1.42.29,<2.0.0" },
122
122
  { name = "loguru", specifier = ">=0.7.3,<0.8.0" },
123
123
  { name = "pyyaml", specifier = ">=6.0.3,<7.0.0" },
124
124
  { name = "requests", specifier = ">=2.32.5,<3.0.0" },
@@ -1,30 +0,0 @@
1
- import os
2
- from typing import Any
3
- import yaml
4
- from dtsdance.bytecloud import SiteConfig
5
-
6
-
7
- def load_site_configs(sites: list[str] | None = None) -> dict[str, SiteConfig]:
8
- """从配置文件加载配置
9
-
10
- Returns:
11
- dict[str, Any]: 应用配置字典
12
-
13
- Raises:
14
- ValueError: 配置文件加载错误
15
- """
16
- config_path = os.environ.get("CONFIG_PATH", "config.yaml")
17
-
18
- configs: dict[str, Any] = {}
19
- try:
20
- with open(config_path, "r", encoding="utf-8") as f:
21
- configs = yaml.safe_load(f)
22
-
23
- except Exception as e:
24
- raise ValueError(f"加载配置失败: {e}")
25
-
26
- return {
27
- k: SiteConfig(k, v["endpoint"], v["svc_account"], v["svc_secret"], v.get("endpoint_bytedts_spacex", None))
28
- for k, v in configs["sites"].items()
29
- if k in sites
30
- }
@@ -1,14 +0,0 @@
1
- from dtsdance.dflow import DFlowClient
2
- from dtsdance.bytecloud import ByteCloudClient
3
-
4
- from config import load_site_configs
5
-
6
- site_configs = load_site_configs(["boe"])
7
- bytecloud_client = ByteCloudClient(site_configs)
8
- dflow_client = DFlowClient(bytecloud_client)
9
-
10
-
11
- # pytest tests/test_dflow.py::test_get_dflow_info -s
12
- def test_get_dflow_info():
13
- info = dflow_client.get_dflow_info("boe", "1324653150464")
14
- print(f"DFlow Info: {info}")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes