Skip to content

Commit cb08b25

Browse files
committed
docs: add Chinese README
1 parent 0554b36 commit cb08b25

2 files changed

Lines changed: 342 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Apollo CLI
22

3+
[中文](README.zh.md)
4+
35
`apollo-cli` is the standalone Rust repository for the `apollo` command-line interface.
46

57
This repository currently covers the first Apollo CLI v0 slices:

README.zh.md

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
# Apollo CLI
2+
3+
[English](README.md)
4+
5+
`apollo-cli``apollo` 命令行工具的独立 Rust 仓库。
6+
7+
当前仓库覆盖 Apollo CLI v0 的第一批能力:
8+
9+
- 顶层 v0 命令路由
10+
- 全局参数解析
11+
- 输出格式化基础
12+
- 非敏感 profile 配置
13+
- 运行时上下文解析
14+
- 凭据存储抽象和 auth 命令
15+
- 保守的脱敏基础能力
16+
- `/openapi/v1/*` 下的代表性 Apollo Portal OpenAPI 调用
17+
- 通过 `apollo api` 透传原始 OpenAPI 请求
18+
- 变更类命令的确认保护
19+
- 本地开发流程和 CI 入口
20+
21+
这个包刻意保持自包含、可移动。它当前位于这个独立仓库中便于评审,但不会假设仓库特有环境,因此后续可以在不修改 Apollo 服务端的情况下拆分、vendored 或重新发布 crate。
22+
23+
本阶段不实现生成式 OpenAPI SDK 绑定、agent session、MCP 或服务端 schema 变更。
24+
25+
## 命令分组
26+
27+
- `auth`
28+
- `profile`
29+
- `app`
30+
- `env`
31+
- `namespace`
32+
- `config`
33+
- `release`
34+
- `api`
35+
36+
代表性的 v0 命令:
37+
38+
```bash
39+
apollo init
40+
apollo profile add dev
41+
apollo profile add prod --use
42+
apollo app list
43+
apollo app get sample-app
44+
apollo env list --app sample-app
45+
apollo namespace list --env DEV --app sample-app
46+
apollo namespace get --env DEV --app sample-app application
47+
apollo namespace create --env DEV --app sample-app application --comment "app settings" --yes
48+
apollo config list --env DEV --app sample-app
49+
apollo config get --env DEV --app sample-app timeout
50+
apollo config set --env DEV --app sample-app timeout 3000 --type 1 --yes
51+
apollo config delete --env DEV --app sample-app timeout --yes
52+
apollo config diff --env DEV --app sample-app --target-env FAT
53+
apollo config apply --env DEV --app sample-app --target-env FAT --yes
54+
apollo release list --env DEV --app sample-app
55+
apollo release create --env DEV --app sample-app --title "release title" --yes
56+
apollo release rollback --env DEV 123 --yes
57+
apollo api get /openapi/v1/apps
58+
apollo api post /openapi/v1/apps --body '{"app":{"appId":"sample-app"}}' --yes
59+
```
60+
61+
这些命令只使用已有的 Apollo Portal OpenAPI 端点。CLI 有意不使用已废弃的 Portal WebAPI 端点。
62+
63+
`apollo namespace create` 会先注册 AppNamespace,再在指定环境和 cluster 中创建 namespace。默认创建私有 AppNamespace。只有在 namespace 应该是公共 namespace 时才传 `--public`。文件类型 namespace 会根据 `.json``.yml``.yaml``.xml` 后缀推断格式;其他名称默认使用 `properties``--comment` 会存储在 AppNamespace 上。公共 AppNamespace 注册会发送 Apollo 的 `appendNamespacePrefix=true` 默认值;如果 namespace 名称必须按原样存储、不使用 Apollo 的公共 namespace 前缀行为,请传 `--no-append-namespace-prefix`
64+
65+
`apollo config set` 会发送 Apollo 的 `OpenItemDTO.type` 字段。默认值为 `0`,表示字符串配置项。Apollo Portal 还使用 `1` 表示数字、`2` 表示布尔值、`3` 表示 JSON;这些值会在发送 OpenAPI 请求前由客户端校验。
66+
67+
## 全局参数
68+
69+
当前脚手架会在子命令之前解析以下全局参数:
70+
71+
- `--profile`
72+
- `--server`
73+
- `--output json|table`
74+
- `--yes`
75+
76+
## 引导式初始化
77+
78+
首次使用时推荐执行 `apollo init`。它会创建 profile,将非敏感 profile 元数据写入 `config.toml`,并且可以通过凭据存储抽象保存 Apollo OpenAPI token。
79+
80+
对于支持 Portal 用户访问 token 的 Apollo 版本,交互式用户、AI agent 和个人自动化推荐使用 user-token 鉴权模式。
81+
82+
本地 Apollo assembly 测试示例:
83+
84+
```bash
85+
apollo --output json init --store-token-in-file
86+
apollo profile show
87+
apollo env list --app sample-app
88+
```
89+
90+
默认情况下,`apollo init` 会创建一个 `local` profile:
91+
92+
- `server = "http://127.0.0.1:8070"`
93+
- 除非显式传入 `--output`,否则不持久化 `output`
94+
- `auth_mode = "user-token"`
95+
- 不配置 `operator`;user-token OpenAPI 请求使用 token 所属用户作为操作人
96+
- `active_profile = "local"`
97+
98+
可以用 `apollo profile add` 增加更多环境,避免手工编辑配置:
99+
100+
```bash
101+
printf '%s\n' "$DEV_TOKEN" | apollo \
102+
--server https://apollo-dev.example.com \
103+
--output json \
104+
profile add dev \
105+
--token-stdin
106+
107+
apollo profile add prod --server https://apollo-prod.example.com --use
108+
apollo profile add legacy --server https://apollo-legacy.example.com --auth-mode consumer-token --operator alice
109+
```
110+
111+
`profile add` 默认不会切换 active profile。如果新建 profile 应该立刻成为 active profile,请传 `--use`。已有 profile 会受到误替换保护;如果确实要替换,请传 `--overwrite`
112+
113+
## Profile 配置
114+
115+
CLI 将非敏感 profile 元数据存储在操作系统配置目录下的 `config.toml` 中:
116+
117+
- macOS:`~/Library/Application Support/apollo/config.toml`
118+
- Linux:`$XDG_CONFIG_HOME/apollo/config.toml``~/.config/apollo/config.toml`
119+
- Windows:`%APPDATA%\apollo\config.toml`
120+
121+
配置文件会存储:
122+
123+
- `active_profile`
124+
- profile 名称
125+
- profile `server`
126+
- profile `output`
127+
- profile `auth_mode`,取值为 `user-token``consumer-token`
128+
- 可选 `operator`
129+
- 可选凭据查找元数据,例如 backend/key 名称
130+
131+
Token 不属于受支持的配置 schema,CLI 有意不把 token 放进这里。建议使用 `apollo init``apollo profile add``apollo auth login`,而不是手工编辑这个文件。
132+
133+
如果缺少 `auth_mode`,CLI 会把该 profile 当作 `consumer-token` 处理,以兼容已有配置。
134+
135+
示例:
136+
137+
```toml
138+
active_profile = "dev"
139+
140+
[profiles.dev]
141+
server = "https://apollo-dev.example.com"
142+
output = "table"
143+
auth_mode = "user-token"
144+
145+
[profiles.dev.credential]
146+
backend = "native"
147+
key = "dev"
148+
```
149+
150+
## Profile 命令
151+
152+
- `apollo init`
153+
- `apollo profile add [name]`
154+
- `apollo profile list`
155+
- `apollo profile show`
156+
- `apollo profile use <name>`
157+
158+
运行时上下文按以下顺序解析:
159+
160+
1. 显式参数,例如 `--profile``--server``--output`
161+
2. 环境变量,例如 `APOLLO_PROFILE``APOLLO_SERVER``APOLLO_OUTPUT`
162+
3. active profile 配置
163+
4. 命令默认值
164+
165+
## Auth 命令
166+
167+
- `apollo auth login`
168+
- `apollo auth login --token-stdin`
169+
- `apollo auth login --token-stdin --store-token-in-file`
170+
- `apollo auth status`
171+
- `apollo auth whoami`
172+
- `apollo auth capabilities`
173+
- `apollo auth logout`
174+
175+
凭据存储使用内部 store 抽象,包含以下逻辑 provider:
176+
177+
- `native`:默认凭据后端,通过 Rust `keyring` crate 使用操作系统凭据存储
178+
- `env`:通过 `APOLLO_TOKEN` 提供只读的 CI/headless provider
179+
- `file`:只有显式传 `--store-token-in-file` 时才启用的文件回退
180+
- 用于单元测试的内存 provider
181+
182+
Native 后端选择遵循底层操作系统凭据存储行为:
183+
184+
- macOS:Keychain Services
185+
- Windows:Credential Manager
186+
- Linux desktop:兼容 freedesktop Secret Service 的 provider
187+
- Linux headless/CI:使用 `APOLLO_TOKEN`,或显式选择文件回退
188+
189+
文件回退会把 token material 写到 `config.toml` 之外的 CLI 凭据目录中,并在 Unix 上使用受限文件权限。Profile 配置只存储非敏感凭据查找元数据。
190+
191+
OpenAPI 命令支持两种 token 模式:
192+
193+
- `user-token`:推荐用于交互式用户、AI agent 和本地自动化。Token 以 `apollo_pat_` 开头,并以 `Authorization: Bearer <token>` 形式发送。
194+
- `consumer-token`:用于兼容已有集成和旧版本 Apollo 部署。Token 会作为原始 `Authorization: <token>` header 值发送。
195+
196+
`apollo init``apollo profile add` 默认使用 `user-token`。配置旧版 consumer-token 凭据时请使用 `--auth-mode consumer-token`。变更类命令只在 `consumer-token` 模式下要求配置 `operator`;user-token 请求会使用所属 Portal 用户。
197+
198+
`apollo env list``apollo namespace list``apollo namespace get``apollo config get``apollo config list``apollo config diff``apollo config apply` 会读取 env、namespace 或配置项数据,这些数据的授权范围可能比 app 更窄。请在这些命令中使用 `user-token` 模式。旧版 `consumer-token` 模式无法从可用的 `/openapi/v1/apps/authorized` 响应中安全校验 env/namespace 级读取范围,因此 CLI 会拒绝这些 scoped-read 工作流,而不是只依赖 app 级可见性。
199+
200+
本地或 CI 使用时,`APOLLO_TOKEN` 优先级最高,并且永远不会写入磁盘:
201+
202+
```bash
203+
APOLLO_TOKEN="$TOKEN" apollo --server http://localhost:8070 app list --output json
204+
```
205+
206+
`APOLLO_TOKEN``apollo_pat_` 开头时,CLI 会自动将其视为 `user-token`;否则使用 `consumer-token` 兼容模式。
207+
208+
`apollo auth logout` 会删除所选 profile 引用的凭据。它不能从父 shell 环境中删除 `APOLLO_TOKEN`。如果 `APOLLO_TOKEN` 仍然存在,logout 会提示环境凭据仍会继续生效;执行 `unset APOLLO_TOKEN` 可以禁用这个临时凭据。
209+
210+
交互式使用时,先配置 profile,再用隐藏输入保存 token:
211+
212+
```bash
213+
apollo --profile dev auth login
214+
apollo --profile dev app list
215+
```
216+
217+
`auth login` 默认把 token 存到操作系统凭据存储。如果 native store 在交互式终端中不可用,CLI 会询问是否改用本地文件回退。
218+
219+
脚本或手工粘贴并回车的场景下,`--token-stdin` 会读取一行 token:
220+
221+
```bash
222+
printf '%s\n' "$TOKEN" | apollo --profile dev auth login --token-stdin
223+
apollo --profile dev auth login --token-stdin
224+
printf '%s\n' "$LEGACY_CONSUMER_TOKEN" | apollo --profile legacy auth login --auth-mode consumer-token --token-stdin
225+
```
226+
227+
登录后可使用 user-token 自检命令:
228+
229+
```bash
230+
apollo --profile dev auth whoami
231+
apollo --profile dev auth capabilities
232+
```
233+
234+
这些命令会调用 `/openapi/v1/user-tokens/current``/openapi/v1/user-tokens/current/capabilities`。它们要求使用 `user-token` 鉴权模式,并且不会创建、轮转或撤销 token;用户 token 的创建仍然是 Portal 自助流程。
235+
236+
## 脱敏和错误
237+
238+
输出层会在渲染前对人类可读输出和 JSON 输出应用保守脱敏。类 token 字段、`Authorization: Bearer ...` header 和 `consumer token ...` 文本都会渲染为 `[REDACTED]`
239+
240+
结构化 JSON 错误包含:
241+
242+
- `code`:稳定错误码
243+
- `category`:稳定错误分类
244+
- `message`:人类可读错误信息
245+
- 可选的非敏感详情,例如 `command``profile``path``follow_up_issue`
246+
247+
当前错误分类:
248+
249+
- `authentication_failed`
250+
- `permission_denied`
251+
- `invalid_input`
252+
- `not_found`
253+
- `conflict`
254+
- `precondition_failed`
255+
- `network`
256+
- `server`
257+
- `confirmation_required`
258+
- `unsupported_operation`
259+
260+
## OpenAPI 行为
261+
262+
第一版 v0 实现使用一个小型通用 HTTP client,而不是生成式 SDK。这样可以让 CLI 与 Apollo 服务端仓库解耦,同时仍然保证所有内置资源命令都限定在 `/openapi/v1/*`
263+
264+
路径和 payload 映射遵循当前 Apollo Portal OpenAPI contract,包括:
265+
266+
- `GET /openapi/v1/apps`
267+
- `GET /openapi/v1/envs`
268+
- `GET /openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces`
269+
- `GET|PUT|DELETE /openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key}`
270+
- `POST /openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/diff`
271+
- `POST /openapi/v1/apps/{appId}/appnamespaces` 用于 AppNamespace 注册
272+
- `POST /openapi/v1/namespaces`
273+
- `POST /openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/synchronize`
274+
- `GET /openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active`
275+
- `POST /openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases`
276+
- `PUT /openapi/v1/envs/{env}/releases/{releaseId}/rollback`
277+
278+
变更类命令要求传 `--yes`。如果没有传,CLI 会在建立网络连接之前返回 `confirmation_required`
279+
280+
## 本地开发
281+
282+
构建 CLI:
283+
284+
```bash
285+
cargo build
286+
```
287+
288+
运行 help 输出:
289+
290+
```bash
291+
cargo run -- --help
292+
```
293+
294+
运行测试:
295+
296+
```bash
297+
cargo test
298+
```
299+
300+
使用本地 mock HTTP server 运行聚焦的 OpenAPI 命令集成测试:
301+
302+
```bash
303+
cargo test --test openapi
304+
```
305+
306+
如果本地运行了 Apollo Portal,也可以直接对它做 smoke test:
307+
308+
```bash
309+
APOLLO_TOKEN="$TOKEN" cargo run -- --server http://localhost:8070 --output json env list --app sample-app
310+
APOLLO_TOKEN="$TOKEN" cargo run -- --server http://localhost:8070 --output json app list
311+
APOLLO_TOKEN="$USER_TOKEN" cargo run -- --server http://localhost:8070 --output json auth whoami
312+
```
313+
314+
格式化仓库:
315+
316+
```bash
317+
cargo fmt
318+
```
319+
320+
运行 lint:
321+
322+
```bash
323+
cargo clippy --all-targets --all-features -- -D warnings
324+
```
325+
326+
## 仓库结构
327+
328+
- `src/cli.rs`:CLI 定义和参数解析
329+
- `src/config.rs`:profile 配置加载、保存和上下文解析
330+
- `src/command.rs`:顶层命令路由
331+
- `src/credential.rs`:凭据存储抽象和 provider
332+
- `src/error.rs`:结构化 CLI 错误模型
333+
- `src/http.rs`:通用 OpenAPI HTTP client 和路径 helper
334+
- `src/output.rs`:输出渲染抽象
335+
- `src/redaction.rs`:保守脱敏工具
336+
- `tests/auth.rs`:auth 命令和凭据行为的集成覆盖
337+
- `tests/cli.rs`:help、参数和结构化错误的集成覆盖
338+
- `tests/openapi.rs`:OpenAPI path、鉴权 header 和确认保护的集成覆盖
339+
- `tests/profile.rs`:profile 命令和上下文解析的集成覆盖
340+
- `tests/redaction.rs`:脱敏行为的集成覆盖

0 commit comments

Comments
 (0)