dataops-sdk 0.3.0__py3-none-any.whl
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.
Potentially problematic release.
This version of dataops-sdk might be problematic. Click here for more details.
- dataops_sdk/__init__.py +84 -0
- dataops_sdk/constants.py +6 -0
- dataops_sdk/exceptions.py +31 -0
- dataops_sdk/runner/__init__.py +46 -0
- dataops_sdk/runner/datasource_factory.py +83 -0
- dataops_sdk/runner/schemas/nacos/__init__.py +5 -0
- dataops_sdk/runner/schemas/nacos/config.py +40 -0
- dataops_sdk/runner/schemas/nacos/constants.py +235 -0
- dataops_sdk/runner/schemas/nacos/instance.py +103 -0
- dataops_sdk/runner/schemas/nacos/nacos_exception.py +44 -0
- dataops_sdk/runner/schemas/nacos/naming_param.py +62 -0
- dataops_sdk/runner/schemas/nacos/naming_request.py +84 -0
- dataops_sdk/runner/schemas/nacos/naming_response.py +50 -0
- dataops_sdk/runner/schemas/nacos/preserved_metadata_key.py +10 -0
- dataops_sdk/runner/schemas/nacos/service.py +119 -0
- dataops_sdk/runner/utils/__init__.py +42 -0
- dataops_sdk/runner/utils/common.py +209 -0
- dataops_sdk/runner/utils/dbConn_base.py +256 -0
- dataops_sdk/runner/utils/dbConn_sync.py +485 -0
- dataops_sdk/runner/utils/duckdb_manager.py +203 -0
- dataops_sdk/runner/utils/file_transfer_base.py +307 -0
- dataops_sdk/runner/utils/ftp_file_transfer.py +242 -0
- dataops_sdk/runner/utils/log.py +50 -0
- dataops_sdk/runner/utils/nacos.py +96 -0
- dataops_sdk/runner/utils/neo4j_sync.py +236 -0
- dataops_sdk/runner/utils/queue_base.py +224 -0
- dataops_sdk/runner/utils/queue_kafka.py +150 -0
- dataops_sdk/runner/utils/sftp_file_transfer.py +243 -0
- dataops_sdk/schemas/__init__.py +32 -0
- dataops_sdk/schemas/alarm.py +38 -0
- dataops_sdk/schemas/api.py +37 -0
- dataops_sdk/schemas/data_table.py +437 -0
- dataops_sdk/schemas/datasource.py +26 -0
- dataops_sdk/schemas/dict_.py +13 -0
- dataops_sdk/schemas/enums.py +120 -0
- dataops_sdk/schemas/group.py +40 -0
- dataops_sdk/schemas/hazard.py +151 -0
- dataops_sdk/schemas/meta.py +175 -0
- dataops_sdk/schemas/query.py +175 -0
- dataops_sdk/schemas/report.py +22 -0
- dataops_sdk/schemas/skill.py +70 -0
- dataops_sdk/schemas/table.py +65 -0
- dataops_sdk/schemas/user.py +52 -0
- dataops_sdk/schemas/widget.py +651 -0
- dataops_sdk/schemas/workflow.py +63 -0
- dataops_sdk/services/__init__.py +110 -0
- dataops_sdk/services/alarm.py +324 -0
- dataops_sdk/services/api.py +28 -0
- dataops_sdk/services/auth.py +120 -0
- dataops_sdk/services/data_table.py +485 -0
- dataops_sdk/services/dataset.py +127 -0
- dataops_sdk/services/datasource.py +57 -0
- dataops_sdk/services/dict_.py +69 -0
- dataops_sdk/services/hazard.py +260 -0
- dataops_sdk/services/meta.py +523 -0
- dataops_sdk/services/metrics.py +42 -0
- dataops_sdk/services/ref.py +66 -0
- dataops_sdk/services/report.py +36 -0
- dataops_sdk/services/skill.py +276 -0
- dataops_sdk/services/table.py +340 -0
- dataops_sdk/services/widget.py +143 -0
- dataops_sdk/services/workflow.py +102 -0
- dataops_sdk/session.py +292 -0
- dataops_sdk/tiptap/__init__.py +30 -0
- dataops_sdk/tiptap/builder.py +75 -0
- dataops_sdk/tiptap/constants.py +133 -0
- dataops_sdk/tiptap/markdown_parser.py +294 -0
- dataops_sdk/tiptap/models.py +43 -0
- dataops_sdk/tiptap/parse_utils.py +889 -0
- dataops_sdk/tiptap/render_utils.py +846 -0
- dataops_sdk/tiptap/renderers.py +51 -0
- dataops_sdk/tiptap/tool.py +629 -0
- dataops_sdk/utils/__init__.py +15 -0
- dataops_sdk/utils/common.py +211 -0
- dataops_sdk/utils/utils.py +120 -0
- dataops_sdk-0.3.0.dist-info/METADATA +25 -0
- dataops_sdk-0.3.0.dist-info/RECORD +79 -0
- dataops_sdk-0.3.0.dist-info/WHEEL +5 -0
- dataops_sdk-0.3.0.dist-info/top_level.txt +1 -0
dataops_sdk/__init__.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from . import runner, schemas, utils
|
|
2
|
+
from .services import ( # noqa: F401
|
|
3
|
+
release_list_create,
|
|
4
|
+
release_list_get_by_code,
|
|
5
|
+
release_list_get_by_name,
|
|
6
|
+
release_list_list,
|
|
7
|
+
release_list_page,
|
|
8
|
+
release_list_total,
|
|
9
|
+
release_list_update,
|
|
10
|
+
release_ref_list,
|
|
11
|
+
release_ref_list_by_ref,
|
|
12
|
+
service_clear_hazard_history_records,
|
|
13
|
+
service_count_alarm_action,
|
|
14
|
+
service_count_alarm_rule_matches,
|
|
15
|
+
service_count_alarm_rules,
|
|
16
|
+
service_count_alarm_specs,
|
|
17
|
+
service_count_table_by_code,
|
|
18
|
+
service_count_table_by_name,
|
|
19
|
+
service_count_widget_by_code,
|
|
20
|
+
service_create_data_table,
|
|
21
|
+
service_create_data_table_record,
|
|
22
|
+
service_delete_data_table_record_by_id,
|
|
23
|
+
service_delete_data_table_record_by_id_list,
|
|
24
|
+
service_exec_sql_by_datasource,
|
|
25
|
+
service_find_alarm_table_data,
|
|
26
|
+
service_find_meta_by_codes,
|
|
27
|
+
service_get_alarm_rule_enums,
|
|
28
|
+
service_get_alarm_table_columns,
|
|
29
|
+
service_get_api_by_code,
|
|
30
|
+
service_get_api_by_name,
|
|
31
|
+
service_get_current_application,
|
|
32
|
+
service_get_data_table_by_code,
|
|
33
|
+
service_get_data_table_by_name,
|
|
34
|
+
service_get_data_table_data_by_code,
|
|
35
|
+
service_get_data_table_data_by_name,
|
|
36
|
+
service_get_data_table_record_by_id,
|
|
37
|
+
service_get_data_table_reference_list,
|
|
38
|
+
service_get_data_table_total,
|
|
39
|
+
service_get_dataset_data_by_code,
|
|
40
|
+
service_get_dataset_detail_by_code,
|
|
41
|
+
service_get_datasource_by_name,
|
|
42
|
+
service_get_datasource_config_by_application_id,
|
|
43
|
+
service_get_dict_detail_by_code,
|
|
44
|
+
service_get_dict_detail_by_name,
|
|
45
|
+
service_get_hazard_task_log_records,
|
|
46
|
+
service_get_hazard_task_logs,
|
|
47
|
+
service_get_main_datasource_config_by_application,
|
|
48
|
+
service_get_metrics,
|
|
49
|
+
service_get_rel_table_columns,
|
|
50
|
+
service_get_report,
|
|
51
|
+
service_get_table_data_by_code,
|
|
52
|
+
service_get_table_data_by_name,
|
|
53
|
+
service_get_table_detail_by_code,
|
|
54
|
+
service_get_table_detail_by_name,
|
|
55
|
+
service_get_widget_data_by_code,
|
|
56
|
+
service_get_widget_detail_by_code,
|
|
57
|
+
service_get_workflow_by_code,
|
|
58
|
+
service_get_workflow_by_name,
|
|
59
|
+
service_list_alarm_rule_matches,
|
|
60
|
+
service_list_alarm_rules,
|
|
61
|
+
service_list_alarm_specs,
|
|
62
|
+
service_list_applications,
|
|
63
|
+
service_list_datasets,
|
|
64
|
+
service_list_dicts,
|
|
65
|
+
service_list_hazard_history_records,
|
|
66
|
+
service_list_hazard_records,
|
|
67
|
+
service_list_metrics,
|
|
68
|
+
service_list_reports,
|
|
69
|
+
service_list_tables,
|
|
70
|
+
service_list_widgets,
|
|
71
|
+
service_list_workflows,
|
|
72
|
+
service_login,
|
|
73
|
+
service_logout,
|
|
74
|
+
service_ref_backward,
|
|
75
|
+
service_ref_forward,
|
|
76
|
+
service_set_application,
|
|
77
|
+
service_start_workflow,
|
|
78
|
+
service_start_workflow_async,
|
|
79
|
+
service_trigger_hazard_task,
|
|
80
|
+
service_update_data_table_record_by_id,
|
|
81
|
+
service_update_data_table_record_by_id_list,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
__version__ = "0.3.0"
|
dataops_sdk/constants.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class DataOpsError(Exception):
|
|
2
|
+
"""DataOps API 错误基类。"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, message: str, status_code: int | None = None):
|
|
5
|
+
self.message = message
|
|
6
|
+
self.status_code = status_code
|
|
7
|
+
super().__init__(message)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NotFoundError(DataOpsError):
|
|
11
|
+
"""资源未找到。"""
|
|
12
|
+
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AuthenticationError(DataOpsError):
|
|
17
|
+
"""认证失败异常。"""
|
|
18
|
+
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class FailedToCreateError(DataOpsError):
|
|
23
|
+
"""创建失败异常。"""
|
|
24
|
+
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FailedToUpdateError(DataOpsError):
|
|
29
|
+
"""更新失败异常。"""
|
|
30
|
+
|
|
31
|
+
pass
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Runner 包 - 独立的脚本执行工具集。
|
|
2
|
+
|
|
3
|
+
提供脚本执行所需的数据库连接、DuckDB 管理、Neo4j 连接等工具。
|
|
4
|
+
可作为独立模块被导入使用。
|
|
5
|
+
|
|
6
|
+
Modules:
|
|
7
|
+
schemas: Nacos 配置数据模型
|
|
8
|
+
utils: 通用工具(数据库连接、加密、日志等)
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
>>> from runner.utils import DatabaseConn, DuckDBManager
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .datasource_factory import get_datasource_instent
|
|
15
|
+
from .schemas.nacos import NacosSettings
|
|
16
|
+
from .utils import (
|
|
17
|
+
DatabaseConn,
|
|
18
|
+
FTPFileTransfer,
|
|
19
|
+
KafkaQueue,
|
|
20
|
+
Neo4jConn,
|
|
21
|
+
SFTPFileTransfer,
|
|
22
|
+
decrypt_body,
|
|
23
|
+
encrypt_body,
|
|
24
|
+
generate_uuid,
|
|
25
|
+
get_service_instance,
|
|
26
|
+
getLogger,
|
|
27
|
+
parse_args,
|
|
28
|
+
print_json,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"DatabaseConn",
|
|
33
|
+
"FTPFileTransfer",
|
|
34
|
+
"KafkaQueue",
|
|
35
|
+
"SFTPFileTransfer",
|
|
36
|
+
"Neo4jConn",
|
|
37
|
+
"decrypt_body",
|
|
38
|
+
"encrypt_body",
|
|
39
|
+
"getLogger",
|
|
40
|
+
"print_json",
|
|
41
|
+
"generate_uuid",
|
|
42
|
+
"parse_args",
|
|
43
|
+
"NacosSettings",
|
|
44
|
+
"get_service_instance",
|
|
45
|
+
"get_datasource_instent",
|
|
46
|
+
]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
数据源实例工厂模块。
|
|
3
|
+
|
|
4
|
+
根据数据源元数据动态创建对应的连接实例(数据库或消息队列)。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataops_sdk.services.datasource import service_get_datasource_by_name
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_datasource_instent(datasource: str, log_sql: bool | None = None):
|
|
11
|
+
"""
|
|
12
|
+
根据数据源名称获取对应的连接实例。
|
|
13
|
+
|
|
14
|
+
通过数据源名称从平台查询元数据,根据数据源的 category(数据库/消息队列)
|
|
15
|
+
和 type(具体类型)动态创建并返回相应的连接实例。
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
datasource: 数据源名称,用于从平台查询数据源元数据。
|
|
19
|
+
log_sql: 是否记录 SQL 执行日志,传递给数据库连接实例。
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
DatabaseConn: 通用数据库连接实例(MySQL、PostgreSQL 等)。
|
|
23
|
+
Neo4jConn: Neo4j 图数据库连接实例。
|
|
24
|
+
KafkaQueue: Kafka 消息队列连接实例。
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
NotImplementedError: 当数据源类型未被支持时抛出。
|
|
28
|
+
|
|
29
|
+
Note:
|
|
30
|
+
当前支持的 category:
|
|
31
|
+
- database: 关系型/图数据库(Neo4j、MySQL、PostgreSQL 等)
|
|
32
|
+
- queue: 消息队列(Kafka)
|
|
33
|
+
"""
|
|
34
|
+
# 从平台查询数据源元数据
|
|
35
|
+
meta = service_get_datasource_by_name(datasource)
|
|
36
|
+
|
|
37
|
+
# 根据数据源类别分发处理
|
|
38
|
+
if meta.data.category == "queue":
|
|
39
|
+
# 消息队列类型处理
|
|
40
|
+
if meta.data.type == "kafka":
|
|
41
|
+
# Kafka 连接需要 bootstrap_servers
|
|
42
|
+
assert meta.data.bootstrap_servers, "bootstrap_servers is required, but not provided"
|
|
43
|
+
from dataops_sdk.runner import KafkaQueue
|
|
44
|
+
|
|
45
|
+
return KafkaQueue(meta.data.bootstrap_servers)
|
|
46
|
+
else:
|
|
47
|
+
raise NotImplementedError(f"Queue type {meta.data.type} is not supported")
|
|
48
|
+
|
|
49
|
+
elif meta.data.category == "database":
|
|
50
|
+
# 数据库类型处理,验证必要的连接参数
|
|
51
|
+
assert meta.data.ip, "host is required, but not provided"
|
|
52
|
+
assert meta.data.port, "port is required, but not provided"
|
|
53
|
+
assert meta.data.username, "user is required, but not provided"
|
|
54
|
+
assert meta.data.password, "password is required, but not provided"
|
|
55
|
+
assert meta.data.database, "database is required, but not provided"
|
|
56
|
+
|
|
57
|
+
if meta.data.type == "neo4j":
|
|
58
|
+
# Neo4j 图数据库使用专用连接类
|
|
59
|
+
from dataops_sdk.runner import Neo4jConn
|
|
60
|
+
|
|
61
|
+
return Neo4jConn(
|
|
62
|
+
host=meta.data.ip,
|
|
63
|
+
port=meta.data.port,
|
|
64
|
+
user=meta.data.username,
|
|
65
|
+
password=meta.data.password,
|
|
66
|
+
db=meta.data.database,
|
|
67
|
+
log_sql=log_sql,
|
|
68
|
+
name=meta.title,
|
|
69
|
+
)
|
|
70
|
+
else:
|
|
71
|
+
# 通用数据库连接,支持 MySQL、PostgreSQL 等
|
|
72
|
+
from dataops_sdk.runner import DatabaseConn
|
|
73
|
+
|
|
74
|
+
return DatabaseConn(
|
|
75
|
+
host=meta.data.ip,
|
|
76
|
+
port=meta.data.port,
|
|
77
|
+
user=meta.data.username,
|
|
78
|
+
password=meta.data.password,
|
|
79
|
+
db=meta.data.database,
|
|
80
|
+
db_type=meta.data.type,
|
|
81
|
+
log_sql=log_sql,
|
|
82
|
+
name=meta.title,
|
|
83
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Nacos 配置模块。
|
|
2
|
+
|
|
3
|
+
定义 Nacos 相关的配置数据模型,与主应用中的 Settings 类似,
|
|
4
|
+
但用于 runner 子包独立运行时。
|
|
5
|
+
|
|
6
|
+
Classes:
|
|
7
|
+
NacosSettings: Nacos 配置类
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
>>> from runner.schemas.nacos import NacosSettings
|
|
11
|
+
>>> config = NacosSettings()
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Annotated
|
|
15
|
+
|
|
16
|
+
from pydantic import Field
|
|
17
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class NacosSettings(BaseSettings):
|
|
21
|
+
"""Nacos 配置类。
|
|
22
|
+
|
|
23
|
+
从 .env 文件和环境变量加载配置。配置项包括后端监听、
|
|
24
|
+
子系统连接和 Nacos 服务发现参数。
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
nacos_addrs: NACOS服务地址
|
|
28
|
+
nacos_user: NACOS用户名
|
|
29
|
+
nacos_password: NACOS密码
|
|
30
|
+
nacos_discovery_namespace: NACOS服务发现命名空间
|
|
31
|
+
nacos_group_name: NACOS服务发现组名
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
nacos_addrs: Annotated[str, Field(description="NACOS服务地址")]
|
|
35
|
+
nacos_user: Annotated[str, Field(description="NACOS用户名")]
|
|
36
|
+
nacos_password: Annotated[str, Field(description="NACOS密码")]
|
|
37
|
+
nacos_discovery_namespace: Annotated[str, Field(description="NACOS服务发现命名空间")]
|
|
38
|
+
nacos_group_name: Annotated[str, Field(description="NACOS服务发现组名")] = "DEFAULT_GROUP"
|
|
39
|
+
|
|
40
|
+
model_config = SettingsConfigDict(extra="ignore")
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
class Constants:
|
|
2
|
+
NAMING_MODULE = "naming"
|
|
3
|
+
|
|
4
|
+
CONFIG_MODULE = "config"
|
|
5
|
+
|
|
6
|
+
AI_MODULE = "ai"
|
|
7
|
+
|
|
8
|
+
LABEL_SOURCE = "source"
|
|
9
|
+
|
|
10
|
+
LABEL_SOURCE_SDK = "sdk"
|
|
11
|
+
|
|
12
|
+
LABEL_SOURCE_CLUSTER = "cluster"
|
|
13
|
+
|
|
14
|
+
LABEL_MODULE = "module"
|
|
15
|
+
|
|
16
|
+
CLIENT_VERSION = "Nacos-Python-Client:v3.2.0"
|
|
17
|
+
|
|
18
|
+
DATA_IN_BODY_VERSION = 204
|
|
19
|
+
|
|
20
|
+
DEFAULT_GROUP = "DEFAULT_GROUP"
|
|
21
|
+
|
|
22
|
+
WEB_CONTEXT = "/nacos"
|
|
23
|
+
|
|
24
|
+
APPNAME = "AppName"
|
|
25
|
+
|
|
26
|
+
UNKNOWN_APP = "UnknownApp"
|
|
27
|
+
|
|
28
|
+
DEFAULT_DOMAINNAME = "commonconfig.config-host.taobao.com"
|
|
29
|
+
|
|
30
|
+
DAILY_DOMAINNAME = "commonconfig.taobao.net"
|
|
31
|
+
|
|
32
|
+
NULL = ""
|
|
33
|
+
|
|
34
|
+
DATAID = "dataId"
|
|
35
|
+
|
|
36
|
+
GROUP = "group"
|
|
37
|
+
|
|
38
|
+
DEFAULT_HEARTBEAT_INTERVAL = 5
|
|
39
|
+
|
|
40
|
+
LAST_MODIFIED = "Last-Modified"
|
|
41
|
+
|
|
42
|
+
ACCEPT_ENCODING = "Accept-Encoding"
|
|
43
|
+
|
|
44
|
+
CONTENT_ENCODING = "Content-Encoding"
|
|
45
|
+
|
|
46
|
+
PROBE_MODIFY_REQUEST = "Listening-Configs"
|
|
47
|
+
|
|
48
|
+
PROBE_MODIFY_RESPONSE = "Probe-Modify-Response"
|
|
49
|
+
|
|
50
|
+
PROBE_MODIFY_RESPONSE_NEW = "Probe-Modify-Response-New"
|
|
51
|
+
|
|
52
|
+
USE_ZIP = "true"
|
|
53
|
+
|
|
54
|
+
CONTENT_MD5 = "Content-MD5"
|
|
55
|
+
|
|
56
|
+
CONFIG_VERSION = "Config-Version"
|
|
57
|
+
|
|
58
|
+
CONFIG_TYPE = "Config-Type"
|
|
59
|
+
|
|
60
|
+
ENCRYPTED_DATA_KEY = "Encrypted-Data-Key"
|
|
61
|
+
|
|
62
|
+
IF_MODIFIED_SINCE = "If-Modified-Since"
|
|
63
|
+
|
|
64
|
+
SPACING_INTERVAL = "client-spacing-interval"
|
|
65
|
+
|
|
66
|
+
BASE_PATH = "/v1/cs"
|
|
67
|
+
|
|
68
|
+
SERVICE_BASE_PATH = "/v1/ns"
|
|
69
|
+
|
|
70
|
+
CONFIG_CONTROLLER_PATH = BASE_PATH + "/configs"
|
|
71
|
+
|
|
72
|
+
TOKEN = "token"
|
|
73
|
+
|
|
74
|
+
ACCESS_TOKEN = "accessToken"
|
|
75
|
+
|
|
76
|
+
TOKEN_TTL = "tokenTtl"
|
|
77
|
+
|
|
78
|
+
GLOBAL_ADMIN = "globalAdmin"
|
|
79
|
+
|
|
80
|
+
USERNAME = "username"
|
|
81
|
+
|
|
82
|
+
TOKEN_REFRESH_WINDOW = "tokenRefreshWindow"
|
|
83
|
+
|
|
84
|
+
# second.
|
|
85
|
+
ASYNC_UPDATE_ADDRESS_INTERVAL = 300
|
|
86
|
+
|
|
87
|
+
# second.
|
|
88
|
+
POLLING_INTERVAL_TIME = 15
|
|
89
|
+
|
|
90
|
+
# millisecond.
|
|
91
|
+
ONCE_TIMEOUT = 2000
|
|
92
|
+
|
|
93
|
+
# millisecond.
|
|
94
|
+
SO_TIMEOUT = 60000
|
|
95
|
+
|
|
96
|
+
# millisecond.
|
|
97
|
+
CONFIG_LONG_POLL_TIMEOUT = 30000
|
|
98
|
+
|
|
99
|
+
# millisecond.
|
|
100
|
+
MIN_CONFIG_LONG_POLL_TIMEOUT = 10000
|
|
101
|
+
|
|
102
|
+
# millisecond.
|
|
103
|
+
CONFIG_RETRY_TIME = 2000
|
|
104
|
+
|
|
105
|
+
# Maximum number of retries.
|
|
106
|
+
MAX_RETRY = 3
|
|
107
|
+
|
|
108
|
+
# millisecond.
|
|
109
|
+
RECV_WAIT_TIMEOUT = ONCE_TIMEOUT * 5
|
|
110
|
+
|
|
111
|
+
ENCODE = "UTF-8"
|
|
112
|
+
|
|
113
|
+
MAP_FILE = "map-file.js"
|
|
114
|
+
|
|
115
|
+
FLOW_CONTROL_THRESHOLD = 20
|
|
116
|
+
|
|
117
|
+
FLOW_CONTROL_SLOT = 10
|
|
118
|
+
|
|
119
|
+
FLOW_CONTROL_INTERVAL = 1000
|
|
120
|
+
|
|
121
|
+
DEFAULT_PROTECT_THRESHOLD = 0.0
|
|
122
|
+
|
|
123
|
+
LINE_SEPARATOR = chr(1)
|
|
124
|
+
|
|
125
|
+
WORD_SEPARATOR = chr(2)
|
|
126
|
+
|
|
127
|
+
LONGPOLLING_LINE_SEPARATOR = "\r\n"
|
|
128
|
+
|
|
129
|
+
CLIENT_APPNAME_HEADER = "Client-AppName"
|
|
130
|
+
|
|
131
|
+
APP_NAME_HEADER = "AppName"
|
|
132
|
+
|
|
133
|
+
CLIENT_REQUEST_TS_HEADER = "Client-RequestTS"
|
|
134
|
+
|
|
135
|
+
CLIENT_REQUEST_TOKEN_HEADER = "Client-RequestToken"
|
|
136
|
+
|
|
137
|
+
ATOMIC_MAX_SIZE = 1000
|
|
138
|
+
|
|
139
|
+
NAMING_INSTANCE_ID_SPLITTER = "#"
|
|
140
|
+
|
|
141
|
+
NAMING_INSTANCE_ID_SEG_COUNT = 4
|
|
142
|
+
|
|
143
|
+
NAMING_HTTP_HEADER_SPLITTER = "\\|"
|
|
144
|
+
|
|
145
|
+
DEFAULT_CLUSTER_NAME = "DEFAULT"
|
|
146
|
+
|
|
147
|
+
DEFAULT_HEART_BEAT_TIMEOUT = 15000
|
|
148
|
+
|
|
149
|
+
DEFAULT_IP_DELETE_TIMEOUT = 30000
|
|
150
|
+
|
|
151
|
+
DEFAULT_HEART_BEAT_INTERVAL = 5000
|
|
152
|
+
|
|
153
|
+
DEFAULT_NAMESPACE_ID = ""
|
|
154
|
+
|
|
155
|
+
NAMING_DEFAULT_NAMESPACE_ID = "public"
|
|
156
|
+
|
|
157
|
+
DEFAULT_USE_CLOUD_NAMESPACE_PARSING = True
|
|
158
|
+
|
|
159
|
+
WRITE_REDIRECT_CODE = 307
|
|
160
|
+
|
|
161
|
+
RESPONSE_SUCCESS_CODE = 200
|
|
162
|
+
|
|
163
|
+
REQUEST_DOMAIN_RETRY_TIME = 3
|
|
164
|
+
|
|
165
|
+
SERVICE_INFO_SPLITER = "@@"
|
|
166
|
+
|
|
167
|
+
CONFIG_INFO_SPLITER = "@@"
|
|
168
|
+
|
|
169
|
+
SERVICE_INFO_SPLIT_COUNT = 2
|
|
170
|
+
|
|
171
|
+
NULL_STRING = "null"
|
|
172
|
+
|
|
173
|
+
NUMBER_PATTERN = "^\\d+$"
|
|
174
|
+
|
|
175
|
+
ANY_PATTERN = ".*"
|
|
176
|
+
|
|
177
|
+
DEFAULT_INSTANCE_ID_GENERATOR = "simple"
|
|
178
|
+
|
|
179
|
+
SNOWFLAKE_INSTANCE_ID_GENERATOR = "snowflake"
|
|
180
|
+
|
|
181
|
+
HTTP_PREFIX = "http"
|
|
182
|
+
|
|
183
|
+
ALL_PATTERN = "*"
|
|
184
|
+
|
|
185
|
+
COLON = ":"
|
|
186
|
+
|
|
187
|
+
LINE_BREAK = "\n"
|
|
188
|
+
|
|
189
|
+
POUND = "#"
|
|
190
|
+
|
|
191
|
+
VIPSERVER_TAG = "Vipserver-Tag"
|
|
192
|
+
|
|
193
|
+
AMORY_TAG = "Amory-Tag"
|
|
194
|
+
|
|
195
|
+
LOCATION_TAG = "Location-Tag"
|
|
196
|
+
|
|
197
|
+
CHARSET_KEY = "charset"
|
|
198
|
+
|
|
199
|
+
EX_CONFIG_INFO = "exConfigInfo"
|
|
200
|
+
|
|
201
|
+
GROUP_NAME_KEY = "groupName"
|
|
202
|
+
|
|
203
|
+
SERVICE_NAME_KEY = "serviceName"
|
|
204
|
+
|
|
205
|
+
CIPHER_PRE_FIX = "cipher-"
|
|
206
|
+
|
|
207
|
+
DEFAULT_PORT = 8848
|
|
208
|
+
|
|
209
|
+
GRPC_MAX_RECEIVE_MESSAGE_LENGTH = 100 * 1024 * 1024
|
|
210
|
+
|
|
211
|
+
GRPC_KEEPALIVE_TIME_MILLS = 60 * 1000
|
|
212
|
+
|
|
213
|
+
GRPC_INITIAL_WINDOW_SIZE = 10 * 1024 * 1024
|
|
214
|
+
|
|
215
|
+
GRPC_INITIAL_CONN_WINDOW_SIZE = 10 * 1024 * 1024
|
|
216
|
+
|
|
217
|
+
KEEP_ALIVE_TIME_MILLS = 5000
|
|
218
|
+
|
|
219
|
+
INTERNAL_TIME_MILLS = 3000
|
|
220
|
+
|
|
221
|
+
DEFAULT_GRPC_TIMEOUT_MILLS = 3000
|
|
222
|
+
|
|
223
|
+
GRPC_CAPABILITY_NEGOTIATION_TIMEOUT = 5000
|
|
224
|
+
|
|
225
|
+
GRPC_PORT_OFFSET = 1000 # gRPC port = HTTP port + offset
|
|
226
|
+
|
|
227
|
+
DEFAULT_TIMEOUT_MILLS = 10000
|
|
228
|
+
|
|
229
|
+
PER_TASK_CONFIG_SIZE = 3000
|
|
230
|
+
|
|
231
|
+
MSE_KMS_V1_DEFAULT_KEY_ID = "alias/acs/mse"
|
|
232
|
+
|
|
233
|
+
KMS_AES_128_ALGORITHM_NAME = "AES_128"
|
|
234
|
+
|
|
235
|
+
KMS_AES_256_ALGORITHM_NAME = "AES_256"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from .constants import Constants
|
|
9
|
+
from .nacos_exception import INVALID_PARAM, NacosException
|
|
10
|
+
from .preserved_metadata_key import PreservedMetadataKeys
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Instance(BaseModel):
|
|
14
|
+
instanceId: Annotated[str, Field(description="实例ID")] = ""
|
|
15
|
+
ip: Annotated[str, Field(description="实例IP地址")]
|
|
16
|
+
port: Annotated[int, Field(description="实例端口号")]
|
|
17
|
+
weight: Annotated[float, Field(description="实例权重")] = 1.0
|
|
18
|
+
healthy: Annotated[bool, Field(description="实例健康状态")] = True
|
|
19
|
+
enabled: Annotated[bool, Field(description="实例是否启用")] = True
|
|
20
|
+
ephemeral: Annotated[bool, Field(description="实例是否临时实例")] = True
|
|
21
|
+
clusterName: Annotated[str, Field(description="实例所在集群名称")] = ""
|
|
22
|
+
serviceName: Annotated[str, Field(description="实例所在服务名称")] = ""
|
|
23
|
+
metadata: Annotated[dict, Field(description="实例元数据")] = {}
|
|
24
|
+
|
|
25
|
+
def __str__(self):
|
|
26
|
+
return f"Instance({', '.join(f'{key}={value!r}' for key, value in self.__dict__.items())})"
|
|
27
|
+
|
|
28
|
+
def to_inet_addr(self):
|
|
29
|
+
return self.ip + ":" + str(self.port)
|
|
30
|
+
|
|
31
|
+
def is_ephemeral(self) -> bool:
|
|
32
|
+
return self.ephemeral
|
|
33
|
+
|
|
34
|
+
def get_weight(self):
|
|
35
|
+
return self.weight
|
|
36
|
+
|
|
37
|
+
def add_metadata(self, key: str, value: str) -> None:
|
|
38
|
+
if self.metadata is None:
|
|
39
|
+
self.metadata = {}
|
|
40
|
+
self.metadata[key] = value
|
|
41
|
+
|
|
42
|
+
def get_instance_heart_beat_interval(self):
|
|
43
|
+
return self.__get_metadata_by_key_with_int_default(
|
|
44
|
+
PreservedMetadataKeys.HEART_BEAT_INTERVAL, Constants.DEFAULT_HEART_BEAT_INTERVAL
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def get_instance_heart_beat_timeout(self):
|
|
48
|
+
return self.__get_metadata_by_key_with_int_default(
|
|
49
|
+
PreservedMetadataKeys.HEART_BEAT_INTERVAL, Constants.DEFAULT_HEART_BEAT_TIMEOUT
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def get_ip_delete_timeout(self):
|
|
53
|
+
return self.__get_metadata_by_key_with_int_default(
|
|
54
|
+
PreservedMetadataKeys.IP_DELETE_TIMEOUT, Constants.DEFAULT_IP_DELETE_TIMEOUT
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def get_instance_id_generator(self):
|
|
58
|
+
return self.__get_metadata_by_key_with_str_default(
|
|
59
|
+
PreservedMetadataKeys.INSTANCE_ID_GENERATOR, Constants.DEFAULT_INSTANCE_ID_GENERATOR
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def check_instance_is_legal(self):
|
|
63
|
+
if (
|
|
64
|
+
self.get_instance_heart_beat_timeout() < self.get_instance_heart_beat_interval()
|
|
65
|
+
or self.get_ip_delete_timeout() < self.get_instance_heart_beat_interval()
|
|
66
|
+
):
|
|
67
|
+
raise NacosException(
|
|
68
|
+
INVALID_PARAM,
|
|
69
|
+
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.",
|
|
70
|
+
)
|
|
71
|
+
self.fill_default_value()
|
|
72
|
+
|
|
73
|
+
if not self.ip or len(self.ip) == 0:
|
|
74
|
+
raise NacosException(INVALID_PARAM, "Instance 'ip' can not be empty.")
|
|
75
|
+
|
|
76
|
+
if self.port < 0 or self.port > 65535:
|
|
77
|
+
raise NacosException(INVALID_PARAM, "Instance 'port' must be between 0 and 65535.")
|
|
78
|
+
|
|
79
|
+
def fill_default_value(self):
|
|
80
|
+
if self.clusterName is None or len(self.clusterName) == 0:
|
|
81
|
+
self.clusterName = Constants.DEFAULT_CLUSTER_NAME
|
|
82
|
+
|
|
83
|
+
def contains_metadata(self, key: str) -> bool:
|
|
84
|
+
if not self.metadata:
|
|
85
|
+
return False
|
|
86
|
+
return key in self.metadata.keys()
|
|
87
|
+
|
|
88
|
+
def __get_metadata_by_key_with_int_default(self, key: str, default_value: int) -> int:
|
|
89
|
+
if not self.metadata or key not in self.metadata:
|
|
90
|
+
return default_value
|
|
91
|
+
value = self.metadata[key]
|
|
92
|
+
|
|
93
|
+
pattern = re.compile(Constants.NUMBER_PATTERN)
|
|
94
|
+
|
|
95
|
+
if value.strip() and re.match(pattern, value):
|
|
96
|
+
return int(value)
|
|
97
|
+
|
|
98
|
+
return default_value
|
|
99
|
+
|
|
100
|
+
def __get_metadata_by_key_with_str_default(self, key: str, default_value: str) -> str:
|
|
101
|
+
if not self.metadata:
|
|
102
|
+
return default_value
|
|
103
|
+
return self.metadata[key]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
CLIENT_INVALID_PARAM = -400
|
|
2
|
+
|
|
3
|
+
CLIENT_DISCONNECT = -401
|
|
4
|
+
|
|
5
|
+
CLIENT_OVER_THRESHOLD = -503
|
|
6
|
+
|
|
7
|
+
INVALID_PARAM = 400
|
|
8
|
+
|
|
9
|
+
NO_RIGHT = 403
|
|
10
|
+
|
|
11
|
+
NOT_FOUND = 404
|
|
12
|
+
|
|
13
|
+
CONFLICT = 409
|
|
14
|
+
|
|
15
|
+
SERVER_ERROR = 500
|
|
16
|
+
|
|
17
|
+
SERVER_NOT_IMPLEMENTED = 501
|
|
18
|
+
|
|
19
|
+
BAD_GATEWAY = 502
|
|
20
|
+
|
|
21
|
+
OVER_THRESHOLD = 503
|
|
22
|
+
|
|
23
|
+
INVALID_SERVER_STATUS = 300
|
|
24
|
+
|
|
25
|
+
UN_REGISTER = 301
|
|
26
|
+
|
|
27
|
+
NO_HANDLER = 302
|
|
28
|
+
|
|
29
|
+
NOT_MODIFIED = 304
|
|
30
|
+
|
|
31
|
+
INVALID_INTERFACE_ERROR = -403
|
|
32
|
+
|
|
33
|
+
RESOURCE_NOT_FOUND = -404
|
|
34
|
+
|
|
35
|
+
HTTP_CLIENT_ERROR_CODE = -500
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class NacosException(Exception):
|
|
39
|
+
"""Custom exception class with an error code attribute."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, error_code, message="An error occurred"):
|
|
42
|
+
self.error_code = error_code
|
|
43
|
+
self.message = message
|
|
44
|
+
super().__init__(f"Error [{error_code}]: {message}")
|