@lazycatcloud/lzc-cli 1.1.13 → 1.2.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/lib/app/index.js +33 -35
- package/lib/app/lpk_debug_bridge.js +101 -0
- package/lib/app/lpk_devshell.js +55 -114
- package/lib/app/lpk_installer.js +43 -40
- package/lib/appstore/login.js +1 -1
- package/lib/appstore/publish.js +18 -8
- package/lib/box/index.js +2 -86
- package/lib/env.js +18 -178
- package/lib/lzc_sdk.js +16 -2
- package/lib/shellapi.js +95 -0
- package/lib/shellapi.proto +301 -0
- package/lib/utils.js +2 -103
- package/package.json +3 -24
- package/template/_lpk/busybox-1.35.0 +0 -0
- package/template/_lpk/exec.sh +1 -10
- package/template/_lpk/init_debug_bridge.sh +24 -0
- package/template/_lpk/vue.lzc-build.yml.in +0 -16
- package/template/golang/lzc-build.yml +0 -15
- package/template/ionic_vue3/lzc-build.yml +0 -16
- package/template/ionic_vue3/package-lock.json +8100 -0
- package/template/lite/lzc-build.yml +0 -28
- package/lib/api.js +0 -155
- package/lib/app/lpk_devshell_docker.js +0 -211
- package/lib/app/lpk_log.js +0 -68
- package/lib/app/lpk_status.js +0 -18
- package/lib/app/lpk_uninstall.js +0 -19
- package/lib/box/api/clientapi.js +0 -1322
- package/lib/box/api/empty.js +0 -35
- package/lib/box/check_qemu.js +0 -51
- package/lib/box/qemu_vm_mgr.js +0 -608
- package/lib/box/schemes/vm_box_system_debian.json +0 -47
- package/lib/core.proto +0 -118
- package/lib/docker/promise.js +0 -91
- package/lib/docker-compose.js +0 -50
- package/lib/fetch.js +0 -50
- package/lib/git/git-commit.sh +0 -7
- package/lib/git/git-reset.sh +0 -15
- package/lib/key.js +0 -102
- package/lib/sdk.js +0 -135
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
package space.heiyu.hportal.shell;
|
|
4
|
+
|
|
5
|
+
import "google/protobuf/empty.proto";
|
|
6
|
+
|
|
7
|
+
option go_package = "/shellapi";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
message LoginRequest {
|
|
11
|
+
string box_name_or_id = 1;
|
|
12
|
+
|
|
13
|
+
string user_name = 2;
|
|
14
|
+
string user_passwd = 3;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
//若为true则将此盒子设置为默认盒子,
|
|
18
|
+
//即使为false,但当前没有任何盒子的话,也会自动变为default_box
|
|
19
|
+
bool as_default_box = 4;
|
|
20
|
+
|
|
21
|
+
//最多等待多久
|
|
22
|
+
int32 max_wait_seconds = 5;
|
|
23
|
+
|
|
24
|
+
optional string tfa_code = 6;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
// 此接口为hclient&hserver曝露给管理界面、命令行客户端等使用的API
|
|
29
|
+
service ShellCore {
|
|
30
|
+
// 删除盒子
|
|
31
|
+
rpc DelBoxConfig(BoxID) returns (google.protobuf.Empty);
|
|
32
|
+
|
|
33
|
+
// 添加、修改盒子的登录信息、开启、关闭盒子等
|
|
34
|
+
// 如果是登录新盒子,可以直接使用LoginBox这个接口,一次性处理ModifyBoxConfig和等待成功操作
|
|
35
|
+
rpc ModifyBoxConfig(BoxSetting) returns (google.protobuf.Empty);
|
|
36
|
+
|
|
37
|
+
// 阻塞请求登录一个具体盒子,以下几种情况下会结束整个请求
|
|
38
|
+
// 1. 请求超时。(由LoginRequest中的max_wait_seconds决定)
|
|
39
|
+
// 2. 结果为非connecting状态
|
|
40
|
+
//
|
|
41
|
+
// 连接中的状态会通过stream返回
|
|
42
|
+
rpc LoginBox(LoginRequest) returns (stream BoxInfo);
|
|
43
|
+
|
|
44
|
+
// 查询当前盒子列表的状态
|
|
45
|
+
rpc QueryBoxList(google.protobuf.Empty) returns(BoxList);
|
|
46
|
+
|
|
47
|
+
// 查询shellcore本身的一些信息
|
|
48
|
+
rpc QueryShellCoreInfo(google.protobuf.Empty) returns (ShellCoreInfo);
|
|
49
|
+
|
|
50
|
+
// 将日志以及额外的调试信息上传到官方服务器, 主要给最终用户点击上传日志时使用
|
|
51
|
+
rpc UploadDebugInfo(UploadDebugInfoRequest) returns (UploadDebugInfoResponse);
|
|
52
|
+
|
|
53
|
+
// 基于BSID与附近的盒子建立"近场"直连通讯
|
|
54
|
+
// 成功连接后,hclient与hserver可以正常通讯,但底层可能是ble之类的慢速通道
|
|
55
|
+
// 后续会在合适的时候自动使用此通道进行连接(优先级较低)
|
|
56
|
+
rpc ConnectNearbyBox(ConnectNearbyBoxRequest) returns (stream ConnectNearbyBoxReply);
|
|
57
|
+
|
|
58
|
+
// 请求访问(盒子里)通过sysbridge/RegisterBoxService注册的服务
|
|
59
|
+
//
|
|
60
|
+
// - 在成功连接上请求的盒子后会返回本地的代理监听地址
|
|
61
|
+
// - 当调用者关闭本请求时或会自动释放相关资源
|
|
62
|
+
// - 返回的监听地址为127.0.0.1上的随机端口
|
|
63
|
+
// - 若盒子服务在开始存在,但在此函数中途丢失或出现网络错误
|
|
64
|
+
// 本函数不会主动终止,调用者应该根据实际代理服务的情况来决定是否应该主动结束DialBoxService
|
|
65
|
+
rpc DialBoxService(DialBoxServiceRequest) returns (stream DialBoxServiceReply);
|
|
66
|
+
|
|
67
|
+
//------------------------以下所有接口都将废弃或即将废弃------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
// 使shellcore进程退出. 只有PC上有意义,优先考虑在client侧处理
|
|
70
|
+
rpc Exit(google.protobuf.Empty) returns (google.protobuf.Empty) {option deprecated=true;}
|
|
71
|
+
rpc DialTokenNetwork(DialTokenNetworkRequest) returns (stream DialTokenNetworkReply) {option deprecated=true;}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
message DialBoxServiceRequest {
|
|
75
|
+
string box_id = 1;
|
|
76
|
+
string service_name = 2;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
message DialBoxServiceReply {
|
|
80
|
+
string local_proxy_address = 1; //返回本地监听的临时地址
|
|
81
|
+
string service_extra_info = 2;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
message ConnectNearbyBoxRequest {
|
|
85
|
+
string bsid = 1;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
message ConnectNearbyBoxReply {
|
|
89
|
+
enum Status {
|
|
90
|
+
// 正在搜索
|
|
91
|
+
Scanning = 0;
|
|
92
|
+
|
|
93
|
+
// 搜索到盒子,正在连接中
|
|
94
|
+
Connecting = 1;
|
|
95
|
+
|
|
96
|
+
// 无法建立连接,具体原因看failed_reason字段
|
|
97
|
+
Failed = 2;
|
|
98
|
+
|
|
99
|
+
// 成功建立连接, 此处的Connected仅代表libp2p层连接成功,
|
|
100
|
+
// 调用者依旧需要使用`ModifyBox`之类的盒子管理接口来添加到盒子列表中
|
|
101
|
+
Connected = 3;
|
|
102
|
+
}
|
|
103
|
+
Status status = 1;
|
|
104
|
+
|
|
105
|
+
// 当status为Failed时,`failed_reason`提供更具体的信息
|
|
106
|
+
optional string failed_reason = 2;
|
|
107
|
+
|
|
108
|
+
// 当status为Connected时,此字段为盒子的peer id
|
|
109
|
+
optional string box_peer = 3;
|
|
110
|
+
|
|
111
|
+
// 是否应该提示开启相关通道,此状态仅在状态为Scanning时有效
|
|
112
|
+
bool should_enable_ble = 4;
|
|
113
|
+
bool should_enable_wifidirect = 5;
|
|
114
|
+
// 是否已初始化
|
|
115
|
+
bool is_initialized = 6;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
message DialTokenNetworkRequest {
|
|
119
|
+
option deprecated=true;
|
|
120
|
+
|
|
121
|
+
string box_id = 1; //远端地址
|
|
122
|
+
|
|
123
|
+
string network = 2; //目前只允许访问token类型网络,此字段必须写"token"
|
|
124
|
+
string address = 3; //token的值
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
message DialTokenNetworkReply {
|
|
128
|
+
option deprecated=true;
|
|
129
|
+
|
|
130
|
+
string local_endpoint = 1; //返回本地监听的临时地址
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
message BoxID {
|
|
134
|
+
string id = 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
message BoxSetting {
|
|
138
|
+
string id = 1; //box_id
|
|
139
|
+
optional string name = 2; //box_name
|
|
140
|
+
|
|
141
|
+
// 以下optional,若不设置则使用当前值
|
|
142
|
+
|
|
143
|
+
optional bool enabled = 3;
|
|
144
|
+
|
|
145
|
+
message AuthInfo {
|
|
146
|
+
string user = 3;
|
|
147
|
+
string password = 4;
|
|
148
|
+
optional string password_hash = 5;
|
|
149
|
+
}
|
|
150
|
+
optional AuthInfo auth = 4;
|
|
151
|
+
|
|
152
|
+
//设置此盒子为默认盒子,会覆盖其他(如果有)默认盒子的配置
|
|
153
|
+
//第一个添加的盒子会自动成为默认盒子
|
|
154
|
+
optional bool set_as_default_box = 5;
|
|
155
|
+
|
|
156
|
+
optional string tfa_code = 6;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 盒子只会处于以下四种状态之一
|
|
160
|
+
enum BoxStatus {
|
|
161
|
+
// 此盒子当前未激活
|
|
162
|
+
DISABLED = 0;
|
|
163
|
+
|
|
164
|
+
// 内部状态,当激活的一瞬间会处于此状态
|
|
165
|
+
// 此状态下会很快自动进入CONNECTING状态
|
|
166
|
+
ENABLED = 4;
|
|
167
|
+
|
|
168
|
+
// 正在连接中,此过程持续时间无法评估,
|
|
169
|
+
// 可能瞬间结束也可能持续一两分钟(在确实可以连接上的前提下)
|
|
170
|
+
CONNECTING = 1;
|
|
171
|
+
|
|
172
|
+
// 此盒子已经可以正常使用
|
|
173
|
+
READY = 2;
|
|
174
|
+
|
|
175
|
+
// 确定无法连接,此时不会继续调度,需要客户端介入.
|
|
176
|
+
// 客户端需要根据FailedStatus的具体值,进行修复。
|
|
177
|
+
FAILED = 3;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
//------ 000 未知原因失败。其他所有状态都会有一个明确的处理方式,客户端UI需要根据具体的失败状态进行UI交互
|
|
181
|
+
//------ 1xx 未进行login前的失败,如版本不匹配
|
|
182
|
+
//------ 2xx login hserver未成功,如帐号密码错误、TFA失败、当前设备被管理员移除等
|
|
183
|
+
//------ 3xx (hserver成功后)上层盒子系统异常,如数据盘需要解密、核心组件无法启动等
|
|
184
|
+
enum FailedStatus {
|
|
185
|
+
// 当前客户端无法处理此失败,直接提示failed reason
|
|
186
|
+
// 比如hserver版本较高或较低,提供了一些当前hclient无法支持的失败状态
|
|
187
|
+
FAILED_UNKNOWN = 0;
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
//调用LoginBox的过程中,此盒子的状态被其他API请求转换为disabled了
|
|
191
|
+
FAILED_LOCAL_DISABLED_BOX = 100;
|
|
192
|
+
//调用LoginBox时使用了一个不存在的盒子名称。(若只是本地不盒子列表不存在此盒子,会自动添加到盒子列表)
|
|
193
|
+
FAILED_LOCAL_NO_SUCH_BOX_IN_THE_WORLD = 101;
|
|
194
|
+
//使用LoginBox时,登录超时
|
|
195
|
+
FAILED_LOCAL_CONNECTING_TIMEOUT = 102;
|
|
196
|
+
// 当前设备已经被移除,请不要继续登录。仅在LoginBox时会出现此状态。且shellapi会自动删除此状态的配置信息
|
|
197
|
+
FAILED_LOCAL_DEVICE_HAS_BEEN_REMOVED = 103;
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
//盒子未初始化,需要调用setupnewbox向horigin申请盒子名称以及配套资源
|
|
201
|
+
FAILED_LOGIN_HSERVER_NOT_INIT = 200;
|
|
202
|
+
// 当前登录信息不正确,需要调用ModifyBox设置新的auth信息
|
|
203
|
+
FAILED_LOGIN_INVALID_PASSWORD = 201;
|
|
204
|
+
// 当前客户端与服务器版本不匹配,无法连接,需要升级盒子系统或客户端软件
|
|
205
|
+
FAILED_LOGIN_MISMATCH_BOX_VERSION = 203;
|
|
206
|
+
// 需要进行两步验证
|
|
207
|
+
FAILED_LOGIN_TFA_REQUIRE = 204;
|
|
208
|
+
// 两步验证结果不通过
|
|
209
|
+
FAILED_LOGIN_TFA_FAILED = 205;
|
|
210
|
+
// 两步验证等待超时
|
|
211
|
+
FAILED_LOGIN_TFA_TIMEOUT = 206;
|
|
212
|
+
FAILED_LOGIN_TFA_NO_TRUSTED_DEVICE_ONLINE = 207;
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
// 盒子系统处于异常状态,需要管理员介入修复
|
|
216
|
+
FAILED_BOXSYS_UNKNOWN_EXCEPTION = 301;
|
|
217
|
+
// 盒子系统处于数据盘等待解密状态,需要管理员输入磁盘密码
|
|
218
|
+
FAILED_BOXSYS_WAITING_DATADISK_DECRYPTION = 302;
|
|
219
|
+
// 盒子系统处于数据盘未初始化状态,需要管理员选择磁盘格式化方案,比如是否加密等
|
|
220
|
+
FAILED_BOXSYS_DATADISK_NOT_INIT = 303;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
message BoxInfo {
|
|
224
|
+
string box_id = 1;
|
|
225
|
+
|
|
226
|
+
string box_name = 2;
|
|
227
|
+
|
|
228
|
+
string box_home_url = 3;
|
|
229
|
+
|
|
230
|
+
string box_domain = 14;
|
|
231
|
+
|
|
232
|
+
string box_virtual_ip = 10;
|
|
233
|
+
|
|
234
|
+
BoxStatus status = 4;
|
|
235
|
+
|
|
236
|
+
string status_reason = 5;
|
|
237
|
+
optional FailedStatus failed_status = 6;
|
|
238
|
+
|
|
239
|
+
string login_user = 7;
|
|
240
|
+
bool is_admin_login = 8;
|
|
241
|
+
|
|
242
|
+
string auth_token = 9;
|
|
243
|
+
|
|
244
|
+
// 此盒子属于当前客户端的默认盒子
|
|
245
|
+
bool is_default_box = 15;
|
|
246
|
+
|
|
247
|
+
// 与此盒子的底层网络是否连通
|
|
248
|
+
bool low_network_connected = 16;
|
|
249
|
+
// 与此盒子的底层网络连通是通过中转的低速网络
|
|
250
|
+
bool is_relay_connection = 13;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
message BoxList {
|
|
254
|
+
repeated BoxInfo boxes = 1;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
message ShellCoreInfo {
|
|
258
|
+
string id = 1;
|
|
259
|
+
string tun_ip = 2;
|
|
260
|
+
|
|
261
|
+
// 当前节点广播的地址列表
|
|
262
|
+
repeated string local_ips = 3;
|
|
263
|
+
|
|
264
|
+
string origin_server = 4;
|
|
265
|
+
|
|
266
|
+
string device_domain = 5;
|
|
267
|
+
|
|
268
|
+
string version = 6;
|
|
269
|
+
|
|
270
|
+
// 当前节点上的网卡地址列表
|
|
271
|
+
repeated string ifce_ips = 7;
|
|
272
|
+
|
|
273
|
+
// 当前节点上实际监听的地址列表
|
|
274
|
+
repeated string listen_ips = 8;
|
|
275
|
+
|
|
276
|
+
string device_os = 9;
|
|
277
|
+
|
|
278
|
+
// // 设备 DNS 服务器地址
|
|
279
|
+
// string dns_ip = 10;
|
|
280
|
+
|
|
281
|
+
// // 内存占用
|
|
282
|
+
// int32 memory_usage = 11;
|
|
283
|
+
|
|
284
|
+
// 额外的调试信息
|
|
285
|
+
map<string, string> debug_extras = 101;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
message UploadDebugInfoRequest {
|
|
289
|
+
// 上传的服务器地址
|
|
290
|
+
string url = 1;
|
|
291
|
+
|
|
292
|
+
// 由用户提供的描述信息
|
|
293
|
+
string issue_content = 2;
|
|
294
|
+
|
|
295
|
+
// 用户联系方式, 如手机号或邮箱地址
|
|
296
|
+
string contact = 3;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
message UploadDebugInfoResponse {
|
|
300
|
+
string id = 1;
|
|
301
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -7,7 +7,7 @@ import mergeWith from "lodash.mergewith";
|
|
|
7
7
|
import { dirname } from "path";
|
|
8
8
|
import { fileURLToPath } from "url";
|
|
9
9
|
import ignore from "ignore";
|
|
10
|
-
import { createHash
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
11
|
import https from "node:https";
|
|
12
12
|
import http from "node:http";
|
|
13
13
|
import zlib from "node:zlib";
|
|
@@ -15,11 +15,6 @@ import process from "node:process";
|
|
|
15
15
|
import { spawnSync } from "node:child_process";
|
|
16
16
|
import logger from "loglevel";
|
|
17
17
|
|
|
18
|
-
export const APP_FOLDER = ".lazycat";
|
|
19
|
-
export const APP_CONFIG_FILE = "app-config";
|
|
20
|
-
export const APP_SDK_HOSTNAME = "box";
|
|
21
|
-
export const GLOBAL_CONFIG_DIR = path.join(os.homedir(), "/.config/lazycat");
|
|
22
|
-
|
|
23
18
|
export const envsubstr = async (templateContents, args) => {
|
|
24
19
|
const parse = await importDefault("envsub/js/envsub-parser.js");
|
|
25
20
|
return parse(templateContents, args);
|
|
@@ -60,7 +55,7 @@ export function dumpToYaml(template, target) {
|
|
|
60
55
|
export function toPair(object) {
|
|
61
56
|
return Object.keys(object).map((key) => {
|
|
62
57
|
let value = object[key] ? object[key].toString() : "";
|
|
63
|
-
key = key.
|
|
58
|
+
key = key.replace(/-/g, "_");
|
|
64
59
|
return {
|
|
65
60
|
name: key,
|
|
66
61
|
value,
|
|
@@ -85,71 +80,6 @@ export async function envTemplateFile(templateFile, env) {
|
|
|
85
80
|
);
|
|
86
81
|
}
|
|
87
82
|
|
|
88
|
-
export async function createTemplateFile(templateFile, outputFile, env) {
|
|
89
|
-
let output = await envTemplateFile(templateFile, env);
|
|
90
|
-
fs.writeFileSync(outputFile, output);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function createTemplateFileCommon(templateFile, outputFile, env) {
|
|
94
|
-
const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
|
|
95
|
-
const options = {
|
|
96
|
-
envs: toPair(env),
|
|
97
|
-
syntax: "default",
|
|
98
|
-
protect: false,
|
|
99
|
-
};
|
|
100
|
-
const output = await envsubstr(fs.readFileSync(templateFile, "utf-8"), {
|
|
101
|
-
options,
|
|
102
|
-
});
|
|
103
|
-
fs.writeFileSync(outputFile, output);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export async function envsubstrDefault(templateContents, env) {
|
|
107
|
-
const options = {
|
|
108
|
-
envs: toPair(env),
|
|
109
|
-
syntax: "default",
|
|
110
|
-
protect: false,
|
|
111
|
-
};
|
|
112
|
-
return envsubstr(templateContents, { options });
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// this will copy current app to a tmp dir
|
|
116
|
-
export async function copyDotAppDir(from, to, opts = {}) {
|
|
117
|
-
const {
|
|
118
|
-
include = [],
|
|
119
|
-
ignore = ["app-config", "output", "box-config.json"],
|
|
120
|
-
env = {},
|
|
121
|
-
} = opts;
|
|
122
|
-
try {
|
|
123
|
-
if (fs.existsSync(to)) {
|
|
124
|
-
fs.rmSync(to, { recursive: true });
|
|
125
|
-
}
|
|
126
|
-
const _files = await glob(["**"].concat(include), {
|
|
127
|
-
cwd: from,
|
|
128
|
-
dot: true,
|
|
129
|
-
ignore: ignore,
|
|
130
|
-
});
|
|
131
|
-
for (let f of _files) {
|
|
132
|
-
let needConvert = false;
|
|
133
|
-
let templateFile = path.join(from, f);
|
|
134
|
-
let outputFile = path.join(to, f);
|
|
135
|
-
if (f.endsWith(".in")) {
|
|
136
|
-
outputFile = outputFile.replace(/.in$/, "");
|
|
137
|
-
needConvert = true;
|
|
138
|
-
}
|
|
139
|
-
ensureDir(outputFile);
|
|
140
|
-
if (needConvert) {
|
|
141
|
-
await createTemplateFile(templateFile, outputFile, env);
|
|
142
|
-
} else {
|
|
143
|
-
fs.copyFileSync(templateFile, outputFile);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return to;
|
|
147
|
-
} catch (e) {
|
|
148
|
-
console.log(e);
|
|
149
|
-
return "";
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
83
|
export function mergeYamlInMemory(args) {
|
|
154
84
|
if (args.length == 0) {
|
|
155
85
|
return {};
|
|
@@ -166,22 +96,6 @@ export function mergeYamlInMemory(args) {
|
|
|
166
96
|
}, {});
|
|
167
97
|
}
|
|
168
98
|
|
|
169
|
-
// override yaml, notice this will change target file
|
|
170
|
-
export function mergeYaml(target, source) {
|
|
171
|
-
const targetContent = yaml.load(fs.readFileSync(target, "utf8"));
|
|
172
|
-
const sourceContent = yaml.load(fs.readFileSync(source, "utf8"));
|
|
173
|
-
const merged = mergeWith(
|
|
174
|
-
targetContent,
|
|
175
|
-
sourceContent,
|
|
176
|
-
(objValue, srcValue) => {
|
|
177
|
-
if (Array.isArray(objValue)) {
|
|
178
|
-
return objValue.concat(srcValue);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
);
|
|
182
|
-
dumpToYaml(merged, target);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
99
|
export function contextDirname(url = import.meta.url) {
|
|
186
100
|
return dirname(fileURLToPath(url));
|
|
187
101
|
}
|
|
@@ -254,17 +168,6 @@ export function isFileExist(path) {
|
|
|
254
168
|
}
|
|
255
169
|
}
|
|
256
170
|
|
|
257
|
-
export function urlHostname(url) {
|
|
258
|
-
let u = new URL(url);
|
|
259
|
-
return u.hostname;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// REVIEW: 用户输入的app-id 空格替换为减号并且转换为全小写。
|
|
263
|
-
// 这会影响默认的app-name,因为app-name的默认值依赖app-id,但是如果特定输入了app-name则正常
|
|
264
|
-
export function parse2CorrectName(name) {
|
|
265
|
-
return name.replaceAll(" ", "-").toLowerCase();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
171
|
export async function sleep(ms) {
|
|
269
172
|
return new Promise((resolve) => {
|
|
270
173
|
setTimeout(resolve, ms);
|
|
@@ -348,10 +251,6 @@ export class Downloader {
|
|
|
348
251
|
}
|
|
349
252
|
}
|
|
350
253
|
|
|
351
|
-
export function randomString(length = 4) {
|
|
352
|
-
return randomBytes(length).toString("hex");
|
|
353
|
-
}
|
|
354
|
-
|
|
355
254
|
export class FileLocker {
|
|
356
255
|
constructor(id) {
|
|
357
256
|
this.filename = undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "tap",
|
|
@@ -28,46 +28,25 @@
|
|
|
28
28
|
"author": "zac zeng",
|
|
29
29
|
"license": "ISC",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@grpc/
|
|
33
|
-
"@grpc/proto-loader": "^0.7.6",
|
|
34
|
-
"@improbable-eng/grpc-web": "^0.15.0",
|
|
35
|
-
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
|
31
|
+
"@grpc/grpc-js": "^1.8.18",
|
|
32
|
+
"@grpc/proto-loader": "^0.7.8",
|
|
36
33
|
"archiver": "^5.3.0",
|
|
37
|
-
"browser-headers": "^0.4.1",
|
|
38
34
|
"chalk": "^4.1.2",
|
|
39
35
|
"chokidar": "^3.5.3",
|
|
40
36
|
"command-exists": "^1.2.9",
|
|
41
|
-
"dockerfile-ast": "^0.4.1",
|
|
42
|
-
"dockerode": "^3.3.1",
|
|
43
|
-
"ejs": "^3.1.6",
|
|
44
37
|
"envsub": "^4.0.7",
|
|
45
|
-
"execa": "^5.1.1",
|
|
46
38
|
"fast-glob": "^3.2.7",
|
|
47
|
-
"fetch-cookie": "^2.1.0",
|
|
48
39
|
"form-data": "^4.0.0",
|
|
49
40
|
"ignore": "^5.2.0",
|
|
50
41
|
"inquirer": "^8.2.0",
|
|
51
42
|
"isbinaryfile": "^4.0.8",
|
|
52
43
|
"js-yaml": "^4.1.0",
|
|
53
44
|
"lodash.debounce": "^4.0.8",
|
|
54
|
-
"lodash.get": "^4.4.2",
|
|
55
45
|
"lodash.merge": "^4.6.2",
|
|
56
46
|
"lodash.mergewith": "^4.6.2",
|
|
57
|
-
"log-update": "^5.0.0",
|
|
58
47
|
"loglevel": "^1.8.0",
|
|
59
|
-
"minimist": "^1.2.5",
|
|
60
48
|
"node-fetch": "^2.6.6",
|
|
61
|
-
"node-stream-zip": "^1.15.0",
|
|
62
|
-
"ora": "^6.0.1",
|
|
63
|
-
"protobufjs": "^7.1.1",
|
|
64
|
-
"rxjs": "^7.5.6",
|
|
65
|
-
"semver": "^7.3.5",
|
|
66
|
-
"ssh2": "^1.5.0",
|
|
67
|
-
"ssh2-promise": "^1.0.2",
|
|
68
49
|
"tar": "^6.1.11",
|
|
69
|
-
"tough-cookie-file-store": "^2.0.3",
|
|
70
|
-
"urllib": "^3.1.0",
|
|
71
50
|
"yargs": "^17.5.1"
|
|
72
51
|
},
|
|
73
52
|
"devDependencies": {
|
|
Binary file
|
package/template/_lpk/exec.sh
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
DEBUG_BRIDGE_LZCAPP=http://app.cloud.lazycat.developer.tools.lzcapp
|
|
5
|
+
BUSYBOX=/lzcapp/pkg/content/devshell/busybox
|
|
6
|
+
|
|
7
|
+
mkdir -p /root/.ssh
|
|
8
|
+
mkdir -p /etc/debug.bridge
|
|
9
|
+
|
|
10
|
+
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/dropbearmulti -O /usr/bin/dropbearmulti
|
|
11
|
+
chmod +x /usr/bin/dropbearmulti
|
|
12
|
+
|
|
13
|
+
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/rsync -O /usr/bin/rsync
|
|
14
|
+
chmod +x /usr/bin/rsync
|
|
15
|
+
|
|
16
|
+
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/authorized_keys -O /root/.ssh/authorized_keys
|
|
17
|
+
chmod 0644 /root/.ssh/authorized_keys
|
|
18
|
+
|
|
19
|
+
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/bannerfile -O /etc/debug.bridge/bannerfile
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
mkdir -p /etc/dropbear
|
|
23
|
+
|
|
24
|
+
exec dropbearmulti dropbear -R -F -E -B -p 22222
|
|
@@ -32,25 +32,9 @@ icon: ./lazycat.png
|
|
|
32
32
|
# - /=http://127.0.0.1:3000
|
|
33
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
34
|
|
|
35
|
-
# devshell 指定构建Dockerfile
|
|
36
|
-
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
-
# devshell:
|
|
38
|
-
# routes:
|
|
39
|
-
# - /=http://127.0.0.1:3000
|
|
40
|
-
# image: ${package}-devshell:${version}
|
|
41
|
-
# pull_policy: build
|
|
42
|
-
# build: .
|
|
43
|
-
|
|
44
|
-
# dvshell 指定开发依赖的情况
|
|
45
|
-
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
-
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
47
35
|
devshell:
|
|
48
36
|
routes:
|
|
49
37
|
- /=http://127.0.0.1:3000
|
|
50
|
-
dependencies:
|
|
51
|
-
- nodejs
|
|
52
|
-
- vim
|
|
53
|
-
- npm
|
|
54
38
|
# setupscript 每次进入到app container后都会执行的配置脚本
|
|
55
39
|
# - 可以为脚本的路径地址
|
|
56
40
|
# - 如果构建命令简单,也可以直接写 sh 的命令
|
|
@@ -32,24 +32,9 @@ icon: ./lazycat.png
|
|
|
32
32
|
# - /=http://127.0.0.1:3000
|
|
33
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
34
|
|
|
35
|
-
# devshell 指定构建Dockerfile
|
|
36
|
-
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
-
# devshell:
|
|
38
|
-
# routes:
|
|
39
|
-
# - /=http://127.0.0.1:3000
|
|
40
|
-
# image: ${package}-devshell:${version}
|
|
41
|
-
# pull_policy: build
|
|
42
|
-
# build: .
|
|
43
|
-
|
|
44
|
-
# dvshell 指定开发依赖的情况
|
|
45
|
-
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
-
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
47
35
|
devshell:
|
|
48
36
|
routes:
|
|
49
37
|
- /=http://127.0.0.1:3000
|
|
50
|
-
dependencies:
|
|
51
|
-
- go
|
|
52
|
-
- vim
|
|
53
38
|
# setupscript 每次进入到app container后都会执行的配置脚本
|
|
54
39
|
# - 可以为脚本的路径地址
|
|
55
40
|
# - 如果构建命令简单,也可以直接写 sh 的命令
|
|
@@ -32,25 +32,9 @@ icon: ./lazycat.png
|
|
|
32
32
|
# - /=http://127.0.0.1:3000
|
|
33
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
34
|
|
|
35
|
-
# devshell 指定构建Dockerfile
|
|
36
|
-
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
-
# devshell:
|
|
38
|
-
# routes:
|
|
39
|
-
# - /=http://127.0.0.1:3000
|
|
40
|
-
# image: ${package}-devshell:${version}
|
|
41
|
-
# pull_policy: build
|
|
42
|
-
# build: .
|
|
43
|
-
|
|
44
|
-
# dvshell 指定开发依赖的情况
|
|
45
|
-
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
-
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
47
35
|
devshell:
|
|
48
36
|
routes:
|
|
49
37
|
- /=http://127.0.0.1:3000
|
|
50
|
-
dependencies:
|
|
51
|
-
- nodejs
|
|
52
|
-
- vim
|
|
53
|
-
- npm
|
|
54
38
|
# setupscript 每次进入到app container后都会执行的配置脚本
|
|
55
39
|
# - 可以为脚本的路径地址
|
|
56
40
|
# - 如果构建命令简单,也可以直接写 sh 的命令
|