@lazycatcloud/lzc-cli 1.1.12 → 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 +52 -33
- package/lib/app/lpk_build.js +1 -5
- package/lib/app/lpk_create.js +9 -3
- package/lib/app/lpk_debug_bridge.js +101 -0
- package/lib/app/lpk_devshell.js +59 -129
- package/lib/app/lpk_installer.js +43 -50
- 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 +75 -17
- package/lib/shellapi.js +95 -0
- package/lib/shellapi.proto +301 -0
- package/lib/utils.js +7 -103
- package/package.json +3 -21
- package/scripts/cli.js +6 -6
- 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/docker/promise.js +0 -91
- package/lib/docker-compose.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
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "home-cloud",
|
|
3
|
-
"uuid": "047dac31-b75b-46ed-aedb-a31fa46a6503",
|
|
4
|
-
"memory": 4096,
|
|
5
|
-
"kernel": "debian",
|
|
6
|
-
"uefi": true,
|
|
7
|
-
"path": "${HOME}/.cache/box-emulator",
|
|
8
|
-
"volume": {
|
|
9
|
-
"config": "/etc/home-cloud"
|
|
10
|
-
},
|
|
11
|
-
"disks": [
|
|
12
|
-
{
|
|
13
|
-
"id": "system",
|
|
14
|
-
"size": "8G",
|
|
15
|
-
"system": true,
|
|
16
|
-
"partitions": [
|
|
17
|
-
{
|
|
18
|
-
"fs_type": "vfat",
|
|
19
|
-
"size": "100M",
|
|
20
|
-
"mount_point": "/boot/ESP"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"fs_type": "ext4",
|
|
24
|
-
"size": "4G",
|
|
25
|
-
"mount_point": "/"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"fs_type": "ext4",
|
|
29
|
-
"size": "full",
|
|
30
|
-
"mount_point": "/mnt"
|
|
31
|
-
}
|
|
32
|
-
]
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"id": "data1",
|
|
36
|
-
"size": "64G",
|
|
37
|
-
"system": false,
|
|
38
|
-
"partitions": []
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"id": "data2",
|
|
42
|
-
"size": "64G",
|
|
43
|
-
"rebuild": false,
|
|
44
|
-
"partitions": []
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
|
-
}
|
package/lib/docker/promise.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import Docker from "dockerode";
|
|
2
|
-
|
|
3
|
-
var wrappedProto = Docker.prototype;
|
|
4
|
-
|
|
5
|
-
function denodeify(func) {
|
|
6
|
-
return function (...args) {
|
|
7
|
-
return new Promise((resolve, reject) => {
|
|
8
|
-
let input = [...args, (err, val) => (err ? reject(err) : resolve(val))];
|
|
9
|
-
func.apply(this, input);
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function proxyPromise(method) {
|
|
15
|
-
var promisey = denodeify(method);
|
|
16
|
-
return function () {
|
|
17
|
-
return promisey.apply(this.$subject, arguments);
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function promiseObj(target, input) {
|
|
22
|
-
for (var key in input) {
|
|
23
|
-
if (typeof input[key] !== "function") continue;
|
|
24
|
-
target[key] = proxyPromise(input[key]);
|
|
25
|
-
}
|
|
26
|
-
return target;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function PromiseProxy(subject) {
|
|
30
|
-
var result = Object.create(subject);
|
|
31
|
-
result.$subject = subject;
|
|
32
|
-
return promiseObj(result, subject);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function ContainerProxy(subject) {
|
|
36
|
-
var result = PromiseProxy(subject);
|
|
37
|
-
var exec = result.exec;
|
|
38
|
-
result.exec = function () {
|
|
39
|
-
return exec.apply(this, arguments).then(function (exec) {
|
|
40
|
-
return PromiseProxy(exec);
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function DockerProxy(options) {
|
|
47
|
-
this.$subject = new Docker(options);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
promiseObj(DockerProxy.prototype, wrappedProto);
|
|
51
|
-
|
|
52
|
-
// sadly we need to wrap run directly as a promise to consolidate both
|
|
53
|
-
// of the resulting arguments.
|
|
54
|
-
DockerProxy.prototype.run = function (image, command, stream) {
|
|
55
|
-
var subject = this.$subject;
|
|
56
|
-
return new Promise(function (accept, reject) {
|
|
57
|
-
subject.run(image, command, stream, function (err, result, container) {
|
|
58
|
-
if (err) return reject(err);
|
|
59
|
-
accept({
|
|
60
|
-
result: result,
|
|
61
|
-
// re-wrap
|
|
62
|
-
container: ContainerProxy(container),
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// We also have wrap createContainer manually as it returns
|
|
69
|
-
DockerProxy.prototype.createContainer = function (opts) {
|
|
70
|
-
var subject = this.$subject;
|
|
71
|
-
return new Promise(function (accept, reject) {
|
|
72
|
-
subject.createContainer(opts, function (err, container) {
|
|
73
|
-
if (err) return reject(err);
|
|
74
|
-
accept(ContainerProxy(container));
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
DockerProxy.prototype.getImage = function (id) {
|
|
80
|
-
return PromiseProxy(this.$subject.getImage(id));
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
DockerProxy.prototype.getContainer = function (id) {
|
|
84
|
-
return ContainerProxy(this.$subject.getContainer(id));
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
DockerProxy.prototype.getVolume = function (name) {
|
|
88
|
-
return PromiseProxy(this.$subject.getVolume(name));
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export default DockerProxy;
|
package/lib/docker-compose.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import yaml from "js-yaml";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import mergeWith from "lodash.mergewith";
|
|
4
|
-
|
|
5
|
-
export function load(filePath) {
|
|
6
|
-
return yaml.load(fs.readFileSync(filePath, "utf8"));
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// 用于合并多个 DockerCompose 文件
|
|
10
|
-
export default class DockerCompose {
|
|
11
|
-
constructor(basefile) {
|
|
12
|
-
this.basefile = basefile;
|
|
13
|
-
this.obj = load(basefile);
|
|
14
|
-
}
|
|
15
|
-
// 直接修改 yaml 内容
|
|
16
|
-
pipe(cb) {
|
|
17
|
-
cb.apply(this, [this.obj]);
|
|
18
|
-
return this;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// mergeFile({file: ""}) or merge({content: ""})
|
|
22
|
-
merge(context) {
|
|
23
|
-
let newObj;
|
|
24
|
-
if (context.file) {
|
|
25
|
-
newObj = load(context.file);
|
|
26
|
-
}
|
|
27
|
-
if (context.content) {
|
|
28
|
-
newObj = yaml.load(context.content);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
this.obj = mergeWith(this.obj, newObj, (objValue, srcValue) => {
|
|
32
|
-
if (Array.isArray(objValue)) {
|
|
33
|
-
return objValue.concat(srcValue);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// to: optional
|
|
40
|
-
save(to) {
|
|
41
|
-
fs.writeFileSync(
|
|
42
|
-
to || this.basefile,
|
|
43
|
-
yaml.dump(this.obj, {
|
|
44
|
-
styles: {
|
|
45
|
-
"!!null": "empty", // dump null as ""
|
|
46
|
-
},
|
|
47
|
-
})
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
}
|
package/lib/git/git-commit.sh
DELETED
package/lib/git/git-reset.sh
DELETED
package/lib/key.js
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import inquirer from "inquirer";
|
|
2
|
-
import glob from "fast-glob";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { Client } from "ssh2";
|
|
5
|
-
import process from "process";
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import execa from "execa";
|
|
8
|
-
import API from "./api.js";
|
|
9
|
-
import { ensureDir } from "./utils.js";
|
|
10
|
-
import os from "os";
|
|
11
|
-
|
|
12
|
-
const KEY_NAME = "id_ed25519";
|
|
13
|
-
const SSH_CONFIG_DIR = path.join(os.homedir(), ".ssh");
|
|
14
|
-
|
|
15
|
-
export default class Key {
|
|
16
|
-
// 确保该秘钥可以工作
|
|
17
|
-
async ensure(host) {
|
|
18
|
-
const pairs = await this.getKeyPair();
|
|
19
|
-
await this.validationCheck(host, pairs);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async generate() {
|
|
23
|
-
const privateKeyFile = path.join(SSH_CONFIG_DIR, KEY_NAME);
|
|
24
|
-
ensureDir(privateKeyFile);
|
|
25
|
-
await execa(
|
|
26
|
-
"ssh-keygen",
|
|
27
|
-
["-t", "ed25519", "-P", "", "-f", privateKeyFile],
|
|
28
|
-
{
|
|
29
|
-
stdio: "inherit",
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
return {
|
|
33
|
-
private: privateKeyFile,
|
|
34
|
-
public: privateKeyFile + ".pub",
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async validationCheck(host, pair) {
|
|
39
|
-
const hostname = new URL(host).hostname;
|
|
40
|
-
const client = new Client();
|
|
41
|
-
return new Promise((resolve, reject) => {
|
|
42
|
-
client
|
|
43
|
-
.on("ready", () => {
|
|
44
|
-
resolve(true);
|
|
45
|
-
client.end();
|
|
46
|
-
})
|
|
47
|
-
.on("error", (err) => {
|
|
48
|
-
if (err.level == "client-authentication") {
|
|
49
|
-
inquirer
|
|
50
|
-
.prompt([
|
|
51
|
-
{
|
|
52
|
-
name: "key",
|
|
53
|
-
type: "confirm",
|
|
54
|
-
message: "发布应用需要上传公钥, 确定上传?",
|
|
55
|
-
},
|
|
56
|
-
])
|
|
57
|
-
.then(({ key }) => {
|
|
58
|
-
if (key) {
|
|
59
|
-
const api = new API("", host);
|
|
60
|
-
api
|
|
61
|
-
.postPublicKey(fs.readFileSync(pair["public"]))
|
|
62
|
-
.then(() => {
|
|
63
|
-
resolve(true);
|
|
64
|
-
});
|
|
65
|
-
} else {
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
} else {
|
|
70
|
-
reject(err);
|
|
71
|
-
}
|
|
72
|
-
})
|
|
73
|
-
.connect({
|
|
74
|
-
host: hostname,
|
|
75
|
-
port: 2222,
|
|
76
|
-
username: "box",
|
|
77
|
-
retry: 3,
|
|
78
|
-
wait: 500,
|
|
79
|
-
authHandler: [
|
|
80
|
-
{
|
|
81
|
-
type: "publickey",
|
|
82
|
-
username: "box",
|
|
83
|
-
key: fs.readFileSync(pair["private"]),
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
keepaliveInterval: 60000, // 60s
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async getKeyPair() {
|
|
92
|
-
const privateKey = path.join(SSH_CONFIG_DIR, KEY_NAME);
|
|
93
|
-
const publicKey = path.join(SSH_CONFIG_DIR, `${KEY_NAME}.pub`);
|
|
94
|
-
if (fs.existsSync(privateKey) && fs.existsSync(publicKey)) {
|
|
95
|
-
return {
|
|
96
|
-
private: privateKey,
|
|
97
|
-
public: publicKey,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return await this.generate();
|
|
101
|
-
}
|
|
102
|
-
}
|
package/lib/sdk.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import ssh from "docker-modem/lib/ssh.js";
|
|
2
|
-
// import Docker from "./docker/promise.js";
|
|
3
|
-
import Docker from "dockerode";
|
|
4
|
-
import process from "process";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import { Client } from "ssh2";
|
|
7
|
-
import Key from "./key.js";
|
|
8
|
-
import logger from "loglevel";
|
|
9
|
-
|
|
10
|
-
const sshDebug = function () {
|
|
11
|
-
if (process.env["SSH2_DEBUG"]) {
|
|
12
|
-
return logger.debug;
|
|
13
|
-
} else {
|
|
14
|
-
return function () {};
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export async function connectOptions(host) {
|
|
19
|
-
const pairs = await new Key().getKeyPair();
|
|
20
|
-
return {
|
|
21
|
-
host: host,
|
|
22
|
-
port: 2222,
|
|
23
|
-
username: "box",
|
|
24
|
-
retry: 3,
|
|
25
|
-
wait: 500,
|
|
26
|
-
authHandler: [
|
|
27
|
-
{
|
|
28
|
-
type: "publickey",
|
|
29
|
-
username: "box",
|
|
30
|
-
key: fs.readFileSync(pairs["private"]),
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
type: "agent",
|
|
34
|
-
username: "box",
|
|
35
|
-
agent: process.env.SSH_AUTH_SOCK,
|
|
36
|
-
},
|
|
37
|
-
],
|
|
38
|
-
keepaliveInterval: 60000, // 60s
|
|
39
|
-
debug: sshDebug(),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export class DockerClient {
|
|
44
|
-
constructor(host) {
|
|
45
|
-
this.host = host;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async init() {
|
|
49
|
-
this.docker = !!this.host
|
|
50
|
-
? new Docker({
|
|
51
|
-
protocal: "ssh",
|
|
52
|
-
agent: ssh(await connectOptions(this.host)),
|
|
53
|
-
})
|
|
54
|
-
: new Docker();
|
|
55
|
-
|
|
56
|
-
const host = this.host;
|
|
57
|
-
|
|
58
|
-
async function onUncaughtException(e) {
|
|
59
|
-
if (e.code == "ECONNREFUSED") {
|
|
60
|
-
logger.error(`无法连接 sdk 服务, 请确保 ${host} 可以访问`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
} else {
|
|
63
|
-
throw e;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
process.on("uncaughtException", onUncaughtException);
|
|
67
|
-
await this.docker.ping();
|
|
68
|
-
process.off("uncaughtException", onUncaughtException);
|
|
69
|
-
return this.docker;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export class SSHClient {
|
|
74
|
-
// arg can be a simple host name or a ssh connectOptions
|
|
75
|
-
constructor(arg) {
|
|
76
|
-
if (typeof arg == "string") {
|
|
77
|
-
this.opts = connectOptions(arg);
|
|
78
|
-
} else {
|
|
79
|
-
this.opts = arg;
|
|
80
|
-
}
|
|
81
|
-
this.con = new Client();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
connect() {
|
|
85
|
-
return new Promise((resolve, reject) => {
|
|
86
|
-
this.con
|
|
87
|
-
.on("ready", () => resolve(this.con))
|
|
88
|
-
.on("error", (err) => {
|
|
89
|
-
logger.error("ssh client ", err);
|
|
90
|
-
reject(err);
|
|
91
|
-
})
|
|
92
|
-
.on("close", () => resolve(null))
|
|
93
|
-
.connect(this.opts);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
close() {
|
|
98
|
-
this.con.end();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
exec(command, options = {}) {
|
|
102
|
-
return new Promise((resolve, reject) => {
|
|
103
|
-
this.con.exec(command, options, (err, chan) => {
|
|
104
|
-
if (err) return reject(err);
|
|
105
|
-
resolve(chan);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async shell() {
|
|
111
|
-
this.con.shell(
|
|
112
|
-
{
|
|
113
|
-
term: process.env.TERM,
|
|
114
|
-
rows: process.stdout.rows,
|
|
115
|
-
cols: process.stdout.columns,
|
|
116
|
-
},
|
|
117
|
-
(err, stream) => {
|
|
118
|
-
if (err) throw err;
|
|
119
|
-
|
|
120
|
-
stream.on("close", () => {
|
|
121
|
-
process.exit();
|
|
122
|
-
});
|
|
123
|
-
process.stdin.setRawMode(true);
|
|
124
|
-
process.stdin.pipe(stream);
|
|
125
|
-
|
|
126
|
-
// Connect remote output to local stdout
|
|
127
|
-
stream.pipe(process.stdout);
|
|
128
|
-
process.stdout.on("resize", () => {
|
|
129
|
-
// Let the remote end know when the local terminal has been resized
|
|
130
|
-
stream.setWindow(process.stdout.rows, process.stdout.columns, 0, 0);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|