data-ops-cli 0.5.1__tar.gz → 0.5.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.
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/PKG-INFO +1 -1
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/data_ops_cli.egg-info/PKG-INFO +1 -1
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/data_ops_cli.egg-info/SOURCES.txt +0 -2
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/__init__.py +1 -1
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/__init__.py +1 -1
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/factory.py +1 -5
- data_ops_cli-0.5.1/src/dataops_cli/cli/alarm.py +0 -721
- data_ops_cli-0.5.1/src/dataops_cli/cli/hazard.py +0 -406
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/README.md +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/pyproject.toml +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/setup.cfg +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/data_ops_cli.egg-info/dependency_links.txt +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/data_ops_cli.egg-info/entry_points.txt +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/data_ops_cli.egg-info/requires.txt +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/data_ops_cli.egg-info/top_level.txt +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/_compat.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/api.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/auth.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/data_table.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/dataset.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/datasource.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/dict_.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/kb.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/metrics.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/ontology.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/ref.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/report.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/skill.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/table.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/tag.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/utils.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/widget.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/cli/workflow.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/exceptions.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/runner.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/schems.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/sdk.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/session.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/src/dataops_cli/utils.py +0 -0
- {data_ops_cli-0.5.1 → data_ops_cli-0.5.2}/tests/test_table_relation.py +0 -0
|
@@ -15,7 +15,6 @@ src/dataops_cli/sdk.py
|
|
|
15
15
|
src/dataops_cli/session.py
|
|
16
16
|
src/dataops_cli/utils.py
|
|
17
17
|
src/dataops_cli/cli/__init__.py
|
|
18
|
-
src/dataops_cli/cli/alarm.py
|
|
19
18
|
src/dataops_cli/cli/api.py
|
|
20
19
|
src/dataops_cli/cli/auth.py
|
|
21
20
|
src/dataops_cli/cli/data_table.py
|
|
@@ -23,7 +22,6 @@ src/dataops_cli/cli/dataset.py
|
|
|
23
22
|
src/dataops_cli/cli/datasource.py
|
|
24
23
|
src/dataops_cli/cli/dict_.py
|
|
25
24
|
src/dataops_cli/cli/factory.py
|
|
26
|
-
src/dataops_cli/cli/hazard.py
|
|
27
25
|
src/dataops_cli/cli/kb.py
|
|
28
26
|
src/dataops_cli/cli/metrics.py
|
|
29
27
|
src/dataops_cli/cli/ontology.py
|
|
@@ -39,20 +39,18 @@ def main(
|
|
|
39
39
|
def create_app():
|
|
40
40
|
"""组装并返回 data-ops-cli 的顶层 Typer 应用。
|
|
41
41
|
|
|
42
|
-
负责集中导入各业务子命令模块(
|
|
42
|
+
负责集中导入各业务子命令模块(api、auth 等),将其 Typer 子命令组
|
|
43
43
|
注册到根应用上,并绑定 ``--version`` 回调。
|
|
44
44
|
|
|
45
45
|
Returns:
|
|
46
46
|
已注册所有子命令组的 ``typer.Typer`` 应用实例。
|
|
47
47
|
"""
|
|
48
|
-
from dataops_cli.cli.alarm import alarm_typer
|
|
49
48
|
from dataops_cli.cli.api import api_typer
|
|
50
49
|
from dataops_cli.cli.auth import auth_typer
|
|
51
50
|
from dataops_cli.cli.data_table import data_table_typer
|
|
52
51
|
from dataops_cli.cli.dataset import dataset_typer
|
|
53
52
|
from dataops_cli.cli.datasource import datasource_typer
|
|
54
53
|
from dataops_cli.cli.dict_ import dict_typer
|
|
55
|
-
from dataops_cli.cli.hazard import hazard_typer
|
|
56
54
|
from dataops_cli.cli.kb import kb_typer
|
|
57
55
|
from dataops_cli.cli.metrics import metrics_typer
|
|
58
56
|
from dataops_cli.cli.ontology import ontology_typer
|
|
@@ -71,7 +69,6 @@ def create_app():
|
|
|
71
69
|
)
|
|
72
70
|
app.add_typer(auth_typer)
|
|
73
71
|
app.add_typer(api_typer)
|
|
74
|
-
app.add_typer(alarm_typer)
|
|
75
72
|
app.add_typer(datasource_typer)
|
|
76
73
|
app.add_typer(dataset_typer)
|
|
77
74
|
app.add_typer(table_typer)
|
|
@@ -84,7 +81,6 @@ def create_app():
|
|
|
84
81
|
app.add_typer(data_table_typer)
|
|
85
82
|
app.add_typer(widget_typer)
|
|
86
83
|
app.add_typer(dict_typer)
|
|
87
|
-
app.add_typer(hazard_typer)
|
|
88
84
|
app.add_typer(kb_typer)
|
|
89
85
|
app.add_typer(tag_typer)
|
|
90
86
|
|
|
@@ -1,721 +0,0 @@
|
|
|
1
|
-
"""告警管理模块.
|
|
2
|
-
|
|
3
|
-
提供告警规则的查询与配置能力,覆盖后端 /alarm/rule/* 接口。
|
|
4
|
-
|
|
5
|
-
- 服务层函数 (service_*):纯 Python 接口,返回原始数据
|
|
6
|
-
- CLI 命令:基于服务层的薄包装,负责格式化输出
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import json
|
|
10
|
-
from typing import Annotated, Any
|
|
11
|
-
|
|
12
|
-
import typer
|
|
13
|
-
from dataops_sdk.exceptions import DataOpsError
|
|
14
|
-
from dataops_sdk.services.alarm import (
|
|
15
|
-
service_count_alarm_action,
|
|
16
|
-
service_count_alarm_rule_matches,
|
|
17
|
-
service_count_alarm_rules,
|
|
18
|
-
service_count_alarm_specs,
|
|
19
|
-
service_find_alarm_table_data,
|
|
20
|
-
service_find_meta_by_codes,
|
|
21
|
-
service_get_alarm_action_detail,
|
|
22
|
-
service_get_alarm_builtin_function_detail,
|
|
23
|
-
service_get_alarm_preprocess_detail,
|
|
24
|
-
service_get_alarm_rule_detail,
|
|
25
|
-
service_get_alarm_rule_enums,
|
|
26
|
-
service_get_alarm_rule_type_detail,
|
|
27
|
-
service_get_alarm_spec_detail,
|
|
28
|
-
service_get_alarm_table_columns,
|
|
29
|
-
service_get_rel_table_columns,
|
|
30
|
-
service_list_alarm_action,
|
|
31
|
-
service_list_alarm_builtin_functions,
|
|
32
|
-
service_list_alarm_preprocess,
|
|
33
|
-
service_list_alarm_rule_matches,
|
|
34
|
-
service_list_alarm_rules,
|
|
35
|
-
service_list_alarm_specs,
|
|
36
|
-
)
|
|
37
|
-
from pydantic_core import to_json
|
|
38
|
-
from rich.console import Console
|
|
39
|
-
from rich.table import Table
|
|
40
|
-
|
|
41
|
-
from dataops_cli.cli.utils import print_list
|
|
42
|
-
|
|
43
|
-
# ---------------------------------------------------------------------------
|
|
44
|
-
# CLI 命令(薄包装,负责输出渲染)
|
|
45
|
-
# ---------------------------------------------------------------------------
|
|
46
|
-
|
|
47
|
-
alarm_typer = typer.Typer(name="alarm", help="告警规则配置", no_args_is_help=True)
|
|
48
|
-
alarm_rule_typer = typer.Typer(name="rule", help="告警规则命令", no_args_is_help=True)
|
|
49
|
-
alarm_rule_type_typer = typer.Typer(name="type", help="告警规则类型命令", no_args_is_help=True)
|
|
50
|
-
alarm_spec_typer = typer.Typer(name="spec", help="告警专业命令", no_args_is_help=True)
|
|
51
|
-
alarm_action_typer = typer.Typer(name="action", help="告警动作命令", no_args_is_help=True)
|
|
52
|
-
alarm_preprocess_typer = typer.Typer(name="preprocess", help="预处理脚本命令", no_args_is_help=True)
|
|
53
|
-
alarm_builtin_function_typer = typer.Typer(
|
|
54
|
-
name="builtin-function", help="内置函数命令", no_args_is_help=True
|
|
55
|
-
)
|
|
56
|
-
rule_match_typer = typer.Typer(name="match", help="规则匹配命令", no_args_is_help=True)
|
|
57
|
-
alarm_typer.add_typer(alarm_rule_typer, no_args_is_help=True)
|
|
58
|
-
alarm_typer.add_typer(alarm_spec_typer, no_args_is_help=True)
|
|
59
|
-
alarm_rule_typer.add_typer(alarm_rule_type_typer, no_args_is_help=True)
|
|
60
|
-
alarm_rule_typer.add_typer(rule_match_typer, no_args_is_help=True)
|
|
61
|
-
alarm_typer.add_typer(alarm_action_typer, no_args_is_help=True)
|
|
62
|
-
alarm_typer.add_typer(alarm_preprocess_typer, no_args_is_help=True)
|
|
63
|
-
alarm_typer.add_typer(alarm_builtin_function_typer, no_args_is_help=True)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def _safe_str(value: Any) -> str:
|
|
67
|
-
if value is None:
|
|
68
|
-
return ""
|
|
69
|
-
if isinstance(value, (dict, list)):
|
|
70
|
-
return to_json(value).decode("utf-8")
|
|
71
|
-
return str(value)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def _extract_column_list(data: Any) -> list:
|
|
75
|
-
"""从响应中提取列数组。
|
|
76
|
-
|
|
77
|
-
后端返回可能是:
|
|
78
|
-
- list[...] 直接列表
|
|
79
|
-
- dict {"columns": [...], "indexes": [...]} 嵌套结构
|
|
80
|
-
- None / 其他 空
|
|
81
|
-
"""
|
|
82
|
-
if isinstance(data, list):
|
|
83
|
-
return data
|
|
84
|
-
if isinstance(data, dict):
|
|
85
|
-
columns = data.get("columns")
|
|
86
|
-
if isinstance(columns, list):
|
|
87
|
-
return columns
|
|
88
|
-
return []
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def _print_column_list(data: Any) -> None:
|
|
92
|
-
"""统一渲染列数组(list[dict] → 平面表;其他 → JSON)."""
|
|
93
|
-
columns = _extract_column_list(data)
|
|
94
|
-
if not columns:
|
|
95
|
-
print("(空)")
|
|
96
|
-
return
|
|
97
|
-
if isinstance(columns[0], dict):
|
|
98
|
-
headers = list(columns[0].keys())
|
|
99
|
-
rows = [[_safe_str(c.get(h)) for h in headers] for c in columns]
|
|
100
|
-
print_list(headers, rows)
|
|
101
|
-
else:
|
|
102
|
-
print(to_json(columns).decode("utf-8"))
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def _print_alarm_detail(detail: Any, title: str, simplify: bool = False) -> None:
|
|
106
|
-
"""渲染告警详情的主体、data 和参数。"""
|
|
107
|
-
console = Console(no_color=True)
|
|
108
|
-
meta = detail.meta
|
|
109
|
-
basic_table = Table("字段", "值", title=title, show_header=False)
|
|
110
|
-
for field in ("code", "title", "type", "remark", "createUser", "lastModifyTime"):
|
|
111
|
-
value = getattr(meta, field, None)
|
|
112
|
-
if value is not None:
|
|
113
|
-
basic_table.add_row(field, _safe_str(value))
|
|
114
|
-
console.print(basic_table)
|
|
115
|
-
|
|
116
|
-
data = meta.data or {}
|
|
117
|
-
if hasattr(data, "model_dump"):
|
|
118
|
-
data = data.model_dump(mode="json")
|
|
119
|
-
if isinstance(data, dict):
|
|
120
|
-
data_table = Table("data 字段", "值", title="详情数据", show_header=False)
|
|
121
|
-
for key, value in data.items():
|
|
122
|
-
if simplify and key.lower() in {"script", "scriptcontent", "script_content"}:
|
|
123
|
-
continue
|
|
124
|
-
data_table.add_row(str(key), _safe_str(value))
|
|
125
|
-
if data_table.row_count:
|
|
126
|
-
console.print(data_table)
|
|
127
|
-
|
|
128
|
-
if detail.params:
|
|
129
|
-
params_table = Table("参数", "值", title="Meta 参数", show_header=False)
|
|
130
|
-
for key, value in detail.params.items():
|
|
131
|
-
params_table.add_row(str(key), _safe_str(value))
|
|
132
|
-
console.print(params_table)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def _handle_alarm_detail(detail_service, code: str, title: str, simplify: bool) -> None:
|
|
136
|
-
"""统一处理详情 service 的错误和终端输出。"""
|
|
137
|
-
try:
|
|
138
|
-
detail = detail_service(code)
|
|
139
|
-
except DataOpsError as e:
|
|
140
|
-
typer.echo(f"错误: {e.message}")
|
|
141
|
-
raise typer.Exit(code=1) from None
|
|
142
|
-
_print_alarm_detail(detail, title, simplify)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
@alarm_preprocess_typer.command("list", help="查询预处理脚本")
|
|
146
|
-
def list_alarm_preprocess(
|
|
147
|
-
spec_type: Annotated[
|
|
148
|
-
list[str] | None, typer.Option("--spec-type", help="关联专业编码,可重复传入")
|
|
149
|
-
] = None,
|
|
150
|
-
enabled: Annotated[
|
|
151
|
-
list[str] | None, typer.Option("--enabled", help="启用状态值 1/0,可重复传入")
|
|
152
|
-
] = None,
|
|
153
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
154
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
155
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="脚本名称关键词")] = None,
|
|
156
|
-
) -> None:
|
|
157
|
-
"""查询预处理脚本列表。"""
|
|
158
|
-
try:
|
|
159
|
-
rows = service_list_alarm_preprocess(
|
|
160
|
-
page_num,
|
|
161
|
-
page_size,
|
|
162
|
-
query,
|
|
163
|
-
spec_type or [],
|
|
164
|
-
enabled or [],
|
|
165
|
-
)
|
|
166
|
-
except DataOpsError as e:
|
|
167
|
-
typer.echo(f"错误: {e.message}")
|
|
168
|
-
raise typer.Exit(code=1) from None
|
|
169
|
-
|
|
170
|
-
if not rows:
|
|
171
|
-
print("未查询到预处理脚本")
|
|
172
|
-
return
|
|
173
|
-
print_list(
|
|
174
|
-
["脚本编码", "脚本名称", "关联专业", "脚本说明", "启用状态", "创建人", "创建时间"],
|
|
175
|
-
[
|
|
176
|
-
[
|
|
177
|
-
row.CODE,
|
|
178
|
-
row.TITLE,
|
|
179
|
-
row.N_SPEC_TYPE,
|
|
180
|
-
row.DESCRIPTION,
|
|
181
|
-
row.IS_ENABLED,
|
|
182
|
-
row.CREATE_USER,
|
|
183
|
-
row.CREATE_TIME,
|
|
184
|
-
]
|
|
185
|
-
for row in rows
|
|
186
|
-
],
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
@alarm_preprocess_typer.command("detail", no_args_is_help=True)
|
|
191
|
-
def get_alarm_preprocess_detail(
|
|
192
|
-
code: Annotated[str, typer.Argument(help="预处理脚本编码")],
|
|
193
|
-
simplify: Annotated[bool, typer.Option("-s", "--simplify", help="隐藏脚本正文")] = False,
|
|
194
|
-
) -> None:
|
|
195
|
-
"""按编码查询预处理脚本详情。"""
|
|
196
|
-
_handle_alarm_detail(
|
|
197
|
-
service_get_alarm_preprocess_detail,
|
|
198
|
-
code,
|
|
199
|
-
"预处理脚本详情",
|
|
200
|
-
simplify,
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
@alarm_builtin_function_typer.command("list", help="查询内置函数")
|
|
205
|
-
def list_alarm_builtin_functions(
|
|
206
|
-
enabled: Annotated[
|
|
207
|
-
list[str] | None, typer.Option("--enabled", help="启用状态值 1/0,可重复传入")
|
|
208
|
-
] = None,
|
|
209
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
210
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
211
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="函数名称关键词")] = None,
|
|
212
|
-
) -> None:
|
|
213
|
-
"""查询内置函数列表。"""
|
|
214
|
-
try:
|
|
215
|
-
rows = service_list_alarm_builtin_functions(page_num, page_size, query, enabled or [])
|
|
216
|
-
except DataOpsError as e:
|
|
217
|
-
typer.echo(f"错误: {e.message}")
|
|
218
|
-
raise typer.Exit(code=1) from None
|
|
219
|
-
|
|
220
|
-
if not rows:
|
|
221
|
-
print("未查询到内置函数")
|
|
222
|
-
return
|
|
223
|
-
print_list(
|
|
224
|
-
["函数编码", "函数名称", "类全路径", "备注", "启用状态", "创建人", "创建时间"],
|
|
225
|
-
[
|
|
226
|
-
[
|
|
227
|
-
row.CODE,
|
|
228
|
-
row.TITLE,
|
|
229
|
-
row.CLAZZ,
|
|
230
|
-
row.REMARK,
|
|
231
|
-
row.IS_ENABLED,
|
|
232
|
-
row.CREATE_USER,
|
|
233
|
-
row.CREATE_TIME,
|
|
234
|
-
]
|
|
235
|
-
for row in rows
|
|
236
|
-
],
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
@alarm_builtin_function_typer.command("detail", no_args_is_help=True)
|
|
241
|
-
def get_alarm_builtin_function_detail(
|
|
242
|
-
code: Annotated[str, typer.Argument(help="内置函数编码")],
|
|
243
|
-
simplify: Annotated[bool, typer.Option("-s", "--simplify", help="隐藏函数脚本")] = False,
|
|
244
|
-
) -> None:
|
|
245
|
-
"""按编码查询内置函数详情。"""
|
|
246
|
-
_handle_alarm_detail(
|
|
247
|
-
service_get_alarm_builtin_function_detail,
|
|
248
|
-
code,
|
|
249
|
-
"内置函数详情",
|
|
250
|
-
simplify,
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
@rule_match_typer.command("count", help="查询告警匹配规则数量")
|
|
255
|
-
def count_alarm_rules_match(
|
|
256
|
-
spec: Annotated[list[str], typer.Option(help="专业值", default_factory=list)],
|
|
257
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
258
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
259
|
-
):
|
|
260
|
-
"""查询告警匹配规则数量。
|
|
261
|
-
|
|
262
|
-
按专业、关键字与启用状态进行过滤,返回匹配规则的总数。
|
|
263
|
-
|
|
264
|
-
Args:
|
|
265
|
-
spec: 专业值列表,多个值会同时参与匹配。
|
|
266
|
-
query: 可选关键字,用于模糊搜索。
|
|
267
|
-
enabled: 可选启用状态过滤;为 ``True`` / ``False`` 时严格匹配。
|
|
268
|
-
|
|
269
|
-
Examples:
|
|
270
|
-
>>> data-ops-cli alarm rule match count --spec MY_SPEC
|
|
271
|
-
"""
|
|
272
|
-
try:
|
|
273
|
-
total = service_count_alarm_rule_matches(query, enabled, spec)
|
|
274
|
-
except DataOpsError as e:
|
|
275
|
-
typer.echo(f"错误: {e.message}")
|
|
276
|
-
raise typer.Exit(code=1) from None
|
|
277
|
-
print(total)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
@rule_match_typer.command("list", help="查询告警匹配规则")
|
|
281
|
-
def list_alarm_rules_match(
|
|
282
|
-
spec: Annotated[list[str], typer.Option(help="专业值", default_factory=list)],
|
|
283
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
284
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
285
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
286
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
287
|
-
):
|
|
288
|
-
"""查询告警匹配规则列表。
|
|
289
|
-
|
|
290
|
-
按专业、关键字与启用状态过滤告警匹配规则,并以平面表格形式输出。
|
|
291
|
-
|
|
292
|
-
Args:
|
|
293
|
-
spec: 专业值列表,多个值同时参与匹配。
|
|
294
|
-
page: 页码(从 0 开始)。
|
|
295
|
-
size: 每页条数。
|
|
296
|
-
query: 可选关键字。
|
|
297
|
-
enabled: 可选启用状态过滤。
|
|
298
|
-
|
|
299
|
-
Examples:
|
|
300
|
-
>>> data-ops-cli alarm rule match list --spec MY_SPEC --page 0 --size 20
|
|
301
|
-
"""
|
|
302
|
-
try:
|
|
303
|
-
group_nodes = service_list_alarm_rule_matches(page_num, page_size, query, enabled, spec)
|
|
304
|
-
except DataOpsError as e:
|
|
305
|
-
typer.echo(f"错误: {e.message}")
|
|
306
|
-
raise typer.Exit(code=1) from None
|
|
307
|
-
|
|
308
|
-
if not group_nodes:
|
|
309
|
-
print("未查询到匹配告警规则")
|
|
310
|
-
return
|
|
311
|
-
print_list(
|
|
312
|
-
[
|
|
313
|
-
"告警匹配规则名称",
|
|
314
|
-
"规则类型(值)",
|
|
315
|
-
"启用状态",
|
|
316
|
-
"所属区域",
|
|
317
|
-
"专业类型(值)",
|
|
318
|
-
"创建人",
|
|
319
|
-
"更新时间",
|
|
320
|
-
],
|
|
321
|
-
[
|
|
322
|
-
[
|
|
323
|
-
column.TITLE,
|
|
324
|
-
f"{column.N_RULE_TYPE}({column.RULE_TYPE})",
|
|
325
|
-
column.N_IS_ENABLED,
|
|
326
|
-
column.AREA,
|
|
327
|
-
f"{column.N_SPEC_TYPE}({column.SPEC_TYPE})",
|
|
328
|
-
column.CREATE_USER,
|
|
329
|
-
column.LAST_MODIFY_TIME,
|
|
330
|
-
]
|
|
331
|
-
for column in group_nodes
|
|
332
|
-
],
|
|
333
|
-
)
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
@alarm_rule_typer.command("list", help="查询告警匹配规则")
|
|
337
|
-
def list_alarm_rules(
|
|
338
|
-
spec: Annotated[list[str], typer.Option(help="专业值", default_factory=list)],
|
|
339
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
340
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
341
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
342
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
343
|
-
) -> None:
|
|
344
|
-
"""查询告警匹配规则列表。
|
|
345
|
-
|
|
346
|
-
这是前端 ``pages/alarm/rule`` 对应的 canonical 命令;旧的
|
|
347
|
-
``alarm rule match list`` 仍保留作为兼容入口。
|
|
348
|
-
"""
|
|
349
|
-
list_alarm_rules_match(spec, page_num, page_size, query, enabled)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
@alarm_rule_typer.command("detail", no_args_is_help=True)
|
|
353
|
-
def get_alarm_rule_detail(
|
|
354
|
-
code: Annotated[str, typer.Argument(help="告警匹配规则编码")],
|
|
355
|
-
simplify: Annotated[bool, typer.Option("-s", "--simplify", help="简化详情输出")] = False,
|
|
356
|
-
) -> None:
|
|
357
|
-
"""按编码查询告警匹配规则基础详情。"""
|
|
358
|
-
_handle_alarm_detail(service_get_alarm_rule_detail, code, "告警匹配规则详情", simplify)
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
@alarm_rule_typer.command("count", help="兼容查询告警规则类型数量")
|
|
362
|
-
def count_alarm_rules_compat(
|
|
363
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
364
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
365
|
-
) -> None:
|
|
366
|
-
"""兼容保留的原规则类型数量命令。
|
|
367
|
-
|
|
368
|
-
规则类型的 canonical 列表命令是 ``alarm rule type list``;匹配规则数量
|
|
369
|
-
仍使用 ``alarm rule match count``。
|
|
370
|
-
"""
|
|
371
|
-
try:
|
|
372
|
-
total = service_count_alarm_rules(query, enabled)
|
|
373
|
-
except DataOpsError as e:
|
|
374
|
-
typer.echo(f"错误: {e.message}")
|
|
375
|
-
raise typer.Exit(code=1) from None
|
|
376
|
-
print(total)
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
@alarm_spec_typer.command("list", help="查询告警专业")
|
|
380
|
-
def list_alarm_specs(
|
|
381
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
382
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
383
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
384
|
-
active: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
385
|
-
):
|
|
386
|
-
"""查询告警专业列表。
|
|
387
|
-
|
|
388
|
-
按关键字与启用状态过滤告警专业(spec),输出标题、值、行业等基础字段。
|
|
389
|
-
|
|
390
|
-
Args:
|
|
391
|
-
page: 页码(从 0 开始)。
|
|
392
|
-
size: 每页条数。
|
|
393
|
-
query: 可选关键字。
|
|
394
|
-
active: 可选启用状态过滤。
|
|
395
|
-
|
|
396
|
-
Examples:
|
|
397
|
-
>>> data-ops-cli alarm spec list -q "网元"
|
|
398
|
-
"""
|
|
399
|
-
group_nodes = service_list_alarm_specs(page_num, page_size, query, active)
|
|
400
|
-
|
|
401
|
-
print_list(
|
|
402
|
-
["专业名称", "值", "行业", "启用状态", "创建人", "更新时间"],
|
|
403
|
-
[
|
|
404
|
-
[
|
|
405
|
-
column.TITLE,
|
|
406
|
-
column.CODE,
|
|
407
|
-
column.N_INDUSTRY,
|
|
408
|
-
column.N_IS_ENABLED,
|
|
409
|
-
column.CREATE_USER,
|
|
410
|
-
column.LAST_MODIFY_TIME,
|
|
411
|
-
]
|
|
412
|
-
for column in group_nodes
|
|
413
|
-
],
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
@alarm_spec_typer.command("detail", no_args_is_help=True)
|
|
418
|
-
def get_alarm_spec_detail(
|
|
419
|
-
code: Annotated[str, typer.Argument(help="告警专业编码")],
|
|
420
|
-
simplify: Annotated[bool, typer.Option("-s", "--simplify", help="简化详情输出")] = False,
|
|
421
|
-
) -> None:
|
|
422
|
-
"""按编码查询告警专业详情。"""
|
|
423
|
-
_handle_alarm_detail(service_get_alarm_spec_detail, code, "告警专业详情", simplify)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
@alarm_spec_typer.command("count", help="查询告警专业数量")
|
|
427
|
-
def count_alarm_specs(
|
|
428
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
429
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
430
|
-
):
|
|
431
|
-
"""查询告警专业的总数。
|
|
432
|
-
|
|
433
|
-
Args:
|
|
434
|
-
query: 可选关键字。
|
|
435
|
-
enabled: 可选启用状态过滤。
|
|
436
|
-
|
|
437
|
-
Examples:
|
|
438
|
-
>>> data-ops-cli alarm spec count
|
|
439
|
-
"""
|
|
440
|
-
total = service_count_alarm_specs(query, enabled)
|
|
441
|
-
print(total)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
@alarm_rule_type_typer.command("list", help="查询告警规则类型")
|
|
445
|
-
def list_alarm_rule_types(
|
|
446
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
447
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
448
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
449
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
450
|
-
):
|
|
451
|
-
"""查询告警规则类型列表。
|
|
452
|
-
|
|
453
|
-
按关键字与启用状态过滤告警规则,并以平面表格输出名称、值与启用状态。
|
|
454
|
-
|
|
455
|
-
Args:
|
|
456
|
-
page: 页码(从 0 开始)。
|
|
457
|
-
size: 每页条数。
|
|
458
|
-
query: 可选关键字。
|
|
459
|
-
enabled: 可选启用状态过滤。
|
|
460
|
-
|
|
461
|
-
Examples:
|
|
462
|
-
>>> data-ops-cli alarm rule type list -q "电压"
|
|
463
|
-
"""
|
|
464
|
-
group_nodes = service_list_alarm_rules(page_num, page_size, query, enabled)
|
|
465
|
-
|
|
466
|
-
print_list(
|
|
467
|
-
["规则名称", "值", "启用状态", "创建人", "更新时间"],
|
|
468
|
-
[
|
|
469
|
-
[
|
|
470
|
-
column.TITLE,
|
|
471
|
-
column.CODE,
|
|
472
|
-
column.N_IS_ENABLED,
|
|
473
|
-
column.CREATE_USER,
|
|
474
|
-
column.LAST_MODIFY_TIME,
|
|
475
|
-
]
|
|
476
|
-
for column in group_nodes
|
|
477
|
-
],
|
|
478
|
-
)
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
@alarm_rule_type_typer.command("detail", no_args_is_help=True)
|
|
482
|
-
def get_alarm_rule_type_detail(
|
|
483
|
-
code: Annotated[str, typer.Argument(help="告警规则类型编码")],
|
|
484
|
-
simplify: Annotated[bool, typer.Option("-s", "--simplify", help="简化详情输出")] = False,
|
|
485
|
-
) -> None:
|
|
486
|
-
"""按编码查询告警规则类型详情。"""
|
|
487
|
-
_handle_alarm_detail(service_get_alarm_rule_type_detail, code, "告警规则类型详情", simplify)
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
@alarm_rule_type_typer.command("count", help="查询告警规则类型数量")
|
|
491
|
-
def count_alarm_rule_types(
|
|
492
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
493
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
494
|
-
):
|
|
495
|
-
"""查询告警规则的总数。
|
|
496
|
-
|
|
497
|
-
Args:
|
|
498
|
-
query: 可选关键字。
|
|
499
|
-
enabled: 可选启用状态过滤。
|
|
500
|
-
|
|
501
|
-
Examples:
|
|
502
|
-
>>> data-ops-cli alarm rule type count
|
|
503
|
-
"""
|
|
504
|
-
total = service_count_alarm_rules(query, enabled)
|
|
505
|
-
print(total)
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
@alarm_action_typer.command("list", help="查询告警动作")
|
|
509
|
-
def list_alarm_actions(
|
|
510
|
-
rule: Annotated[list[str], typer.Option(help="专业值", default_factory=list)],
|
|
511
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", "--page", help="页码")] = 0,
|
|
512
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", "--size", help="每页大小")] = 20,
|
|
513
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
514
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
515
|
-
):
|
|
516
|
-
"""查询告警动作列表。
|
|
517
|
-
|
|
518
|
-
按所属规则、关键字与启用状态过滤告警动作,并以平面表格输出。
|
|
519
|
-
|
|
520
|
-
Args:
|
|
521
|
-
rule: 所属规则编码列表。
|
|
522
|
-
page: 页码(从 0 开始)。
|
|
523
|
-
size: 每页条数。
|
|
524
|
-
query: 可选关键字。
|
|
525
|
-
enabled: 可选启用状态过滤。
|
|
526
|
-
|
|
527
|
-
Examples:
|
|
528
|
-
>>> data-ops-cli alarm action list --rule MY_RULE
|
|
529
|
-
"""
|
|
530
|
-
try:
|
|
531
|
-
group_nodes = service_list_alarm_action(page_num, page_size, query, enabled, rule)
|
|
532
|
-
except DataOpsError as e:
|
|
533
|
-
typer.echo(f"错误: {e.message}")
|
|
534
|
-
raise typer.Exit(code=1) from None
|
|
535
|
-
|
|
536
|
-
if not group_nodes:
|
|
537
|
-
print("未查询到匹配告警动作")
|
|
538
|
-
return
|
|
539
|
-
print_list(
|
|
540
|
-
[
|
|
541
|
-
"动作名称",
|
|
542
|
-
"值",
|
|
543
|
-
"规则类型(值)",
|
|
544
|
-
"启用状态",
|
|
545
|
-
"创建人",
|
|
546
|
-
"更新时间",
|
|
547
|
-
],
|
|
548
|
-
[
|
|
549
|
-
[
|
|
550
|
-
column.TITLE,
|
|
551
|
-
column.CODE,
|
|
552
|
-
f"{column.N_RULE_TYPE}({column.RULE_TYPE})",
|
|
553
|
-
column.N_IS_ENABLED,
|
|
554
|
-
column.CREATE_USER,
|
|
555
|
-
column.LAST_MODIFY_TIME,
|
|
556
|
-
]
|
|
557
|
-
for column in group_nodes
|
|
558
|
-
],
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
@alarm_action_typer.command("detail", no_args_is_help=True)
|
|
563
|
-
def get_alarm_action_detail(
|
|
564
|
-
code: Annotated[str, typer.Argument(help="告警动作编码")],
|
|
565
|
-
simplify: Annotated[bool, typer.Option("-s", "--simplify", help="简化详情输出")] = False,
|
|
566
|
-
) -> None:
|
|
567
|
-
"""按编码查询告警处置动作详情。"""
|
|
568
|
-
_handle_alarm_detail(service_get_alarm_action_detail, code, "告警处置动作详情", simplify)
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
@alarm_action_typer.command("count", help="查询告警动作数量")
|
|
572
|
-
def count_alarm_actions(
|
|
573
|
-
rule: Annotated[list[str], typer.Option(help="专业值", default_factory=list)],
|
|
574
|
-
query: Annotated[str | None, typer.Option("-q", "--query", help="搜索关键字")] = None,
|
|
575
|
-
enabled: Annotated[bool | None, typer.Option(help="启用状态")] = None,
|
|
576
|
-
):
|
|
577
|
-
"""查询告警动作的总数。
|
|
578
|
-
|
|
579
|
-
Args:
|
|
580
|
-
rule: 所属规则编码列表。
|
|
581
|
-
query: 可选关键字。
|
|
582
|
-
enabled: 可选启用状态过滤。
|
|
583
|
-
|
|
584
|
-
Examples:
|
|
585
|
-
>>> data-ops-cli alarm action count --rule MY_RULE
|
|
586
|
-
"""
|
|
587
|
-
try:
|
|
588
|
-
total = service_count_alarm_action(query, enabled, rule)
|
|
589
|
-
except DataOpsError as e:
|
|
590
|
-
typer.echo(f"错误: {e.message}")
|
|
591
|
-
raise typer.Exit(code=1) from None
|
|
592
|
-
print(total)
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
@alarm_rule_typer.command("enums")
|
|
596
|
-
def get_alarm_rule_enums() -> None:
|
|
597
|
-
"""获取告警规则枚举配置。
|
|
598
|
-
|
|
599
|
-
后端返回 ``dict`` 时以两列 ``key/value`` 表渲染;其他结构以 JSON 形式输出。
|
|
600
|
-
|
|
601
|
-
Examples:
|
|
602
|
-
>>> data-ops-cli alarm rule enums
|
|
603
|
-
"""
|
|
604
|
-
try:
|
|
605
|
-
data = service_get_alarm_rule_enums()
|
|
606
|
-
except DataOpsError as e:
|
|
607
|
-
typer.echo(f"错误: {e.message}")
|
|
608
|
-
raise typer.Exit(code=1) from None
|
|
609
|
-
|
|
610
|
-
if not data:
|
|
611
|
-
print("(空)")
|
|
612
|
-
return
|
|
613
|
-
|
|
614
|
-
if isinstance(data, dict):
|
|
615
|
-
table = Table("key", "value", show_header=False)
|
|
616
|
-
for k, v in data.items():
|
|
617
|
-
table.add_row(k, _safe_str(v))
|
|
618
|
-
console = Console(no_color=True)
|
|
619
|
-
console.print(table)
|
|
620
|
-
else:
|
|
621
|
-
print(to_json(data).decode("utf-8"))
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
@alarm_rule_typer.command("find-meta-by-codes", no_args_is_help=True)
|
|
625
|
-
def find_meta_by_codes(
|
|
626
|
-
codes: Annotated[list[str], typer.Argument(help="告警规则编码列表")],
|
|
627
|
-
) -> None:
|
|
628
|
-
"""根据告警规则编码批量查询关联元数据。
|
|
629
|
-
|
|
630
|
-
以 JSON 格式输出查询结果,便于人工检视或管道后续处理。
|
|
631
|
-
|
|
632
|
-
Args:
|
|
633
|
-
codes: 告警规则编码列表。
|
|
634
|
-
|
|
635
|
-
Examples:
|
|
636
|
-
>>> data-ops-cli alarm rule find-meta-by-codes code1 code2
|
|
637
|
-
"""
|
|
638
|
-
try:
|
|
639
|
-
data = service_find_meta_by_codes(list(codes))
|
|
640
|
-
except DataOpsError as e:
|
|
641
|
-
typer.echo(f"错误: {e.message}")
|
|
642
|
-
raise typer.Exit(code=1) from None
|
|
643
|
-
|
|
644
|
-
print(to_json(data).decode("utf-8"))
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
@alarm_rule_typer.command("alarm-columns", no_args_is_help=True)
|
|
648
|
-
def get_alarm_table_columns(
|
|
649
|
-
spec_type: Annotated[str, typer.Argument(help="告警规格类型")],
|
|
650
|
-
) -> None:
|
|
651
|
-
"""获取指定 specType 对应的告警表列定义。
|
|
652
|
-
|
|
653
|
-
Args:
|
|
654
|
-
spec_type: 告警规格类型编码。
|
|
655
|
-
|
|
656
|
-
Examples:
|
|
657
|
-
>>> data-ops-cli alarm rule alarm-columns MY_SPEC_TYPE
|
|
658
|
-
"""
|
|
659
|
-
try:
|
|
660
|
-
columns = service_get_alarm_table_columns(spec_type)
|
|
661
|
-
except DataOpsError as e:
|
|
662
|
-
typer.echo(f"错误: {e.message}")
|
|
663
|
-
raise typer.Exit(code=1) from None
|
|
664
|
-
|
|
665
|
-
_print_column_list(columns)
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
@alarm_rule_typer.command("rel-columns", no_args_is_help=True)
|
|
669
|
-
def get_rel_table_columns(
|
|
670
|
-
code: Annotated[str, typer.Argument(help="告警规则编码")],
|
|
671
|
-
) -> None:
|
|
672
|
-
"""获取指定告警规则关联表的列定义。
|
|
673
|
-
|
|
674
|
-
Args:
|
|
675
|
-
code: 告警规则编码。
|
|
676
|
-
|
|
677
|
-
Examples:
|
|
678
|
-
>>> data-ops-cli alarm rule rel-columns rule_code_001
|
|
679
|
-
"""
|
|
680
|
-
try:
|
|
681
|
-
columns = service_get_rel_table_columns(code)
|
|
682
|
-
except DataOpsError as e:
|
|
683
|
-
typer.echo(f"错误: {e.message}")
|
|
684
|
-
raise typer.Exit(code=1) from None
|
|
685
|
-
|
|
686
|
-
_print_column_list(columns)
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
@alarm_rule_typer.command("data", no_args_is_help=True)
|
|
690
|
-
def find_alarm_table_data(
|
|
691
|
-
code: Annotated[str, typer.Option(help="告警规则编码")],
|
|
692
|
-
query: Annotated[
|
|
693
|
-
str | None,
|
|
694
|
-
typer.Option(help="查询条件 JSON 字符串"),
|
|
695
|
-
] = None,
|
|
696
|
-
) -> None:
|
|
697
|
-
"""查询指定数据源中告警表的实际数据(由告警规则写入的记录,非实时告警)。
|
|
698
|
-
|
|
699
|
-
``--query`` 接收 JSON 字符串并解析为 dict 后透传给 SDK。
|
|
700
|
-
|
|
701
|
-
Args:
|
|
702
|
-
code: 告警规则编码。
|
|
703
|
-
query: 可选 JSON 字符串,表示查询条件。
|
|
704
|
-
|
|
705
|
-
Examples:
|
|
706
|
-
>>> data-ops-cli alarm rule data --code rule_code_001
|
|
707
|
-
>>> data-ops-cli alarm rule data --code rule_code_001 --query '{"date":"2026-07-16"}'
|
|
708
|
-
"""
|
|
709
|
-
try:
|
|
710
|
-
query_dict = json.loads(query) if query else None
|
|
711
|
-
except json.JSONDecodeError as e:
|
|
712
|
-
typer.echo(f"错误: --query 不是合法 JSON: {e}")
|
|
713
|
-
raise typer.Exit(code=1) from None
|
|
714
|
-
|
|
715
|
-
try:
|
|
716
|
-
data = service_find_alarm_table_data(code, query_dict)
|
|
717
|
-
except DataOpsError as e:
|
|
718
|
-
typer.echo(f"错误: {e.message}")
|
|
719
|
-
raise typer.Exit(code=1) from None
|
|
720
|
-
|
|
721
|
-
print(to_json(data).decode("utf-8"))
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
"""隐患管理命令组.
|
|
2
|
-
|
|
3
|
-
- 服务层函数 (service_*):纯 Python 接口,返回原始数据
|
|
4
|
-
- CLI 命令:基于服务层的薄包装,负责格式化输出
|
|
5
|
-
|
|
6
|
-
后端接口(位于 data-ops-guard 服务):
|
|
7
|
-
|
|
8
|
-
- /hazard/task/trigger/{code}
|
|
9
|
-
- /hazard/task/logs/{taskCode}
|
|
10
|
-
- /hazard/task/log/records/{taskId}
|
|
11
|
-
- /hazard/record/list
|
|
12
|
-
- /hazard/record/his/list
|
|
13
|
-
- /hazard/record/dispatch/callback
|
|
14
|
-
- /hazard/record/his/clear
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
|
-
import json
|
|
20
|
-
from datetime import datetime
|
|
21
|
-
from typing import Annotated, Any
|
|
22
|
-
|
|
23
|
-
import typer
|
|
24
|
-
from dataops_sdk.exceptions import DataOpsError
|
|
25
|
-
from dataops_sdk.schemas.query import PageParam, SqlQueryParam
|
|
26
|
-
from dataops_sdk.services import (
|
|
27
|
-
service_clear_hazard_history_records,
|
|
28
|
-
service_dispatch_hazard_callback,
|
|
29
|
-
service_get_hazard_task_log_records,
|
|
30
|
-
service_get_hazard_task_logs,
|
|
31
|
-
service_list_hazard_history_records,
|
|
32
|
-
service_list_hazard_records,
|
|
33
|
-
service_trigger_hazard_task,
|
|
34
|
-
)
|
|
35
|
-
from pydantic_core import to_json
|
|
36
|
-
from rich.console import Console
|
|
37
|
-
from rich.table import Table
|
|
38
|
-
|
|
39
|
-
from dataops_cli.cli.utils import print_list
|
|
40
|
-
|
|
41
|
-
# ---------------------------------------------------------------------------
|
|
42
|
-
# CLI 命令(薄包装,负责输出渲染)
|
|
43
|
-
# ---------------------------------------------------------------------------
|
|
44
|
-
|
|
45
|
-
hazard_typer = typer.Typer(name="hazard", help="隐患相关命令", no_args_is_help=True)
|
|
46
|
-
hazard_task_typer = typer.Typer(name="task", help="隐患任务命令", no_args_is_help=True)
|
|
47
|
-
hazard_record_typer = typer.Typer(name="record", help="隐患记录命令", no_args_is_help=True)
|
|
48
|
-
hazard_typer.add_typer(hazard_task_typer)
|
|
49
|
-
hazard_typer.add_typer(hazard_record_typer)
|
|
50
|
-
|
|
51
|
-
console = Console(no_color=True)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# ---------------------------------------------------------------------------
|
|
55
|
-
# 公共工具
|
|
56
|
-
# ---------------------------------------------------------------------------
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def _parse_query_json(query: str | None) -> SqlQueryParam | None:
|
|
60
|
-
"""把 ``--query`` JSON 字符串解析为 SqlQueryParam。
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
query: JSON 字符串;为空时直接返回 ``None``。
|
|
64
|
-
"""
|
|
65
|
-
if not query:
|
|
66
|
-
return None
|
|
67
|
-
try:
|
|
68
|
-
data = json.loads(query)
|
|
69
|
-
except json.JSONDecodeError as e:
|
|
70
|
-
typer.echo(f"错误: --query 不是合法 JSON: {e}")
|
|
71
|
-
raise typer.Exit(code=2) from None
|
|
72
|
-
if not isinstance(data, dict):
|
|
73
|
-
typer.echo("错误: --query 必须是 JSON 对象")
|
|
74
|
-
raise typer.Exit(code=2) from None
|
|
75
|
-
return SqlQueryParam.model_validate(data)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def _make_page_param(page: int, size: int) -> PageParam:
|
|
79
|
-
return PageParam(start=page * size, limit=size)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def _print_dict_list(items: list[dict], columns: list[str] | None = None) -> None:
|
|
83
|
-
"""以 Rich 表格打印字典列表.
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
items: 记录列表.
|
|
87
|
-
columns: 指定展示的列;为空时使用首条记录的全部 keys.
|
|
88
|
-
"""
|
|
89
|
-
if not items:
|
|
90
|
-
console.print("(空)")
|
|
91
|
-
return
|
|
92
|
-
headers = columns or list(items[0].keys())
|
|
93
|
-
table = Table(*headers, show_header=True, header_style="bold")
|
|
94
|
-
for item in items:
|
|
95
|
-
row: list[Any] = []
|
|
96
|
-
for h in headers:
|
|
97
|
-
v = item.get(h)
|
|
98
|
-
if v is None:
|
|
99
|
-
row.append("")
|
|
100
|
-
elif isinstance(v, (dict, list)):
|
|
101
|
-
row.append(to_json(v).decode("utf-8"))
|
|
102
|
-
else:
|
|
103
|
-
row.append(str(v))
|
|
104
|
-
table.add_row(*row)
|
|
105
|
-
console.print(table)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
# ---------------------------------------------------------------------------
|
|
109
|
-
# 隐患任务子命令
|
|
110
|
-
# ---------------------------------------------------------------------------
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
@hazard_task_typer.command("trigger", no_args_is_help=True)
|
|
114
|
-
def trigger_hazard_task(
|
|
115
|
-
code: Annotated[str, typer.Argument(help="隐患任务编码")],
|
|
116
|
-
trigger_time: Annotated[
|
|
117
|
-
str | None,
|
|
118
|
-
typer.Option(
|
|
119
|
-
"--trigger-time",
|
|
120
|
-
help="ISO 时间字符串(如 2026-07-23T10:00:00);缺省为立即触发",
|
|
121
|
-
),
|
|
122
|
-
] = None,
|
|
123
|
-
sync: Annotated[
|
|
124
|
-
bool,
|
|
125
|
-
typer.Option("--sync", help="同步执行(默认通过 Job 模板异步执行)"),
|
|
126
|
-
] = False,
|
|
127
|
-
) -> None:
|
|
128
|
-
"""触发指定编码的隐患任务。
|
|
129
|
-
|
|
130
|
-
Args:
|
|
131
|
-
code: 隐患任务编码。
|
|
132
|
-
trigger_time: 可选 ISO 时间字符串,缺省时立即触发。
|
|
133
|
-
sync: 是否同步执行;默认通过 Job 模板异步执行。
|
|
134
|
-
|
|
135
|
-
Examples:
|
|
136
|
-
>>> data-ops-cli hazard task trigger task_hazard_001
|
|
137
|
-
>>> data-ops-cli hazard task trigger task_hazard_001 --sync
|
|
138
|
-
>>> data-ops-cli hazard task trigger task_hazard_001 \
|
|
139
|
-
... --trigger-time 2026-07-23T10:00:00
|
|
140
|
-
"""
|
|
141
|
-
parsed_time: datetime | None = None
|
|
142
|
-
if trigger_time:
|
|
143
|
-
try:
|
|
144
|
-
parsed_time = datetime.fromisoformat(trigger_time)
|
|
145
|
-
except ValueError as e:
|
|
146
|
-
typer.echo(f"错误: --trigger-time 不是合法 ISO 时间: {e}")
|
|
147
|
-
raise typer.Exit(code=2) from None
|
|
148
|
-
|
|
149
|
-
try:
|
|
150
|
-
ok = service_trigger_hazard_task(code, trigger_time=parsed_time, sync=sync)
|
|
151
|
-
except DataOpsError as e:
|
|
152
|
-
typer.echo(f"错误: {e.message}")
|
|
153
|
-
raise typer.Exit(code=1) from None
|
|
154
|
-
|
|
155
|
-
if ok:
|
|
156
|
-
console.print(f"已触发: {code}")
|
|
157
|
-
else:
|
|
158
|
-
typer.echo(f"触发失败: {code}")
|
|
159
|
-
raise typer.Exit(code=1) from None
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
@hazard_task_typer.command("logs", no_args_is_help=True)
|
|
163
|
-
def get_hazard_task_logs(
|
|
164
|
-
task_code: Annotated[str, typer.Argument(help="隐患任务编码")],
|
|
165
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", help="页码")] = 0,
|
|
166
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", help="每页大小")] = 20,
|
|
167
|
-
count: Annotated[bool, typer.Option("--count", help="只返回记录数")] = False,
|
|
168
|
-
) -> None:
|
|
169
|
-
"""获取隐患任务日志列表(按 ``START_TIME DESC`` 排序)。
|
|
170
|
-
|
|
171
|
-
Args:
|
|
172
|
-
task_code: 隐患任务编码。
|
|
173
|
-
page: 页码(从 0 开始)。
|
|
174
|
-
size: 每页条数。
|
|
175
|
-
count: 是否只返回记录数。
|
|
176
|
-
|
|
177
|
-
Examples:
|
|
178
|
-
>>> data-ops-cli hazard task logs task_hazard_001
|
|
179
|
-
>>> data-ops-cli hazard task logs task_hazard_001 --page-num 0 --page-size 50
|
|
180
|
-
>>> data-ops-cli hazard task logs task_hazard_001 --count
|
|
181
|
-
"""
|
|
182
|
-
try:
|
|
183
|
-
page_param = _make_page_param(page_num, page_size)
|
|
184
|
-
result = service_get_hazard_task_logs(task_code, page_param=page_param, count=count)
|
|
185
|
-
except DataOpsError as e:
|
|
186
|
-
typer.echo(f"错误: {e.message}")
|
|
187
|
-
raise typer.Exit(code=1) from None
|
|
188
|
-
|
|
189
|
-
if count:
|
|
190
|
-
console.print(f"记录数: {result}")
|
|
191
|
-
return
|
|
192
|
-
_print_dict_list(result)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
@hazard_task_typer.command("log-records", no_args_is_help=True)
|
|
196
|
-
def get_hazard_task_log_records(
|
|
197
|
-
task_id: Annotated[str, typer.Argument(help="隐患任务实例 ID")],
|
|
198
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", help="页码")] = 0,
|
|
199
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", help="每页大小")] = 20,
|
|
200
|
-
count: Annotated[bool, typer.Option("--count", help="只返回记录数")] = False,
|
|
201
|
-
) -> None:
|
|
202
|
-
"""获取隐患任务结果记录(按 ``CREATE_TIME DESC`` 排序)。
|
|
203
|
-
|
|
204
|
-
Args:
|
|
205
|
-
task_id: 隐患任务实例 ID。
|
|
206
|
-
page: 页码(从 0 开始)。
|
|
207
|
-
size: 每页条数。
|
|
208
|
-
count: 是否只返回记录数。
|
|
209
|
-
|
|
210
|
-
Examples:
|
|
211
|
-
>>> data-ops-cli hazard task log-records run_001
|
|
212
|
-
"""
|
|
213
|
-
try:
|
|
214
|
-
page_param = _make_page_param(page_num, page_size)
|
|
215
|
-
result = service_get_hazard_task_log_records(task_id, page_param=page_param, count=count)
|
|
216
|
-
except DataOpsError as e:
|
|
217
|
-
typer.echo(f"错误: {e.message}")
|
|
218
|
-
raise typer.Exit(code=1) from None
|
|
219
|
-
|
|
220
|
-
if count:
|
|
221
|
-
console.print(f"记录数: {result}")
|
|
222
|
-
return
|
|
223
|
-
_print_dict_list(result)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
# ---------------------------------------------------------------------------
|
|
227
|
-
# 隐患记录子命令
|
|
228
|
-
# ---------------------------------------------------------------------------
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
@hazard_record_typer.command("list", no_args_is_help=True)
|
|
232
|
-
def list_hazard_records(
|
|
233
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", help="页码")] = 0,
|
|
234
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", help="每页大小")] = 20,
|
|
235
|
-
query: Annotated[
|
|
236
|
-
str | None,
|
|
237
|
-
typer.Option(
|
|
238
|
-
"--query",
|
|
239
|
-
"-q",
|
|
240
|
-
help='SqlQueryParam JSON,如 \'{"conditionList":[{"name":"STATUS","value":1,"alias":"T0"}]}\'',
|
|
241
|
-
),
|
|
242
|
-
] = None,
|
|
243
|
-
count: Annotated[bool, typer.Option("--count", help="只返回记录数")] = False,
|
|
244
|
-
) -> None:
|
|
245
|
-
"""列出活动隐患记录。
|
|
246
|
-
|
|
247
|
-
Args:
|
|
248
|
-
page: 页码(从 0 开始)。
|
|
249
|
-
size: 每页条数。
|
|
250
|
-
query: SqlQueryParam JSON。
|
|
251
|
-
count: 是否只返回记录数。
|
|
252
|
-
|
|
253
|
-
Examples:
|
|
254
|
-
>>> data-ops-cli hazard record list
|
|
255
|
-
>>> data-ops-cli hazard record list -q '{"conditionList":[{"name":"STATUS","value":1,"alias":"T0"}]}'
|
|
256
|
-
>>> data-ops-cli hazard record list --count
|
|
257
|
-
"""
|
|
258
|
-
try:
|
|
259
|
-
query_param = _parse_query_json(query)
|
|
260
|
-
page_param = _make_page_param(page_num, page_size)
|
|
261
|
-
result = service_list_hazard_records(
|
|
262
|
-
page_param=page_param,
|
|
263
|
-
query_param=query_param,
|
|
264
|
-
count=count,
|
|
265
|
-
)
|
|
266
|
-
except DataOpsError as e:
|
|
267
|
-
typer.echo(f"错误: {e.message}")
|
|
268
|
-
raise typer.Exit(code=1) from None
|
|
269
|
-
|
|
270
|
-
if count:
|
|
271
|
-
console.print(f"记录数: {result}")
|
|
272
|
-
return
|
|
273
|
-
_print_dict_list(result)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
@hazard_record_typer.command("his-list", no_args_is_help=True)
|
|
277
|
-
def list_hazard_history_records(
|
|
278
|
-
page_num: Annotated[int, typer.Option("-n", "--page-num", help="页码")] = 0,
|
|
279
|
-
page_size: Annotated[int, typer.Option("-s", "--page-size", help="每页大小")] = 20,
|
|
280
|
-
query: Annotated[
|
|
281
|
-
str | None,
|
|
282
|
-
typer.Option("--query", "-q", help="SqlQueryParam JSON"),
|
|
283
|
-
] = None,
|
|
284
|
-
count: Annotated[bool, typer.Option("--count", help="只返回记录数")] = False,
|
|
285
|
-
) -> None:
|
|
286
|
-
"""列出归档隐患记录。
|
|
287
|
-
|
|
288
|
-
Args:
|
|
289
|
-
page: 页码(从 0 开始)。
|
|
290
|
-
size: 每页条数。
|
|
291
|
-
query: SqlQueryParam JSON。
|
|
292
|
-
count: 是否只返回记录数。
|
|
293
|
-
|
|
294
|
-
Examples:
|
|
295
|
-
>>> data-ops-cli hazard record his-list
|
|
296
|
-
>>> data-ops-cli hazard record his-list --count
|
|
297
|
-
"""
|
|
298
|
-
try:
|
|
299
|
-
query_param = _parse_query_json(query)
|
|
300
|
-
page_param = _make_page_param(page_num, page_size)
|
|
301
|
-
result = service_list_hazard_history_records(
|
|
302
|
-
page_param=page_param,
|
|
303
|
-
query_param=query_param,
|
|
304
|
-
count=count,
|
|
305
|
-
)
|
|
306
|
-
except DataOpsError as e:
|
|
307
|
-
typer.echo(f"错误: {e.message}")
|
|
308
|
-
raise typer.Exit(code=1) from None
|
|
309
|
-
|
|
310
|
-
if count:
|
|
311
|
-
console.print(f"记录数: {result}")
|
|
312
|
-
return
|
|
313
|
-
_print_dict_list(result)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
@hazard_record_typer.command("dispatch-callback", no_args_is_help=True)
|
|
317
|
-
def dispatch_callback(
|
|
318
|
-
cuid: Annotated[str, typer.Option("--cuid", help="隐患记录 ID")],
|
|
319
|
-
order_no: Annotated[str, typer.Option("--order-no", help="外部工单号")],
|
|
320
|
-
dispatch_status: Annotated[
|
|
321
|
-
int,
|
|
322
|
-
typer.Option("--status", help="派遣状态码(业务自行约定,如 1=成功/2=失败)"),
|
|
323
|
-
],
|
|
324
|
-
) -> None:
|
|
325
|
-
"""外部工单系统回写隐患派遣结果。
|
|
326
|
-
|
|
327
|
-
Args:
|
|
328
|
-
cuid: 隐患记录 ID。
|
|
329
|
-
order_no: 外部工单号。
|
|
330
|
-
dispatch_status: 派遣状态码。
|
|
331
|
-
|
|
332
|
-
Examples:
|
|
333
|
-
>>> data-ops-cli hazard record dispatch-callback \
|
|
334
|
-
... --cuid rec-123 --order-no WT-2026-001 --status 1
|
|
335
|
-
"""
|
|
336
|
-
try:
|
|
337
|
-
ok = service_dispatch_hazard_callback(cuid, order_no, dispatch_status)
|
|
338
|
-
except DataOpsError as e:
|
|
339
|
-
typer.echo(f"错误: {e.message}")
|
|
340
|
-
raise typer.Exit(code=1) from None
|
|
341
|
-
|
|
342
|
-
if ok:
|
|
343
|
-
console.print(f"回调成功: cuid={cuid} orderNo={order_no} status={dispatch_status}")
|
|
344
|
-
else:
|
|
345
|
-
typer.echo("回调失败: 活动隐患不存在")
|
|
346
|
-
raise typer.Exit(code=1) from None
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
@hazard_record_typer.command("his-clear", no_args_is_help=True)
|
|
350
|
-
def clear_hazard_history_records(
|
|
351
|
-
cuid: Annotated[str, typer.Option("--cuid", help="归档隐患记录 ID")],
|
|
352
|
-
clear_notify_status: Annotated[
|
|
353
|
-
int | None,
|
|
354
|
-
typer.Option("--notify-status", help="清除通知状态码"),
|
|
355
|
-
] = None,
|
|
356
|
-
) -> None:
|
|
357
|
-
"""清理指定归档隐患记录。
|
|
358
|
-
|
|
359
|
-
Args:
|
|
360
|
-
cuid: 归档隐患记录 ID。
|
|
361
|
-
clear_notify_status: 可选清除通知状态码。
|
|
362
|
-
|
|
363
|
-
Examples:
|
|
364
|
-
>>> data-ops-cli hazard record his-clear --cuid rec-archived-001
|
|
365
|
-
>>> data-ops-cli hazard record his-clear --cuid rec-archived-001 --notify-status 1
|
|
366
|
-
"""
|
|
367
|
-
try:
|
|
368
|
-
ok = service_clear_hazard_history_records(
|
|
369
|
-
cuid,
|
|
370
|
-
clear_notify_status=clear_notify_status,
|
|
371
|
-
)
|
|
372
|
-
except DataOpsError as e:
|
|
373
|
-
typer.echo(f"错误: {e.message}")
|
|
374
|
-
raise typer.Exit(code=1) from None
|
|
375
|
-
|
|
376
|
-
if ok:
|
|
377
|
-
console.print(f"已清除: {cuid}")
|
|
378
|
-
else:
|
|
379
|
-
typer.echo("清除失败: 归档隐患记录不存在")
|
|
380
|
-
raise typer.Exit(code=1) from None
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
# 兼容旧版 CLI(已弃用,保留直至 1.0)
|
|
384
|
-
__all__ = ["hazard_typer"]
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
# 旧接口(已弃用)的 stub,避免破坏外部 import
|
|
388
|
-
def _safe_str(value: Any) -> str:
|
|
389
|
-
if value is None:
|
|
390
|
-
return ""
|
|
391
|
-
if isinstance(value, (dict, list)):
|
|
392
|
-
return to_json(value).decode("utf-8")
|
|
393
|
-
return str(value)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
# 兼容旧版 ``print_list`` 风格的快速打印
|
|
397
|
-
def _legacy_print_dict_list(items: list) -> None:
|
|
398
|
-
if not items:
|
|
399
|
-
print("(空)")
|
|
400
|
-
return
|
|
401
|
-
if isinstance(items[0], dict):
|
|
402
|
-
headers = list(items[0].keys())
|
|
403
|
-
rows = [[_safe_str(item.get(h)) for h in headers] for item in items]
|
|
404
|
-
print_list(headers, rows)
|
|
405
|
-
else:
|
|
406
|
-
print(to_json(items).decode("utf-8"))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|