移除 --auth-context,改为 --auth-stdin,结构化传递解析认证信息
This commit is contained in:
@@ -58,8 +58,8 @@ def simulation_run(
|
||||
require_auth=True,
|
||||
require_network_ctx=True,
|
||||
next_commands=[
|
||||
f"tjwater-cli --auth-context auth.json data timeseries realtime links --start-time {parsed.isoformat()} --end-time {end_time}",
|
||||
f"tjwater-cli --auth-context auth.json data timeseries realtime nodes --start-time {parsed.isoformat()} --end-time {end_time}",
|
||||
f"tjwater-cli data timeseries realtime links --start-time {parsed.isoformat()} --end-time {end_time}",
|
||||
f"tjwater-cli data timeseries realtime nodes --start-time {parsed.isoformat()} --end-time {end_time}",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -92,8 +92,8 @@ def analysis_burst(
|
||||
require_auth=True,
|
||||
require_network_ctx=True,
|
||||
next_commands=[
|
||||
f"tjwater-cli --auth-context auth.json data scheme get --name {scheme_name}",
|
||||
"tjwater-cli --auth-context auth.json data scheme list",
|
||||
f"tjwater-cli data scheme get --name {scheme_name}",
|
||||
"tjwater-cli data scheme list",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import typer
|
||||
@@ -12,7 +11,7 @@ def runtime_context(ctx: typer.Context):
|
||||
obj = ctx.obj or {}
|
||||
return build_runtime_context(
|
||||
server=obj.get("server"),
|
||||
auth_context_path=obj.get("auth_context"),
|
||||
auth_stdin=obj.get("auth_stdin", False),
|
||||
scheme=obj.get("scheme"),
|
||||
timeout=obj.get("timeout", DEFAULT_TIMEOUT),
|
||||
request_id=obj.get("request_id"),
|
||||
|
||||
+10
-29
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
from dataclasses import dataclass, field
|
||||
@@ -80,25 +81,6 @@ class CommandDoc:
|
||||
output: str = "标准 JSON 输出"
|
||||
|
||||
|
||||
def _read_json_file(path: Path) -> dict[str, Any]:
|
||||
try:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
except FileNotFoundError as exc:
|
||||
raise CLIError(
|
||||
"认证失败",
|
||||
code="AUTH_CONTEXT_NOT_FOUND",
|
||||
message=f"auth context file not found: {path}",
|
||||
exit_code=3,
|
||||
) from exc
|
||||
except json.JSONDecodeError as exc:
|
||||
raise CLIError(
|
||||
"认证失败",
|
||||
code="AUTH_CONTEXT_INVALID",
|
||||
message=f"auth context file is not valid JSON: {path}",
|
||||
exit_code=3,
|
||||
) from exc
|
||||
|
||||
|
||||
def _pick(mapping: Mapping[str, Any], *keys: str) -> Any:
|
||||
for key in keys:
|
||||
value = mapping.get(key)
|
||||
@@ -107,10 +89,9 @@ def _pick(mapping: Mapping[str, Any], *keys: str) -> Any:
|
||||
return None
|
||||
|
||||
|
||||
def load_auth_context(auth_context_path: Path | None) -> AuthContext:
|
||||
raw: dict[str, Any] = {}
|
||||
if auth_context_path is not None:
|
||||
raw = _read_json_file(auth_context_path)
|
||||
def load_auth_context(auth_stdin: bool = False) -> AuthContext:
|
||||
if auth_stdin:
|
||||
raw = json.loads(sys.stdin.read())
|
||||
else:
|
||||
extra_headers = os.getenv("TJWATER_EXTRA_HEADERS")
|
||||
raw = {
|
||||
@@ -146,12 +127,12 @@ def load_auth_context(auth_context_path: Path | None) -> AuthContext:
|
||||
def build_runtime_context(
|
||||
*,
|
||||
server: str | None,
|
||||
auth_context_path: Path | None,
|
||||
auth_stdin: bool = False,
|
||||
scheme: str | None,
|
||||
timeout: int,
|
||||
request_id: str | None,
|
||||
) -> RuntimeContext:
|
||||
auth = load_auth_context(auth_context_path)
|
||||
auth = load_auth_context(auth_stdin=auth_stdin)
|
||||
resolved_request_id = request_id or str(uuid.uuid4())
|
||||
return RuntimeContext(
|
||||
server=server or auth.server or DEFAULT_SERVER,
|
||||
@@ -181,7 +162,7 @@ def require_access_token(ctx: RuntimeContext) -> str:
|
||||
code="UNAUTHENTICATED",
|
||||
message="missing access token for agent context",
|
||||
exit_code=3,
|
||||
next_commands=["tjwater-cli <command> --auth-context /path/to/auth-context.json"],
|
||||
next_commands=["provide access_token via --auth-stdin or TJWATER_ACCESS_TOKEN env var"],
|
||||
)
|
||||
|
||||
|
||||
@@ -193,7 +174,7 @@ def require_project_id(ctx: RuntimeContext) -> str:
|
||||
code="PROJECT_CONTEXT_REQUIRED",
|
||||
message="missing project_id for agent context",
|
||||
exit_code=3,
|
||||
next_commands=["add project_id to the auth context file"],
|
||||
next_commands=["add project_id to auth context"],
|
||||
)
|
||||
|
||||
|
||||
@@ -205,7 +186,7 @@ def require_network(ctx: RuntimeContext) -> str:
|
||||
code="NETWORK_CONTEXT_REQUIRED",
|
||||
message="missing network in auth context for legacy network-based endpoints",
|
||||
exit_code=3,
|
||||
next_commands=["add network to the auth context file"],
|
||||
next_commands=["add network to auth context"],
|
||||
)
|
||||
|
||||
|
||||
@@ -217,7 +198,7 @@ def require_username(ctx: RuntimeContext) -> str:
|
||||
code="USERNAME_CONTEXT_REQUIRED",
|
||||
message="missing username in auth context",
|
||||
exit_code=3,
|
||||
next_commands=["add username to the auth context file"],
|
||||
next_commands=["add username to auth context"],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -161,11 +161,10 @@ def _build_example(path: tuple[str, ...], *, existing_examples: list[str] | None
|
||||
]
|
||||
if existing_examples:
|
||||
for example in existing_examples:
|
||||
has_auth = "--auth-context" in example
|
||||
has_required_options = all(f"--{option_name}" in example for option_name in required_option_names)
|
||||
if has_auth and has_required_options:
|
||||
if has_required_options:
|
||||
return example
|
||||
parts = ["tjwater-cli", "--auth-context", "auth.json", *path]
|
||||
parts = ["tjwater-cli", *path]
|
||||
if ctx is None:
|
||||
return " ".join(parts)
|
||||
for parameter in ctx.command.params:
|
||||
|
||||
@@ -27,14 +27,14 @@ from .helping import (
|
||||
def root_callback(
|
||||
ctx: typer.Context,
|
||||
server: Annotated[str | None, typer.Option("--server", help=f"服务端地址,默认 {DEFAULT_SERVER}")] = None,
|
||||
auth_context: Annotated[Path | None, typer.Option("--auth-context", help="认证上下文 JSON 文件")] = None,
|
||||
auth_stdin: Annotated[bool, typer.Option("--auth-stdin", help="从标准输入读取认证上下文 JSON")] = False,
|
||||
scheme: Annotated[str | None, typer.Option("--scheme", help="全局方案标识")] = None,
|
||||
timeout: Annotated[int, typer.Option("--timeout", help="请求超时秒数")] = DEFAULT_TIMEOUT,
|
||||
request_id: Annotated[str | None, typer.Option("--request-id", help="显式请求 ID")] = None,
|
||||
) -> None:
|
||||
ctx.obj = {
|
||||
"server": server,
|
||||
"auth_context": auth_context,
|
||||
"auth_stdin": auth_stdin,
|
||||
"scheme": scheme,
|
||||
"timeout": timeout,
|
||||
"request_id": request_id,
|
||||
|
||||
+19
-17
@@ -39,15 +39,14 @@ COMMAND_DOCS: dict[tuple[str, ...], CommandDoc] = {
|
||||
path=("project", "list"),
|
||||
summary="列出当前用户可访问项目",
|
||||
description="调用 /meta/projects 返回项目列表。",
|
||||
examples=("tjwater-cli --auth-context auth.json project list",),
|
||||
next_commands=("tjwater-cli --auth-context auth.json project info",),
|
||||
output="项目摘要列表",
|
||||
examples=("tjwater-cli project list",),
|
||||
next_commands=("tjwater-cli project info",),
|
||||
),
|
||||
("project", "info"): CommandDoc(
|
||||
path=("project", "info"),
|
||||
summary="读取当前项目元数据",
|
||||
description="调用 /meta/project 返回当前 project 详情。",
|
||||
examples=("tjwater-cli --auth-context auth.json project info",),
|
||||
summary="查看当前项目摘要信息。",
|
||||
description="查看当前项目的基础信息。",
|
||||
examples=("tjwater-cli project info",),
|
||||
output="项目元数据",
|
||||
),
|
||||
("project", "db-health"): CommandDoc(
|
||||
@@ -109,8 +108,8 @@ COMMAND_DOCS: dict[tuple[str, ...], CommandDoc] = {
|
||||
CommandOptionDoc("duration", "持续分钟数", required=True),
|
||||
),
|
||||
next_commands=(
|
||||
"tjwater-cli --auth-context auth.json data timeseries realtime links --start-time 2025-01-02T03:04:05+08:00 --end-time 2025-01-02T03:34:05+08:00",
|
||||
"tjwater-cli --auth-context auth.json data timeseries realtime nodes --start-time 2025-01-02T03:04:05+08:00 --end-time 2025-01-02T03:34:05+08:00",
|
||||
"tjwater-cli data timeseries realtime links --start-time 2025-01-02T03:04:05+08:00 --end-time 2025-01-02T03:34:05+08:00",
|
||||
"tjwater-cli data timeseries realtime nodes --start-time 2025-01-02T03:04:05+08:00 --end-time 2025-01-02T03:34:05+08:00",
|
||||
),
|
||||
output="模拟触发结果;实时数据需通过 data timeseries 命令按时间段查询",
|
||||
),
|
||||
@@ -125,20 +124,23 @@ COMMAND_DOCS: dict[tuple[str, ...], CommandDoc] = {
|
||||
CommandOptionDoc("scheme", "方案名称"),
|
||||
),
|
||||
examples=(
|
||||
"tjwater-cli --auth-context auth.json analysis burst --start-time 2025-01-02T03:04:05+08:00 --duration 30 --burst-file ./burst.json --scheme burst_case_01",
|
||||
"tjwater-cli analysis burst --start-time 2025-01-02T03:04:05+08:00 --duration 30 --burst-file ./burst.json --scheme burst_case_01",
|
||||
"tjwater-cli data scheme get --name burst_case_01",
|
||||
"tjwater-cli data scheme list",
|
||||
),
|
||||
next_commands=(
|
||||
"tjwater-cli --auth-context auth.json data scheme get --name burst_case_01",
|
||||
"tjwater-cli --auth-context auth.json data scheme list",
|
||||
),
|
||||
output="分析执行结果;方案详情需通过 data scheme 命令单独查询",
|
||||
),
|
||||
("analysis", "valve"): CommandDoc(
|
||||
path=("analysis", "valve"),
|
||||
summary="执行阀门关闭或隔离分析",
|
||||
description="mode=close 使用 valve 列表;mode=isolation 需要 accident element,可选 disabled-valve。",
|
||||
summary="阀门工况分析。",
|
||||
description="指定阀门采取关闭/开启等操作逻辑,并执行定时长模拟。结果写入时序库。",
|
||||
options=(
|
||||
CommandOptionDoc(name="mode", description="阀门操作模式:'close' 或 'open'", required=True),
|
||||
CommandOptionDoc(name="start-time", description="起始绝对时间,必须显式带时区偏移", required=True),
|
||||
CommandOptionDoc(name="valve", description="阀门 ID(可多次指定)", required=True, repeated=True),
|
||||
CommandOptionDoc(name="duration", description="模拟持续分钟数", required=True),
|
||||
),
|
||||
examples=(
|
||||
"tjwater-cli --auth-context auth.json analysis valve --mode close --start-time 2025-01-02T03:04:05+08:00 --valve V1 --duration 900",
|
||||
"tjwater-cli analysis valve --mode close --start-time 2025-01-02T03:04:05+08:00 --valve V1 --duration 900",
|
||||
),
|
||||
),
|
||||
("analysis", "flushing"): CommandDoc(
|
||||
|
||||
Reference in New Issue
Block a user