@newbeebox/newbeebox-app-engine-cli 1.1.0 → 1.3.0
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.
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/index.js +74 -2
package/README.md
CHANGED
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// nae —— NewBee App Engine 命令行客户端。
|
|
3
3
|
// 设计:薄壳。每条命令只做「取配置 → 调一个 HTTP 原语 → JSON 出 stdout」,
|
|
4
4
|
// 鉴权/网络/业务错误集中在 run() 归类处理,命令体里不写 try/catch。
|
|
5
|
+
import { readFileSync } from 'fs'
|
|
5
6
|
import { Command } from 'commander'
|
|
6
7
|
import { load, save, configPath } from './config.js'
|
|
7
8
|
import { request, AuthError, NetworkError } from './http.js'
|
|
@@ -14,7 +15,7 @@ const program = new Command()
|
|
|
14
15
|
program
|
|
15
16
|
.name('nae')
|
|
16
17
|
.description('NewBee App Engine CLI —— 默认人类可读,-o json 输出 JSON 供脚本解析')
|
|
17
|
-
.version('1.
|
|
18
|
+
.version('1.3.0')
|
|
18
19
|
.option('--base-url <url>', '覆盖平台地址(也可用环境变量 NAE_BASE_URL)')
|
|
19
20
|
.option('--token <token>', '覆盖访问密钥(也可用环境变量 NAE_TOKEN)')
|
|
20
21
|
.option('-o, --output <format>', '输出格式:text(默认,人类可读)| json', 'text')
|
|
@@ -72,6 +73,25 @@ function parseJSONArg(label, s) {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
// 环境变量来源:--env-file 优先(从文件读 JSON,绕开 shell 引号),否则 --env 内联 JSON。
|
|
77
|
+
// 两者都没给返回 undefined(create 表示不带 env / update 表示不改 env)。
|
|
78
|
+
function envFromOpts(opts) {
|
|
79
|
+
if (opts.envFile !== undefined) {
|
|
80
|
+
let raw
|
|
81
|
+
try {
|
|
82
|
+
raw = readFileSync(opts.envFile, 'utf8')
|
|
83
|
+
} catch (e) {
|
|
84
|
+
throw new Error(`--env-file 读取失败:${opts.envFile}(${e.message})`)
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(raw)
|
|
88
|
+
} catch {
|
|
89
|
+
throw new Error(`--env-file 内容不是合法 JSON:${opts.envFile}`)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return parseJSONArg('--env', opts.env)
|
|
93
|
+
}
|
|
94
|
+
|
|
75
95
|
// --- 认证 ---
|
|
76
96
|
|
|
77
97
|
program
|
|
@@ -129,6 +149,15 @@ program
|
|
|
129
149
|
})
|
|
130
150
|
)
|
|
131
151
|
|
|
152
|
+
program
|
|
153
|
+
.command('llm')
|
|
154
|
+
.description('查询内置 LLM 网关状态:月度额度/本月用量/令牌前缀/内置环境变量名/按模型用量明细')
|
|
155
|
+
.action(
|
|
156
|
+
run(async () => {
|
|
157
|
+
emit(await request(cfg(), 'GET', '/me/llm'))
|
|
158
|
+
})
|
|
159
|
+
)
|
|
160
|
+
|
|
132
161
|
// --- 应用 ---
|
|
133
162
|
|
|
134
163
|
program
|
|
@@ -174,6 +203,7 @@ program
|
|
|
174
203
|
.option('--storage <size>', '模板应用:持久卷大小,如 10Gi')
|
|
175
204
|
.option('--replicas <n>', '副本数', (v) => parseInt(v, 10))
|
|
176
205
|
.option('--env <json>', '环境变量 JSON,如 \'{"KEY":"val"}\'')
|
|
206
|
+
.option('--env-file <path>', '从文件读环境变量 JSON(绕开 Windows PowerShell 引号问题;与 --env 二选一,优先 --env-file)')
|
|
177
207
|
.option(
|
|
178
208
|
'--config <json>',
|
|
179
209
|
"模板应用的服务特性参数 JSON。可用字段随模板而定,运行 'nae templates' 看每个模板的 ConfigSchema(key/类型/默认值/可选项)。redis: {\"password\",\"persistence\":\"rdb|aof|none\"};postgres: {\"database\",\"username\",\"password\"};milvus: {\"root_password\"}"
|
|
@@ -217,7 +247,7 @@ program
|
|
|
217
247
|
template_key: opts.template,
|
|
218
248
|
storage_size: opts.storage,
|
|
219
249
|
replicas: opts.replicas,
|
|
220
|
-
env:
|
|
250
|
+
env: envFromOpts(opts),
|
|
221
251
|
config: parseJSONArg('--config', opts.config),
|
|
222
252
|
owner_id: opts.owner,
|
|
223
253
|
}
|
|
@@ -225,6 +255,48 @@ program
|
|
|
225
255
|
})
|
|
226
256
|
)
|
|
227
257
|
|
|
258
|
+
program
|
|
259
|
+
.command('update <appid>')
|
|
260
|
+
.description(
|
|
261
|
+
'修改应用配置(端口/资源/env/跟踪tag/重启上限/路由前缀)。读-改-写:只覆盖你传的字段,其余保持不变。改后需 restart(运行中)或下次 start 才生效。env/端口/tag/前缀仅普通应用可改;AppID/类型/归属/存储/模板不可改(需删除重建)'
|
|
262
|
+
)
|
|
263
|
+
.option('--port <n>', '容器端口(仅普通应用)', (v) => parseInt(v, 10))
|
|
264
|
+
.option('--cpu <limit>', 'CPU 上限,如 1 / 500m')
|
|
265
|
+
.option('--mem <limit>', '内存上限,如 512Mi / 1Gi')
|
|
266
|
+
.option('--tag <tag>', '跟踪的镜像 tag(仅普通应用)')
|
|
267
|
+
.option('--max-restarts <n>', '失败重启上限,0=不封顶(仅普通应用)', (v) => parseInt(v, 10))
|
|
268
|
+
.option('--keep-path-prefix', '不剥离 /apps/<appid> 前缀(仅普通应用)')
|
|
269
|
+
.option('--strip-path-prefix', '剥离 /apps/<appid> 前缀(仅普通应用;与 --keep-path-prefix 互斥)')
|
|
270
|
+
.option('--env <json>', '环境变量 JSON(整体替换,仅普通应用)')
|
|
271
|
+
.option('--env-file <path>', '从文件读环境变量 JSON(整体替换;绕开 PowerShell 引号;与 --env 二选一,优先 --env-file)')
|
|
272
|
+
.action(
|
|
273
|
+
run(async (appid, opts) => {
|
|
274
|
+
if (opts.keepPathPrefix && opts.stripPathPrefix) {
|
|
275
|
+
throw new Error('--keep-path-prefix 与 --strip-path-prefix 互斥,只能给一个')
|
|
276
|
+
}
|
|
277
|
+
const c = cfg()
|
|
278
|
+
// 读-改-写:PATCH 是整体替换语义,必须以当前配置为基线,只覆盖本次传入的字段,
|
|
279
|
+
// 否则没传的字段会被抹成零值。三态 path 前缀:两个 flag 都不传则沿用当前值。
|
|
280
|
+
const cur = await request(c, 'GET', `/apps/${appid}`)
|
|
281
|
+
const envOverride = envFromOpts(opts)
|
|
282
|
+
const body = {
|
|
283
|
+
cpu_limit: opts.cpu ?? cur.CPULimit,
|
|
284
|
+
mem_limit: opts.mem ?? cur.MemLimit,
|
|
285
|
+
container_port: opts.port ?? cur.ContainerPort,
|
|
286
|
+
tracked_tag: opts.tag ?? cur.TrackedTag,
|
|
287
|
+
max_restarts: opts.maxRestarts ?? cur.MaxRestarts,
|
|
288
|
+
keep_path_prefix: opts.keepPathPrefix
|
|
289
|
+
? true
|
|
290
|
+
: opts.stripPathPrefix
|
|
291
|
+
? false
|
|
292
|
+
: cur.KeepPathPrefix,
|
|
293
|
+
env: envOverride ?? JSON.parse(cur.EnvJSON || '{}'),
|
|
294
|
+
sensitive_keys: JSON.parse(cur.SensitiveEnvJSON || '[]'),
|
|
295
|
+
}
|
|
296
|
+
emit(await request(c, 'PATCH', `/apps/${appid}`, { body }))
|
|
297
|
+
})
|
|
298
|
+
)
|
|
299
|
+
|
|
228
300
|
program
|
|
229
301
|
.command('delete <appid>')
|
|
230
302
|
.description('删除应用(模板级联清子服务/PVC/secret),幂等')
|