@lazycatcloud/lzc-cli 1.1.10 → 1.1.11

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/api.js CHANGED
@@ -7,9 +7,10 @@ import fetch from "node-fetch";
7
7
  //
8
8
  // sdk 提供的API
9
9
  export default class API {
10
- constructor(appId, host) {
10
+ constructor(appId, host, uid = "") {
11
11
  this.appId = appId;
12
12
  this.host = host;
13
+ this.uid = uid;
13
14
  }
14
15
  async install(zipPath) {
15
16
  if (!fs.existsSync(zipPath)) {
@@ -35,7 +36,7 @@ export default class API {
35
36
 
36
37
  async resume() {
37
38
  const resp = await fetch(
38
- `${this.host}/api/v1/app/resume?id=${this.appId}`,
39
+ `${this.host}/api/v1/app/resume?id=${this.appId}&userId=${this.uid}`,
39
40
  {
40
41
  method: "POST",
41
42
  }
@@ -46,24 +47,6 @@ export default class API {
46
47
  }
47
48
  }
48
49
 
49
- async hasMount() {
50
- const resp = await fetch(
51
- `${this.host}/api/v1/app/hasMount?id=${this.appId}`,
52
- {
53
- method: "GET",
54
- }
55
- );
56
- if (resp.status == 200) {
57
- return true;
58
- } else {
59
- const text = await resp.text();
60
- if (text) {
61
- logger.debug("hasMount request failed", text);
62
- }
63
- return false;
64
- }
65
- }
66
-
67
50
  async isDevshell() {
68
51
  const resp = await fetch(
69
52
  `${this.host}/api/v1/app/isDevshell?id=${this.appId}`,
@@ -83,7 +66,9 @@ export default class API {
83
66
  }
84
67
 
85
68
  async status() {
86
- const resp = await fetch(`${this.host}/api/v1/app/status?id=${this.appId}`);
69
+ const resp = await fetch(
70
+ `${this.host}/api/v1/app/status?id=${this.appId}&userId=${this.uid}`
71
+ );
87
72
  if (resp.status == 200) {
88
73
  const status = await resp.json();
89
74
  return status;
package/lib/app/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import path from "node:path";
2
2
  import lpkCreate from "./lpk_create.js";
3
3
  import { LpkBuild } from "./lpk_build.js";
4
- import { AppDevShell, fallbackToRsync } from "./lpk_devshell.js";
4
+ import { AppDevShell } from "./lpk_devshell.js";
5
5
  import { LpkInstaller } from "./lpk_installer.js";
6
6
  import { LpkUninstaller } from "./lpk_uninstall.js";
7
7
  import { LpkStatuser } from "./lpk_status.js";
@@ -53,32 +53,31 @@ export function lpkProjectCommand(program) {
53
53
  alias: "rsync",
54
54
  deprecate: true,
55
55
  type: "boolean",
56
- default: fallbackToRsync(),
56
+ default: true,
57
57
  });
58
- const shell = process.env.SHELL
59
- ? path.basename(process.env.SHELL)
60
- : "sh";
61
58
  args.option("s", {
62
59
  alias: "shell",
63
60
  describe: "指定你最喜欢的shell",
64
61
  type: "string",
65
- default: shell,
62
+ default: "bash",
66
63
  });
67
64
  args.option("f", {
68
65
  alias: "force",
69
66
  describe: "强制重新构建",
70
67
  type: "boolean",
71
68
  });
69
+ args.option("c", {
70
+ alias: "config",
71
+ describe: "devshell配置文件",
72
+ type: "string",
73
+ default: "lzc-build.yml",
74
+ });
72
75
  },
73
- handler: async ({ context, shell, rsync, force }) => {
74
- const app = new AppDevShell(context, undefined, rsync, force);
76
+ handler: async ({ context, shell, force, config }) => {
77
+ const app = new AppDevShell(context, config, force);
75
78
  await app.init();
76
79
  await app.build();
77
- if (rsync) {
78
- await app.rsyncShell(shell);
79
- } else {
80
- await app.sshfsShell(shell);
81
- }
80
+ await app.rsyncShell(shell);
82
81
  },
83
82
  },
84
83
  ];
@@ -14,6 +14,8 @@ import { LpkManifest } from "./lpk_create.js";
14
14
  import archiver from "archiver";
15
15
  import yaml from "js-yaml";
16
16
 
17
+ const isMacos = process.platform == "darwin";
18
+
17
19
  async function tarContentDir(from, to, cwd = "./") {
18
20
  const dest = fs.createWriteStream(to);
19
21
  tar
@@ -90,9 +92,26 @@ async function fetchIconTo(options, cwd, destDir) {
90
92
  // 提供一些方便的环境变量,可以在 lzc-build.yml 中直接使用
91
93
  // - LocalIP 本地局域网ip
92
94
  function localIp() {
95
+ if (isMacos) {
96
+ const result = spawnSync("sh", [
97
+ "-c",
98
+ "ifconfig | awk '/inet /&&!/127.0.0.1/{print $2;exit}'",
99
+ ]);
100
+ if (result.error) {
101
+ logger.debug("macos get current ip is error", result.error);
102
+ return "";
103
+ } else {
104
+ const ip = result.stdout.toString().trim();
105
+ return ip;
106
+ }
107
+ }
93
108
  const output = spawnSync("ip", ["route", "get", "1.1.1.1"], {
94
109
  encoding: "utf-8",
95
110
  });
111
+ if (output.status !== 0) {
112
+ logger.debug("run ip route error", output.status, output.stderr);
113
+ return "";
114
+ }
96
115
  const match = output.stdout.match(/src\ (.+)\ uid/i);
97
116
  if (match) {
98
117
  return match[1];
@@ -2,7 +2,7 @@
2
2
  import path from "node:path";
3
3
  import fs from "node:fs";
4
4
  import logger from "loglevel";
5
- import { spawn, execSync } from "node:child_process";
5
+ import { execSync } from "node:child_process";
6
6
  import { LpkBuild } from "./lpk_build.js";
7
7
  import { LpkInstaller } from "./lpk_installer.js";
8
8
  import debounce from "lodash.debounce";
@@ -13,14 +13,12 @@ import {
13
13
  isFileExist,
14
14
  GitIgnore,
15
15
  sleep,
16
- envTemplateFile,
17
16
  md5String,
18
17
  md5File,
19
18
  createTemplateFileCommon,
20
19
  loadFromYaml,
21
20
  FileLocker,
22
21
  } from "../utils.js";
23
- import yaml from "js-yaml";
24
22
  import Key from "../key.js";
25
23
  import os from "node:os";
26
24
  import { sdkEnv } from "../env.js";
@@ -28,8 +26,8 @@ import commandExists from "command-exists";
28
26
  import chokidar from "chokidar";
29
27
  import _ from "lodash";
30
28
  import BoxAPI from "../api.js";
31
- import inquirer from "inquirer";
32
29
  import { SdkDocker } from "./lpk_devshell_docker.js";
30
+ import { getUidByManifest } from "../lzc_sdk.js";
33
31
 
34
32
  function sdkSSHHost() {
35
33
  const sdkUrl = sdkEnv.sdkUrl;
@@ -41,17 +39,6 @@ function sdkSSHPort() {
41
39
  return 2222;
42
40
  }
43
41
 
44
- function sdkSSHAddress() {
45
- const host = sdkSSHHost();
46
- const port = sdkSSHPort();
47
- return `${host}:${port}`;
48
- }
49
-
50
- // 如果本地的机器没有 docker, 将会使用 rsync 同步
51
- export function fallbackToRsync() {
52
- return !commandExists.sync("docker");
53
- }
54
-
55
42
  // 判断是否需要重新构建
56
43
  // - 先判断 lzc-build.yml 是否发生改变
57
44
  // - 再判断 lzc-build.yml 中的 manifest 中指定的文件是否发生改变
@@ -59,12 +46,11 @@ export function fallbackToRsync() {
59
46
  // - 根据 backend api 判断一个 appid 是否属于 running
60
47
  // - 根据在 backend api 中判断同步的目录下是否存在文件 判断当前运行的 app 是否已经有一个挂载的实例,避免重复挂载
61
48
  class AppDevShellMonitor {
62
- constructor(cwd, pkgId, rsyncMode = false) {
49
+ constructor(cwd, pkgId, uid = "") {
63
50
  this.pwd = cwd ? path.resolve(cwd) : process.cwd();
64
- this.rsyncMode = rsyncMode;
65
51
 
66
52
  this.pkgId = pkgId;
67
- this.boxapi = new BoxAPI(pkgId, sdkEnv.sdkUrl);
53
+ this.boxapi = new BoxAPI(pkgId, sdkEnv.sdkUrl, uid);
68
54
 
69
55
  this.optionsFilePath = path.join(this.pwd, "lzc-build.yml");
70
56
  this.options = loadFromYaml(this.optionsFilePath);
@@ -99,21 +85,10 @@ class AppDevShellMonitor {
99
85
 
100
86
  async shouldBuild() {
101
87
  return (
102
- this.change() ||
103
- (await this.notRunning()) ||
104
- (await this.noMount()) ||
105
- (await this.noDevshell())
88
+ this.change() || (await this.notRunning()) || (await this.noDevshell())
106
89
  );
107
90
  }
108
91
 
109
- async shouldRemount() {
110
- try {
111
- return await this.noMount();
112
- } catch {
113
- return true;
114
- }
115
- }
116
-
117
92
  change() {
118
93
  logger.debug("oldHash", this.oldHash);
119
94
  logger.debug("newHash", this.newHash);
@@ -148,43 +123,31 @@ class AppDevShellMonitor {
148
123
  }
149
124
  }
150
125
 
151
- async noMount() {
152
- let hasMount = await this.boxapi.hasMount();
153
- if (hasMount && this.rsyncMode) {
154
- throw "sshfs docker 进程还在运行中,如果需要使用rsync模式,请先停止;或者继续使用sshfs模式";
155
- }
156
- if (this.rsyncMode) {
157
- // rsync mode skip mount check
158
- return false;
159
- }
160
- return !hasMount;
161
- }
162
-
163
126
  async noDevshell() {
164
127
  return !(await this.boxapi.isDevshell());
165
128
  }
166
129
  }
167
130
 
168
131
  export class AppDevShell {
169
- constructor(cwd, builder, rsyncMode, forceBuild = false) {
132
+ constructor(cwd, config, forceBuild = false) {
170
133
  this.cwd = cwd ? path.resolve(cwd) : process.cwd();
171
- this.lpkBuild = builder;
134
+ this.lpkBuild = undefined;
172
135
  this.monitor = undefined;
173
- this.sshfsProcess = undefined;
174
- this.rsyncMode = rsyncMode;
175
136
  this.forceBuild = forceBuild;
137
+ this.lpkBuildConfig = config;
176
138
  }
177
139
 
178
140
  async init() {
179
141
  if (!this.lpkBuild) {
180
- this.lpkBuild = new LpkBuild(this.cwd);
142
+ this.lpkBuild = new LpkBuild(this.cwd, this.lpkBuildConfig);
181
143
  await this.lpkBuild.init();
182
144
  }
183
145
  const manifest = await this.lpkBuild.getManifest();
146
+ const uid = await getUidByManifest(manifest);
184
147
  this.monitor = await new AppDevShellMonitor(
185
148
  this.cwd,
186
149
  manifest["package"],
187
- this.rsyncMode
150
+ uid
188
151
  ).init();
189
152
  }
190
153
 
@@ -194,11 +157,6 @@ export class AppDevShell {
194
157
  logger.debug("build...");
195
158
  await this.devshellBuild();
196
159
  }
197
- // 判断是否需要重新启动 sshfs 容器
198
- if (!this.rsyncMode && (await this.monitor.shouldRemount())) {
199
- logger.debug("mount...");
200
- this.sshfsProcess = await this.sshfs();
201
- }
202
160
  }
203
161
 
204
162
  async devshellBuild() {
@@ -438,7 +396,8 @@ export class AppDevShell {
438
396
  logger.debug(err);
439
397
  }
440
398
 
441
- const devshell = new DevShell(pairs["private"], pkgId, runShell);
399
+ const uid = await getUidByManifest(manifest);
400
+ const devshell = new DevShell(pairs["private"], pkgId, runShell, uid);
442
401
  if (isSync) {
443
402
  await devshell.shell();
444
403
  } else {
@@ -449,55 +408,16 @@ export class AppDevShell {
449
408
  // 现在会一直卡在退出状态后,必须要另外手动的指定 pkill node
450
409
  process.exit(0);
451
410
  }
452
-
453
- async sshfs() {
454
- const k = new Key();
455
- const pairs = await k.getKeyPair();
456
- const manifest = await this.lpkBuild.getManifest();
457
- const localDevshell = new LocalDevshell(pairs, sdkSSHAddress());
458
- const syncP = localDevshell.run(manifest.package, this.cwd);
459
- await syncP.ready();
460
- return syncP;
461
- }
462
-
463
- async sshfsShell(runShell) {
464
- const manifest = await this.lpkBuild.getManifest();
465
- const sdk = new SdkDocker();
466
- await sdk.interactiveShell(manifest.package, runShell);
467
-
468
- if (this.sshfsProcess) {
469
- // already exit
470
- if (this.sshfsProcess.p.exitCode) {
471
- return;
472
- }
473
-
474
- const questions = [
475
- {
476
- name: "stop",
477
- type: "input",
478
- default: "n",
479
- message: "是否停止 sshfs 同步容器(y/n): ",
480
- },
481
- ];
482
- const answers = await inquirer.prompt(questions);
483
- if (answers.stop.toLowerCase() === "y") {
484
- this.sshfsProcess.p.kill("SIGTERM");
485
- } else {
486
- this.sshfsProcess.p.unref();
487
- // FIXME: why must process.exit()
488
- process.exit(0);
489
- }
490
- }
491
- }
492
411
  }
493
412
 
494
413
  class DevShell {
495
- constructor(keyFile, appId, runShell = "sh") {
414
+ constructor(keyFile, appId, runShell = "sh", uid = "") {
496
415
  logger.debug("keyFile", keyFile);
497
416
  logger.debug("appid", appId);
498
417
 
499
418
  this.keyFile = keyFile;
500
419
  this.appId = appId;
420
+ this.uid = uid;
501
421
  this.runShell = runShell;
502
422
  }
503
423
 
@@ -523,11 +443,12 @@ class DevShell {
523
443
  }
524
444
 
525
445
  let rsyncDebug = process.env.RSYNCDEBUG ? "-P" : "";
526
- let storePath = `/var/lib/box-server/lzcapps/${appId}/lzcapp/cache/devshell`;
446
+ const userId = this.uid ? `/${this.uid}` : "";
447
+ let storePath = `/run/lzc_boot/data/cache/${appId}${userId}/devshell`;
527
448
  // FIXME: 下方执行命令不确定是否有兼容性问题
528
449
  try {
529
450
  execSync(
530
- `rsync ${rsyncDebug} --rsh='${rsh}' --recursive --relative --perms --update . ${host}:${storePath} --filter=':- .gitignore' --exclude='node_modules' --exclude='.git' --delete --ignore-errors --usermap=:nobody --groupmap=*:nobody`,
451
+ `rsync ${rsyncDebug} --rsh='${rsh}' --recursive --relative --perms --update . ${host}:${storePath} --filter=':- .gitignore' --exclude='node_modules' --exclude='.git' --ignore-errors --usermap=:nobody --groupmap=*:nobody`,
531
452
  { stdio: ["ignore", "inherit", "inherit"] }
532
453
  );
533
454
  } catch (err) {
@@ -615,72 +536,6 @@ class DevShell {
615
536
 
616
537
  async connectShell() {
617
538
  const sdk = new SdkDocker();
618
- await sdk.interactiveShell(this.appId, this.runShell);
619
- }
620
- }
621
-
622
- // 本地的 devshell 容器
623
- // - 将当前项目目录通过 volumes 的方式绑定到 local_devshell 中
624
- // - local_devshell 中通过 ssh 反代本地的 22 端口到 sdk 中 30222
625
- // - sdk 中的 sshfs 通过连接 30222 端口进行同步
626
- // - 结合 local_devshell 容器中的 entrypoint 脚本
627
- class LocalDevshell {
628
- constructor(pairs, sdkHost) {
629
- this.publicKey = pairs["public"];
630
- this.privateKey = pairs["private"];
631
- this.sdkHost = sdkHost;
632
- this.log = logger.getLogger("LocalDevshell");
633
- }
634
-
635
- run(pkgId, projectPath) {
636
- const host = this.sdkHost.split(":")[0];
637
- const port = this.sdkHost.split(":")[1];
638
- // prettier-ignore
639
- const syncP = spawn(`docker`, [
640
- `run`, `--rm`,
641
- `--network=host`,
642
- `-v`, `${projectPath}:/project/${pkgId}`,
643
- `-v`, `${this.privateKey}:/sdk/privateKey`,
644
- `-v`, `${this.publicKey}:/sdk/publicKey`,
645
- `-e`, `PKGID=${pkgId}`,
646
- `-e`, `SDK_HOST=${host}`,
647
- `-e`, `SDK_PORT=${port}`,
648
- `-e`, `HOSTUID=${process.getuid()}`,
649
- `-e`, `HOSTGID=${process.getgid()}`,
650
- `registry.lazycat.cloud/lzc-cli/local_devshell:0.0.4`,
651
- ], { detached: true, stdio: ["ignore", "pipe", "pipe"] });
652
- syncP.stdout.on("data", (data) => {
653
- this.log.debug(data.toString());
654
- });
655
- syncP.stderr.on("data", (data) => {
656
- this.log.debug(data.toString());
657
- });
658
- return {
659
- p: syncP,
660
- ready: async () => {
661
- return new Promise((_resolve, _reject) => {
662
- syncP.stdout.on("data", (data) => {
663
- if (data.toString().search(/sshfs running/g) > -1) {
664
- this.log.debug("sshfs ready");
665
- _resolve();
666
- }
667
- });
668
-
669
- syncP.on("error", (err) => {
670
- this.log.error(err);
671
- });
672
-
673
- syncP.on("close", (code) => {
674
- if (code != 0) {
675
- this.log.debug(`docker exited with code ${code}`);
676
- _reject();
677
- } else {
678
- this.log.debug("sshfs close");
679
- _resolve();
680
- }
681
- });
682
- });
683
- },
684
- };
539
+ await sdk.interactiveShell(this.appId, this.runShell, this.uid);
685
540
  }
686
541
  }
@@ -135,14 +135,14 @@ export class SdkDocker {
135
135
  }
136
136
  }
137
137
 
138
- async interactiveShell(appId, shell) {
138
+ async interactiveShell(appId, shell, uid = "") {
139
139
  const host = new URL(sdkEnv.sdkUrl).hostname;
140
140
  const opts = await connectOptions(host);
141
141
  const client = new SSHClient(opts);
142
142
  await client.connect();
143
143
  try {
144
144
  const replacedAppId = appId.replaceAll(".", "_").replaceAll("-", "__");
145
- const containerName = `lzc--${replacedAppId}-app-1`;
145
+ const containerName = `lzc-${uid}-${replacedAppId}-app-1`;
146
146
  const stream = await client.exec(
147
147
  `docker exec -e SHELL=${shell} -e PKGID=${appId} -ti ${containerName} /lzcapp/pkg/content/devshell/exec.sh`,
148
148
  {
@@ -6,6 +6,8 @@ import path from "node:path";
6
6
  import Key from "../key.js";
7
7
  import { loadFromYaml, Downloader, sleep } from "../utils.js";
8
8
  import { spawnSync } from "node:child_process";
9
+ import { getUidByManifest } from "../lzc_sdk.js";
10
+ import fetch from "node-fetch";
9
11
 
10
12
  export class LpkInstaller {
11
13
  constructor() {}
@@ -25,22 +27,30 @@ export class LpkInstaller {
25
27
  }
26
28
 
27
29
  let manifest = await builder.getManifest();
28
- let api = new BoxAPI(manifest["package"], sdkEnv.sdkUrl);
30
+ let uid = await getUidByManifest(manifest);
31
+ let api = new BoxAPI(manifest["package"], sdkEnv.sdkUrl, uid);
29
32
 
30
33
  let pkgPath = await builder.exec("");
31
34
  logger.info("开始部署应用");
32
35
  await api.install(pkgPath);
33
36
 
37
+ const appUrl = sdkEnv.sdkUrl.replace(
38
+ /sdk/,
39
+ manifest["application"]["subdomain"]
40
+ );
41
+ // 如果是多实例的应用,需要先访问下,才会创建对应的容器
42
+ if (manifest["application"]["user_app"]) {
43
+ const res = await fetch(appUrl);
44
+ if (res.status >= 400) {
45
+ throw `访问 ${appUrl} 失败`;
46
+ }
47
+ }
48
+
34
49
  // 新安装的应用默认为休眠的状态,需要先等容器创建成功,等成为 paused 后 resume 下
35
50
  await api.checkStatus(true);
36
51
 
37
52
  await sleep(2000);
38
- logger.info(
39
- `👉 请在浏览器中访问 ${sdkEnv.sdkUrl.replace(
40
- /sdk/,
41
- manifest["application"]["subdomain"]
42
- )}`
43
- );
53
+ logger.info(`👉 请在浏览器中访问 ${appUrl}`);
44
54
  }
45
55
 
46
56
  async install(pkgUrl) {
@@ -1,4 +1,4 @@
1
- import { request } from "./login.js";
1
+ import { request, autoLogin } from "./login.js";
2
2
  import logger from "loglevel";
3
3
  import FormData from "form-data";
4
4
  import fs from "node:fs";
@@ -35,6 +35,8 @@ export class Publish {
35
35
  fs.rmSync(tempDir, { recursive: true });
36
36
  }
37
37
 
38
+ await autoLogin();
39
+
38
40
  if (!changelog) {
39
41
  const answer = await askChangeLog();
40
42
  changelog = answer.changelog;
package/lib/key.js CHANGED
@@ -83,7 +83,7 @@ export default class Key {
83
83
  key: fs.readFileSync(pair["private"]),
84
84
  },
85
85
  ],
86
- keepaliveInterval: 5000,
86
+ keepaliveInterval: 60000, // 60s
87
87
  });
88
88
  });
89
89
  }
package/lib/lzc_sdk.js ADDED
@@ -0,0 +1,25 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import logger from "loglevel";
5
+
6
+ const lzcConfigFile = path.resolve(
7
+ os.homedir(),
8
+ ".config",
9
+ "lzc-client-desktop",
10
+ "defaultBox.json"
11
+ );
12
+
13
+ let lzcConfig = undefined;
14
+ export async function getUidByManifest(manifest) {
15
+ if (manifest["application"]["user_app"]) {
16
+ if (!lzcConfig) {
17
+ lzcConfig = JSON.parse(
18
+ fs.readFileSync(lzcConfigFile, { encoding: "utf8" })
19
+ );
20
+ logger.debug("loginUser: ", lzcConfig["loginUser"]);
21
+ }
22
+ return lzcConfig["loginUser"];
23
+ }
24
+ return "";
25
+ }
package/lib/sdk.js CHANGED
@@ -35,7 +35,7 @@ export async function connectOptions(host) {
35
35
  agent: process.env.SSH_AUTH_SOCK,
36
36
  },
37
37
  ],
38
- keepaliveInterval: 5000, // 5s
38
+ keepaliveInterval: 60000, // 60s
39
39
  debug: sshDebug(),
40
40
  };
41
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazycatcloud/lzc-cli",
3
- "version": "1.1.10",
3
+ "version": "1.1.11",
4
4
  "description": "lazycat cloud developer kit",
5
5
  "scripts": {
6
6
  "test": "tap",
@@ -31,6 +31,7 @@
31
31
  "@balena/dockerignore": "^1.0.2",
32
32
  "@improbable-eng/grpc-web": "^0.15.0",
33
33
  "@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
34
+ "@lazycatcloud/sdk": "^0.1.120",
34
35
  "archiver": "^5.3.0",
35
36
  "browser-headers": "^0.4.1",
36
37
  "chalk": "^4.1.2",
@@ -13,7 +13,10 @@ cd /lzcapp/cache/devshell
13
13
  if command -v $SHELL &> /dev/null
14
14
  then
15
15
  exec $SHELL
16
+ elif command -v bash &> /dev/null
17
+ then
18
+ exec /bin/sh
16
19
  else
17
- echo "$SHELL 不存在,执行默认的 /bin/sh"
20
+ echo "执行默认的 /bin/sh"
18
21
  exec /bin/sh
19
22
  fi
package/lib/autologin.js DELETED
@@ -1,4 +0,0 @@
1
- import fetch from "node-fetch";
2
- export async function request(url, options = {}) {
3
- return fetch(url, options);
4
- }
@@ -1,16 +0,0 @@
1
- FROM alpine:3.16
2
-
3
- RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4
-
5
- RUN apk add --no-cache openssh openssl inotify-tools curl tzdata \
6
- && echo "root:root" | chpasswd
7
-
8
- COPY sshd_config /etc/ssh/sshd_config
9
- COPY entrypoint.sh /entrypoint.sh
10
-
11
- RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
12
- echo "Asia/Shanghai" > /etc/timezone && \
13
- date && \
14
- chmod +x /entrypoint.sh
15
-
16
- CMD ["./entrypoint.sh"]
@@ -1,5 +0,0 @@
1
- #!/usr/bin/sh
2
-
3
- VERSION=0.0.4
4
- docker build -f Dockerfile . -t registry.lazycat.cloud/lzc-cli/local_devshell:$VERSION
5
- docker push registry.lazycat.cloud/lzc-cli/local_devshell:$VERSION
@@ -1,87 +0,0 @@
1
- #!/bin/sh
2
- set -e
3
-
4
- ssh-keygen -A
5
-
6
- free_port(){
7
- # $1 最小端口
8
- local port="$1"
9
- port="${port:-8192}"
10
- local ports
11
- ports="$(cut -c 16-19 /proc/net/tcp)"
12
- while echo "$ports" | grep -q "$(printf '%.4X' "$port")"; do
13
- port=$((port+1))
14
- done
15
- echo $port
16
- }
17
- local_ssh_port="$(free_port 22812)"
18
-
19
- # do not detach (-D), log to stderr (-e), passthrough other arguments
20
- /usr/sbin/sshd -e -p $local_ssh_port
21
-
22
- OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=3 -o ConnectTimeout=30 -o ServerAliveInterval=5"
23
-
24
- # 生成key
25
- cat >/tmp/prepare.sh <<EOF
26
- #!/bin/sh
27
- mkdir -p /tmp/$PKGID/.ssh
28
-
29
- if [ ! -f /tmp/$PKGID/.ssh/id_ed25519 ]; then
30
- ssh-keygen -t ed25519 -f /tmp/$PKGID/.ssh/id_ed25519 -P ""
31
- fi
32
- EOF
33
- ssh $OPTIONS -p $SDK_PORT -i /sdk/privateKey $SDK_HOST "$(cat /tmp/prepare.sh)"
34
-
35
- # 复制生成的 key 到本地的 devshell 容器中
36
- scp -O -i /sdk/privateKey -P $SDK_PORT $OPTIONS $SDK_HOST:/tmp/$PKGID/.ssh/id_ed25519.pub /tmp/id_ed25519.pub
37
- # 输出到本地 devshell 容器中的 authorized_keys 中
38
- mkdir -p /root/.ssh
39
- cat /tmp/id_ed25519.pub >> /root/.ssh/authorized_keys
40
-
41
-
42
- # 生成 ssh port
43
- cat >/tmp/sdk_port.sh <<\EOF
44
- #!/bin/sh
45
- free_port(){
46
- # $1 最小端口
47
- local port="$1"
48
- port="${port:-8192}"
49
- local ports
50
- ports="$(cut -c 16-19 /proc/net/tcp)"
51
- while echo "$ports" | grep -q "$(printf '%.4X' "$port")"; do
52
- port=$((port+1))
53
- done
54
- echo $port
55
- }
56
- echo "ssh_port:$(free_port 12282)"
57
- EOF
58
- ssh_port=$(ssh $OPTIONS -p $SDK_PORT -i /sdk/privateKey $SDK_HOST "$(cat /tmp/sdk_port.sh)" 2>&1 |\
59
- grep ssh_port | awk -F: '{ print $2 }')
60
- echo "ssh port: $ssh_port"
61
-
62
- # inotify script
63
- cat >/tmp/inotify.sh <<EOF
64
- #!/bin/sh
65
- cd /project
66
- while [ -d /project/$PKGID ]
67
- do
68
- cd /project/$PKGID
69
- inotifywait -q -m -r -e "modify,move,create,delete" --timefmt "%Y-%m-%d %X" --format "%T,%:e,%w%f,$PKGID" .
70
- done
71
- EOF
72
- chmod +x /tmp/inotify.sh
73
-
74
- # 反代本地的 $local_ssh_port 端口到 sdk 容器中的端口 ssh_port
75
- cat >/tmp/sshfs.sh <<EOF
76
- #!/bin/sh
77
- set -ex
78
-
79
- mkdir -p /var/lib/box-server/lzcapps/$PKGID/lzcapp/cache/devshell
80
-
81
- sshfs -v root@localhost:/project/$PKGID /var/lib/box-server/lzcapps/$PKGID/lzcapp/cache/devshell -o allow_other,default_permissions -o direct_io -o dir_cache=no -o IdentityFile=/tmp/$PKGID/.ssh/id_ed25519 -o auto_unmount $OPTIONS -p $ssh_port -o uid=$HOSTUID -o gid=$HOSTGID
82
-
83
- echo "sshfs running"
84
- ssh root@localhost $OPTIONS -p $ssh_port -i /tmp/$PKGID/.ssh/id_ed25519 sh -c '/tmp/inotify.sh' | /lzc-cli-backend -inotify
85
- EOF
86
-
87
- exec ssh -R 127.0.0.1:$ssh_port:127.0.0.1:$local_ssh_port -p $SDK_PORT $OPTIONS -i /sdk/privateKey $SDK_HOST "$(cat /tmp/sshfs.sh)"
@@ -1,117 +0,0 @@
1
- # $OpenBSD: sshd_config,v 1.104 2021/07/02 05:11:21 dtucker Exp $
2
-
3
- # This is the sshd server system-wide configuration file. See
4
- # sshd_config(5) for more information.
5
-
6
- # This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
7
-
8
- # The strategy used for options in the default sshd_config shipped with
9
- # OpenSSH is to specify options with their default value where
10
- # possible, but leave them commented. Uncommented options override the
11
- # default value.
12
-
13
- # Port 22456
14
- #AddressFamily any
15
- ListenAddress 127.0.0.1
16
- #ListenAddress ::
17
-
18
- #HostKey /etc/ssh/ssh_host_rsa_key
19
- #HostKey /etc/ssh/ssh_host_ecdsa_key
20
- #HostKey /etc/ssh/ssh_host_ed25519_key
21
-
22
- # Ciphers and keying
23
- #RekeyLimit default none
24
-
25
- # Logging
26
- #SyslogFacility AUTH
27
- #LogLevel INFO
28
-
29
- # Authentication:
30
-
31
- #LoginGraceTime 2m
32
- PermitRootLogin yes
33
- #StrictModes yes
34
- #MaxAuthTries 6
35
- #MaxSessions 10
36
-
37
- PubkeyAuthentication yes
38
-
39
- # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
40
- # but this is overridden so installations will only check .ssh/authorized_keys
41
- AuthorizedKeysFile .ssh/authorized_keys
42
-
43
- #AuthorizedPrincipalsFile none
44
-
45
- #AuthorizedKeysCommand none
46
- #AuthorizedKeysCommandUser nobody
47
-
48
- # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
49
- #HostbasedAuthentication no
50
- # Change to yes if you don't trust ~/.ssh/known_hosts for
51
- # HostbasedAuthentication
52
- IgnoreUserKnownHosts yes
53
- # Don't read the user's ~/.rhosts and ~/.shosts files
54
- IgnoreRhosts yes
55
-
56
- # To disable tunneled clear text passwords, change to no here!
57
- PasswordAuthentication no
58
- PermitEmptyPasswords no
59
-
60
- # Change to no to disable s/key passwords
61
- #KbdInteractiveAuthentication yes
62
-
63
- # Kerberos options
64
- #KerberosAuthentication no
65
- #KerberosOrLocalPasswd yes
66
- #KerberosTicketCleanup yes
67
- #KerberosGetAFSToken no
68
-
69
- # GSSAPI options
70
- #GSSAPIAuthentication no
71
- #GSSAPICleanupCredentials yes
72
-
73
- # Set this to 'yes' to enable PAM authentication, account processing,
74
- # and session processing. If this is enabled, PAM authentication will
75
- # be allowed through the KbdInteractiveAuthentication and
76
- # PasswordAuthentication. Depending on your PAM configuration,
77
- # PAM authentication via KbdInteractiveAuthentication may bypass
78
- # the setting of "PermitRootLogin without-password".
79
- # If you just want the PAM account and session checks to run without
80
- # PAM authentication, then enable this but set PasswordAuthentication
81
- # and KbdInteractiveAuthentication to 'no'.
82
- # UsePAM no
83
-
84
- AllowAgentForwarding yes
85
- # Feel free to re-enable these if your use case requires them.
86
- AllowTcpForwarding yes
87
- GatewayPorts yes
88
- X11Forwarding no
89
- #X11DisplayOffset 10
90
- #X11UseLocalhost yes
91
- #PermitTTY yes
92
- #PrintMotd yes
93
- #PrintLastLog yes
94
- #TCPKeepAlive yes
95
- #PermitUserEnvironment no
96
- #Compression delayed
97
- ClientAliveInterval 5
98
- ClientAliveCountMax 3
99
- #UseDNS no
100
- #PidFile /run/sshd.pid
101
- #MaxStartups 10:30:100
102
- #PermitTunnel no
103
- #ChrootDirectory none
104
- #VersionAddendum none
105
-
106
- # no default banner path
107
- #Banner none
108
-
109
- # override default of no subsystems
110
- Subsystem sftp /usr/lib/ssh/sftp-server
111
-
112
- # Example of overriding settings on a per-user basis
113
- #Match User anoncvs
114
- # X11Forwarding no
115
- # AllowTcpForwarding no
116
- # PermitTTY no
117
- # ForceCommand cvs server