@lazycatcloud/lzc-cli 1.3.11 → 1.3.13
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/changelog.md +24 -0
- package/lib/app/apkshell.js +37 -40
- package/lib/app/index.js +187 -179
- package/lib/app/lpk_build.js +341 -358
- package/lib/app/lpk_create.js +135 -155
- package/lib/app/lpk_create_generator.js +74 -66
- package/lib/app/lpk_devshell.js +444 -533
- package/lib/app/lpk_devshell_docker.js +48 -47
- package/lib/app/lpk_installer.js +119 -123
- package/lib/appstore/index.js +205 -209
- package/lib/appstore/login.js +146 -143
- package/lib/appstore/prePublish.js +101 -100
- package/lib/appstore/publish.js +254 -256
- package/lib/box/index.js +82 -77
- package/lib/config/env.js +2 -2
- package/lib/config/index.js +58 -54
- package/lib/debug_bridge.js +280 -320
- package/lib/docker/index.js +84 -86
- package/lib/i18n/README.md +25 -0
- package/lib/i18n/index.js +37 -0
- package/lib/i18n/locales/en/translation.json +251 -0
- package/lib/i18n/locales/zh/translation.json +251 -0
- package/lib/shellapi.js +122 -146
- package/lib/utils.js +539 -553
- package/package.json +6 -8
- package/scripts/cli.js +81 -77
- package/scripts/lzc-docker-compose.js +34 -33
- package/scripts/lzc-docker.js +34 -33
package/lib/debug_bridge.js
CHANGED
|
@@ -1,331 +1,291 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
contextDirname,
|
|
13
|
-
compareVersions
|
|
14
|
-
} from "./utils.js"
|
|
15
|
-
import logger from "loglevel"
|
|
16
|
-
import commandExists from "command-exists"
|
|
17
|
-
import path from "node:path"
|
|
18
|
-
import fetch from "node-fetch"
|
|
19
|
-
|
|
20
|
-
const bannerfileContent = `˄=ᆽ=ᐟ \\`
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import spawn from 'cross-spawn';
|
|
3
|
+
import logger from 'loglevel';
|
|
4
|
+
import fetch from 'node-fetch';
|
|
5
|
+
|
|
6
|
+
import shellApi from './shellapi.js';
|
|
7
|
+
import { _SYSTEM_ENV_PREFIX } from './config/env.js';
|
|
8
|
+
import { isDebugMode, isTraceMode, resolveDomain, sleep, findSshPublicKey, selectSshPublicKey, isWindows, contextDirname, compareVersions } from './utils.js';
|
|
9
|
+
import { t } from './i18n/index.js';
|
|
10
|
+
|
|
11
|
+
const bannerfileContent = `˄=ᆽ=ᐟ \\`;
|
|
21
12
|
|
|
22
13
|
export function sshBinary() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
if (isWindows) {
|
|
15
|
+
return 'ssh';
|
|
16
|
+
}
|
|
17
|
+
return 'ssh';
|
|
27
18
|
}
|
|
28
19
|
|
|
29
20
|
export function sshCmdArgs(...args) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`-o "UserKnownHostsFile=/dev/null"`,
|
|
33
|
-
`-o "ControlMaster=no"`,
|
|
34
|
-
"-q",
|
|
35
|
-
"-p 22222",
|
|
36
|
-
`${isTraceMode() ? "-v" : ""}`
|
|
37
|
-
]
|
|
38
|
-
return [...defaultOptions, ...args]
|
|
21
|
+
const defaultOptions = [`-o "StrictHostKeyChecking=no"`, `-o "UserKnownHostsFile=/dev/null"`, `-o "ControlMaster=no"`, '-q', '-p 22222', `${isTraceMode() ? '-v' : ''}`];
|
|
22
|
+
return [...defaultOptions, ...args];
|
|
39
23
|
}
|
|
40
24
|
|
|
41
25
|
export class DebugBridge {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
stream.on("close", (code) => {
|
|
295
|
-
code == 0 ? resolve() : reject()
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
async lzcDockerCompose(argv) {
|
|
301
|
-
await this.backendVersion020()
|
|
302
|
-
|
|
303
|
-
const resolvedIp = await resolveDomain(this.domain)
|
|
304
|
-
const stream = spawn(
|
|
305
|
-
sshBinary(),
|
|
306
|
-
[...sshCmdArgs(`box@${resolvedIp}`), "-t", "lzc-docker-compose", ...argv],
|
|
307
|
-
{
|
|
308
|
-
shell: true,
|
|
309
|
-
stdio: "inherit"
|
|
310
|
-
}
|
|
311
|
-
)
|
|
312
|
-
return new Promise((resolve, reject) => {
|
|
313
|
-
stream.on("close", (code) => {
|
|
314
|
-
code == 0 ? resolve() : reject()
|
|
315
|
-
})
|
|
316
|
-
})
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async backendVersion020() {
|
|
320
|
-
const backendVersion = await this.version()
|
|
321
|
-
if (compareVersions("0.2.0", backendVersion) < 0) {
|
|
322
|
-
logger.warn(`
|
|
26
|
+
constructor() {
|
|
27
|
+
this.uid = shellApi.uid;
|
|
28
|
+
this.boxname = shellApi.boxname;
|
|
29
|
+
this.domain = `dev.${this.boxname}.heiyu.space`;
|
|
30
|
+
this.checkUseResolve = !!process.env[`${_SYSTEM_ENV_PREFIX}_CHECK_DNS_RESOLVE`];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async init() {
|
|
34
|
+
await this.checkDevTools();
|
|
35
|
+
if (!(await this.canPublicKey())) {
|
|
36
|
+
// 如果不能 ssh public key 登录则提示授权申请,否则后面可能会出现 rsync 询问密码的问题
|
|
37
|
+
await this.sshApplyGrant();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async checkDevTools() {
|
|
42
|
+
let domain = this.domain;
|
|
43
|
+
if (this.checkUseResolve) {
|
|
44
|
+
try {
|
|
45
|
+
const _ipv6 = await resolveDomain(this.domain, true);
|
|
46
|
+
domain = `[${_ipv6}]`;
|
|
47
|
+
} catch {}
|
|
48
|
+
}
|
|
49
|
+
const url = `https://${domain}/bannerfile`;
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
fetch(url, { redirect: 'error' })
|
|
52
|
+
.then(async (res) => {
|
|
53
|
+
const content = await res.text();
|
|
54
|
+
if (res.status == 200 && content == bannerfileContent) {
|
|
55
|
+
resolve();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
logger.warn(
|
|
59
|
+
t(
|
|
60
|
+
'lzc_cli.lib.debug_bridge.check_dev_tools_not_exist_tips',
|
|
61
|
+
`检测到你还没有安装 '懒猫开发者工具',请先到商店中搜索安装
|
|
62
|
+
点击直接跳转 https://appstore.{{boxname}}.heiyu.space/#/shop/detail/cloud.lazycat.developer.tools
|
|
63
|
+
点击打开应用 https://dev.{{boxname}}.heiyu.space 查看应用状态
|
|
64
|
+
`,
|
|
65
|
+
{ boxname: this.boxname },
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
reject();
|
|
69
|
+
})
|
|
70
|
+
.catch((err) => {
|
|
71
|
+
logger.error(t('lzc_cli.lib.debug_bridge.check_dev_tools_fail_tips', `检测懒猫开发者工具失败,请检测您当前的网络或者懒猫微服客户端是否正常启动。`), err);
|
|
72
|
+
reject();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async common(cmd, args) {
|
|
78
|
+
const resolvedIp = await resolveDomain(this.domain);
|
|
79
|
+
args = args.map((arg) => arg.replace(this.domain, resolvedIp));
|
|
80
|
+
const ssh = spawn.sync(cmd, args, {
|
|
81
|
+
shell: true,
|
|
82
|
+
encoding: 'utf-8',
|
|
83
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
84
|
+
});
|
|
85
|
+
logger.debug(t('lzc_cli.lib.debug_bridge.common_start_log', `执行命令 {{cmd}} {{args}}`, { cmd, args: args.join(' ') }));
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
ssh.status == 0
|
|
88
|
+
? resolve(ssh.stdout)
|
|
89
|
+
: reject(
|
|
90
|
+
t('lzc_cli.lib.debug_bridge.common_exec_fail', `执行命令 {{cmd}} {{args}} 出错\n{{stdout}}\n{{stderr}}`, {
|
|
91
|
+
cmd,
|
|
92
|
+
args: args.join(' '),
|
|
93
|
+
stdout: ssh.stdout ?? '',
|
|
94
|
+
stdout: ssh.stderr ?? '',
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async install(lpkPath, pkgId) {
|
|
101
|
+
const stream = fs.createReadStream(lpkPath);
|
|
102
|
+
const resolvedIp = await resolveDomain(this.domain);
|
|
103
|
+
const ssh = spawn(sshBinary(), [...sshCmdArgs(`box@${resolvedIp}`), `install --uid ${this.uid}`, pkgId ? `--pkgId ${pkgId}` : ''], {
|
|
104
|
+
shell: true,
|
|
105
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
106
|
+
});
|
|
107
|
+
stream.pipe(ssh.stdin);
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
ssh.on('close', (code) => {
|
|
110
|
+
code == 0 ? resolve() : reject(t('lzc_cli.lib.debug_bridge.install_fail', 'install 失败'));
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async canPublicKey() {
|
|
116
|
+
try {
|
|
117
|
+
await this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`)]);
|
|
118
|
+
return true;
|
|
119
|
+
} catch (err) {
|
|
120
|
+
logger.debug('canPublicKey error: ', err);
|
|
121
|
+
if (err?.code == 'ETIMEOUT') {
|
|
122
|
+
throw t('lzc_cli.lib.debug_bridge.can_public_key_resolve_fail', `域名解析失败,请检查代理软件是否对 *.heiyu.space 拦截`);
|
|
123
|
+
} else {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async sshApplyGrant() {
|
|
130
|
+
const keys = await findSshPublicKey();
|
|
131
|
+
logger.info(t('lzc_cli.lib.debug_bridge.ssh_apply_grant_not_exist_tips', '检测到您当前的环境还没有添加 ssh 公钥到 ‘懒猫开发者工具’ 中,请选择您需要添加的公钥类型'));
|
|
132
|
+
const sshInfo = await selectSshPublicKey(keys);
|
|
133
|
+
logger.debug('ssh public key info', sshInfo);
|
|
134
|
+
|
|
135
|
+
const pk = Buffer.from(sshInfo.content.trimLeft()).toString('base64');
|
|
136
|
+
|
|
137
|
+
logger.warn(
|
|
138
|
+
t(
|
|
139
|
+
'lzc_cli.lib.debug_bridge.ssh_apply_grant_not_credible_tips',
|
|
140
|
+
`您当前机器的公钥未添加到微服({{boxname}})的信任列表中,请使用微服管理员账号在浏览器中访问以下地址,将您选择的公钥自动添加到信任列表中。(所有操作均只在您微服中进行,包括本开发机在内的任何数据不会泄漏到您的微服之外)
|
|
141
|
+
|
|
142
|
+
-> https://{{domain}}/auth?key={{pk}}
|
|
143
|
+
`,
|
|
144
|
+
{
|
|
145
|
+
boxname: this.boxname,
|
|
146
|
+
domain: this.domain,
|
|
147
|
+
kp,
|
|
148
|
+
},
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
throw '请在授权完成后重试!';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async status(appId) {
|
|
155
|
+
return this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`), `status --uid ${this.uid}`, appId]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async isDevshell(appId) {
|
|
159
|
+
await this.backendVersion020();
|
|
160
|
+
const stdout = await this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`), `isDevshellV2 --uid ${this.uid}`, appId]);
|
|
161
|
+
return stdout == 'true';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async resume(appId) {
|
|
165
|
+
return this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`), `resume --uid ${this.uid}`, appId]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async version() {
|
|
169
|
+
const output = await this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`), `version`]);
|
|
170
|
+
logger.debug(`backend version:\n${output}`);
|
|
171
|
+
try {
|
|
172
|
+
const data = JSON.parse(output);
|
|
173
|
+
return data.version;
|
|
174
|
+
} catch {
|
|
175
|
+
return '0.0.0';
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async uninstall(appId, deleteAppData = false) {
|
|
180
|
+
return this.common(sshBinary(), [...sshCmdArgs(`box@${this.domain}`), `uninstall --uid ${this.uid}`, deleteAppData ? '--delete-data' : '', appId]);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async devshell(appId, isUserApp, onconnect = null) {
|
|
184
|
+
await this.backendVersion020();
|
|
185
|
+
|
|
186
|
+
let waiting = true;
|
|
187
|
+
while (waiting) {
|
|
188
|
+
if (await this.isDevshell(appId)) {
|
|
189
|
+
waiting = false;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
logger.debug('wait app container to running...');
|
|
193
|
+
await sleep(100);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const resolvedIp = await resolveDomain(this.domain);
|
|
197
|
+
|
|
198
|
+
const stream = spawn(
|
|
199
|
+
sshBinary(),
|
|
200
|
+
[...sshCmdArgs(`box@${resolvedIp}`), '-t', 'devshell', `--uid ${this.uid}`, isUserApp ? '--userapp' : '', appId, '/bin/sh', '/lzcapp/pkg/content/devshell/exec.sh'],
|
|
201
|
+
{
|
|
202
|
+
shell: true,
|
|
203
|
+
stdio: 'inherit',
|
|
204
|
+
},
|
|
205
|
+
);
|
|
206
|
+
return new Promise((resolve, reject) => {
|
|
207
|
+
stream.on('close', (code) => {
|
|
208
|
+
code == 0 ? resolve() : reject();
|
|
209
|
+
});
|
|
210
|
+
// spawn 事件只是进程启动成功的事件,并不是ssh成功连接上的事件。所以这里使
|
|
211
|
+
// 用前面的一个 isDevshell 判断是否已经启动这个容器,再使用 spawn
|
|
212
|
+
stream.on('spawn', () => {
|
|
213
|
+
onconnect && onconnect();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async buildImage(label, contextTar) {
|
|
219
|
+
const backendVersion = await this.version();
|
|
220
|
+
|
|
221
|
+
const tag = `debug.bridge/${label}`;
|
|
222
|
+
const resolvedIp = await resolveDomain(this.domain);
|
|
223
|
+
const stream = fs.createReadStream(contextTar);
|
|
224
|
+
|
|
225
|
+
const buildStream = spawn(sshBinary(), [...sshCmdArgs(`box@${resolvedIp}`), `build --tag ${tag}`], {
|
|
226
|
+
shell: true,
|
|
227
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
228
|
+
});
|
|
229
|
+
stream.pipe(buildStream.stdin);
|
|
230
|
+
return new Promise((resolve, reject) => {
|
|
231
|
+
buildStream.on('close', (code) => {
|
|
232
|
+
code == 0
|
|
233
|
+
? resolve(compareVersions('0.1.12', backendVersion) >= 0 ? `127.0.0.1:5000/${tag}` : `dev.${this.boxname}.heiyu.space/${tag}`)
|
|
234
|
+
: reject(t('lzc_cli.lib.debug_bridge.build_image_fail', `在微服中构建 image 失败`));
|
|
235
|
+
});
|
|
236
|
+
}).finally(() => {
|
|
237
|
+
fs.rmSync(contextTar);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async lzcDocker(argv) {
|
|
242
|
+
await this.backendVersion020();
|
|
243
|
+
|
|
244
|
+
const resolvedIp = await resolveDomain(this.domain);
|
|
245
|
+
const stream = spawn(sshBinary(), [...sshCmdArgs(`box@${resolvedIp}`), '-t', 'lzc-docker', ...argv], {
|
|
246
|
+
shell: true,
|
|
247
|
+
stdio: 'inherit',
|
|
248
|
+
});
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
stream.on('close', (code) => {
|
|
251
|
+
code == 0 ? resolve() : reject();
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async lzcDockerCompose(argv) {
|
|
257
|
+
await this.backendVersion020();
|
|
258
|
+
|
|
259
|
+
const resolvedIp = await resolveDomain(this.domain);
|
|
260
|
+
const stream = spawn(sshBinary(), [...sshCmdArgs(`box@${resolvedIp}`), '-t', 'lzc-docker-compose', ...argv], {
|
|
261
|
+
shell: true,
|
|
262
|
+
stdio: 'inherit',
|
|
263
|
+
});
|
|
264
|
+
return new Promise((resolve, reject) => {
|
|
265
|
+
stream.on('close', (code) => {
|
|
266
|
+
code == 0 ? resolve() : reject();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async backendVersion020() {
|
|
272
|
+
const backendVersion = await this.version();
|
|
273
|
+
if (compareVersions('0.2.0', backendVersion) < 0) {
|
|
274
|
+
logger.warn(
|
|
275
|
+
t(
|
|
276
|
+
'lzc_cli.lib.debug_bridge.backend_version_020_no_match_tips',
|
|
277
|
+
`
|
|
323
278
|
检测到您当前的 lzc-cli 版本较新,而 '懒猫开发者工具' 比较旧,请先到微服的商店升级 '懒猫开发者工具',点击下面的连接跳转:
|
|
324
279
|
|
|
325
|
-
-> https://appstore
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
280
|
+
-> https://appstore.{{boxname}}.heiyu.space/#/shop/detail/cloud.lazycat.developer.tools
|
|
281
|
+
`,
|
|
282
|
+
{
|
|
283
|
+
boxname: this.boxname,
|
|
284
|
+
},
|
|
285
|
+
),
|
|
286
|
+
);
|
|
287
|
+
process.exit(1);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
331
291
|
}
|