@verdnatura/myt 1.5.19 → 1.5.21
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/.dockerignore +2 -2
- package/LICENSE +17 -17
- package/README.md +284 -278
- package/assets/db.ini +5 -5
- package/assets/myt.default.yml +28 -11
- package/assets/structure.sql +24 -24
- package/cli.js +4 -4
- package/exporters/event.ejs +18 -18
- package/exporters/event.js +31 -31
- package/exporters/event.sql +19 -19
- package/exporters/function.ejs +17 -17
- package/exporters/function.js +27 -27
- package/exporters/function.sql +16 -16
- package/exporters/procedure.ejs +11 -11
- package/exporters/procedure.js +23 -23
- package/exporters/procedure.sql +14 -14
- package/exporters/trigger.ejs +4 -4
- package/exporters/trigger.js +10 -10
- package/exporters/trigger.sql +13 -13
- package/exporters/view.ejs +7 -7
- package/exporters/view.js +29 -29
- package/exporters/view.sql +12 -12
- package/helpers/local-fixtures.js +79 -0
- package/lib/command.js +19 -13
- package/lib/conn.js +141 -141
- package/lib/docker.js +133 -133
- package/lib/dumper.js +104 -83
- package/lib/exporter-engine.js +112 -112
- package/lib/exporter.js +86 -86
- package/lib/repo.js +29 -29
- package/lib/server.js +71 -71
- package/lib/util.js +7 -7
- package/myt-clean.js +58 -58
- package/myt-create.js +74 -74
- package/myt-dump.js +134 -75
- package/myt-fixtures.js +28 -29
- package/myt-init.js +36 -36
- package/myt-pull.js +183 -183
- package/myt-push.js +575 -568
- package/myt-run.js +190 -177
- package/myt-start.js +54 -54
- package/myt-version.js +218 -218
- package/myt.js +378 -361
- package/package.json +41 -41
- package/server/Dockerfile.base +1 -1
- package/server/Dockerfile.client +14 -14
- package/server/Dockerfile.dump +13 -16
- package/server/Dockerfile.server +25 -25
- package/server/docker-dump.sh +4 -4
- package/server/docker-fixtures.sh +5 -4
- package/server/docker-import.sh +10 -6
- package/server/docker-init.sh +23 -20
- package/server/docker-start.sh +10 -10
- package/server/docker.cnf +9 -9
- package/template/dump/Dockerfile.base +1 -1
- package/template/dump/dump.after.sql +1 -0
- package/template/dump/dump.before.sql +1 -0
- package/template/dump/fixtures.after.sql +1 -0
- package/template/dump/fixtures.before.sql +1 -0
- package/template/myt.config.yml +11 -11
- package/template/package.json +13 -13
- package/template/remotes/docker.ini +4 -4
- package/template/remotes/local.ini +5 -5
- package/template/routines/README.md +1 -1
- package/template/versions/00001-firstVersion/00-firstScript.sql +1 -1
- package/template/versions/README.md +1 -1
- package/template/dump/afterDump.sql +0 -1
- package/template/dump/beforeDump.sql +0 -1
- package/template/dump/fixtures.sql +0 -1
package/lib/command.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base class for Myt commands.
|
|
3
|
-
*/
|
|
4
|
-
module.exports = class MytCommand {
|
|
5
|
-
constructor(myt, opts) {
|
|
6
|
-
this.myt = myt;
|
|
7
|
-
this.opts = opts;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async run(myt, opts) {
|
|
11
|
-
throw new Error('run command not defined');
|
|
12
|
-
}
|
|
13
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Base class for Myt commands.
|
|
3
|
+
*/
|
|
4
|
+
module.exports = class MytCommand {
|
|
5
|
+
constructor(myt, opts) {
|
|
6
|
+
this.myt = myt;
|
|
7
|
+
this.opts = opts;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async run(myt, opts) {
|
|
11
|
+
throw new Error('run command not defined');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
emit(event) {
|
|
15
|
+
const messages = this.constructor.messages;
|
|
16
|
+
if (messages && messages[event])
|
|
17
|
+
console.log(messages[event]);
|
|
18
|
+
}
|
|
19
|
+
}
|
package/lib/conn.js
CHANGED
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Executes an SQL script.
|
|
5
|
-
*
|
|
6
|
-
* @param {Connection} conn MySQL connection object
|
|
7
|
-
* @returns {Array<Result>} The resultset
|
|
8
|
-
*/
|
|
9
|
-
async function queryFromFile(conn, file) {
|
|
10
|
-
const sql = await fs.readFile(file, 'utf8');
|
|
11
|
-
return await this.multiQuery(conn, sql);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Executes a multi-query string.
|
|
16
|
-
*
|
|
17
|
-
* @param {Connection} conn MySQL connection object
|
|
18
|
-
* @param {String} sql SQL multi-query string
|
|
19
|
-
* @returns {Array<Result>} The resultset
|
|
20
|
-
*/
|
|
21
|
-
async function multiQuery(conn, sql) {
|
|
22
|
-
let results = [];
|
|
23
|
-
const stmts = this.querySplit(sql);
|
|
24
|
-
|
|
25
|
-
for (const stmt of stmts)
|
|
26
|
-
results = results.concat(await conn.query(stmt));
|
|
27
|
-
|
|
28
|
-
return results;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Splits an SQL muti-query into a single-query array, it does an small
|
|
33
|
-
* parse to correctly handle the DELIMITER statement.
|
|
34
|
-
*
|
|
35
|
-
* @param {Array<String>} stmts The splitted SQL statements
|
|
36
|
-
*/
|
|
37
|
-
function querySplit(sql) {
|
|
38
|
-
const stmts = [];
|
|
39
|
-
let i,
|
|
40
|
-
char,
|
|
41
|
-
token,
|
|
42
|
-
escaped,
|
|
43
|
-
stmtStart;
|
|
44
|
-
|
|
45
|
-
let delimiter = ';';
|
|
46
|
-
const delimiterRe = /\s*delimiter\s+(\S+)[^\S\r\n]*(?:\r?\n|\r|$)/yi;
|
|
47
|
-
|
|
48
|
-
function begins(str) {
|
|
49
|
-
let j;
|
|
50
|
-
for (j = 0; j < str.length; j++)
|
|
51
|
-
if (sql[i + j] != str[j])
|
|
52
|
-
return false;
|
|
53
|
-
i += j;
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
for (i = 0; i < sql.length;) {
|
|
58
|
-
stmtStart = i;
|
|
59
|
-
|
|
60
|
-
delimiterRe.lastIndex = i;
|
|
61
|
-
const match = sql.match(delimiterRe);
|
|
62
|
-
if (match) {
|
|
63
|
-
delimiter = match[1];
|
|
64
|
-
i += match[0].length;
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let delimiterFound = false;
|
|
69
|
-
while (i < sql.length) {
|
|
70
|
-
char = sql[i];
|
|
71
|
-
|
|
72
|
-
if (token) {
|
|
73
|
-
if (!escaped && begins(token.end))
|
|
74
|
-
token = null;
|
|
75
|
-
else {
|
|
76
|
-
escaped = !escaped && token.escape(char);
|
|
77
|
-
i++;
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
delimiterFound = begins(delimiter);
|
|
81
|
-
if (delimiterFound) break;
|
|
82
|
-
|
|
83
|
-
const tok = tokenIndex.get(char);
|
|
84
|
-
if (tok && begins(tok.start))
|
|
85
|
-
token = tok;
|
|
86
|
-
else
|
|
87
|
-
i++;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
let len = i - stmtStart;
|
|
92
|
-
if (delimiterFound) len -= delimiter.length;
|
|
93
|
-
const stmt = sql.substr(stmtStart, len);
|
|
94
|
-
|
|
95
|
-
if (!/^\s*$/.test(stmt))
|
|
96
|
-
stmts.push(stmt);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return stmts;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const tokens = {
|
|
103
|
-
string: {
|
|
104
|
-
start: '\'',
|
|
105
|
-
end: '\'',
|
|
106
|
-
escape: char => char == '\'' || char == '\\'
|
|
107
|
-
},
|
|
108
|
-
quotedString: {
|
|
109
|
-
start: '"',
|
|
110
|
-
end: '"',
|
|
111
|
-
escape: char => char == '"' || char == '\\'
|
|
112
|
-
},
|
|
113
|
-
id: {
|
|
114
|
-
start: '`',
|
|
115
|
-
end: '`',
|
|
116
|
-
escape: char => char == '`'
|
|
117
|
-
},
|
|
118
|
-
multiComment: {
|
|
119
|
-
start: '/*',
|
|
120
|
-
end: '*/',
|
|
121
|
-
escape: () => false
|
|
122
|
-
},
|
|
123
|
-
singleComment: {
|
|
124
|
-
start: '-- ',
|
|
125
|
-
end: '\n',
|
|
126
|
-
escape: () => false
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const tokenIndex = new Map();
|
|
131
|
-
for (const tokenId in tokens) {
|
|
132
|
-
const token = tokens[tokenId];
|
|
133
|
-
tokenIndex.set(token.start[0], token);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
module.exports = {
|
|
137
|
-
queryFromFile,
|
|
138
|
-
multiQuery,
|
|
139
|
-
querySplit,
|
|
140
|
-
tokens
|
|
141
|
-
};
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Executes an SQL script.
|
|
5
|
+
*
|
|
6
|
+
* @param {Connection} conn MySQL connection object
|
|
7
|
+
* @returns {Array<Result>} The resultset
|
|
8
|
+
*/
|
|
9
|
+
async function queryFromFile(conn, file) {
|
|
10
|
+
const sql = await fs.readFile(file, 'utf8');
|
|
11
|
+
return await this.multiQuery(conn, sql);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Executes a multi-query string.
|
|
16
|
+
*
|
|
17
|
+
* @param {Connection} conn MySQL connection object
|
|
18
|
+
* @param {String} sql SQL multi-query string
|
|
19
|
+
* @returns {Array<Result>} The resultset
|
|
20
|
+
*/
|
|
21
|
+
async function multiQuery(conn, sql) {
|
|
22
|
+
let results = [];
|
|
23
|
+
const stmts = this.querySplit(sql);
|
|
24
|
+
|
|
25
|
+
for (const stmt of stmts)
|
|
26
|
+
results = results.concat(await conn.query(stmt));
|
|
27
|
+
|
|
28
|
+
return results;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Splits an SQL muti-query into a single-query array, it does an small
|
|
33
|
+
* parse to correctly handle the DELIMITER statement.
|
|
34
|
+
*
|
|
35
|
+
* @param {Array<String>} stmts The splitted SQL statements
|
|
36
|
+
*/
|
|
37
|
+
function querySplit(sql) {
|
|
38
|
+
const stmts = [];
|
|
39
|
+
let i,
|
|
40
|
+
char,
|
|
41
|
+
token,
|
|
42
|
+
escaped,
|
|
43
|
+
stmtStart;
|
|
44
|
+
|
|
45
|
+
let delimiter = ';';
|
|
46
|
+
const delimiterRe = /\s*delimiter\s+(\S+)[^\S\r\n]*(?:\r?\n|\r|$)/yi;
|
|
47
|
+
|
|
48
|
+
function begins(str) {
|
|
49
|
+
let j;
|
|
50
|
+
for (j = 0; j < str.length; j++)
|
|
51
|
+
if (sql[i + j] != str[j])
|
|
52
|
+
return false;
|
|
53
|
+
i += j;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (i = 0; i < sql.length;) {
|
|
58
|
+
stmtStart = i;
|
|
59
|
+
|
|
60
|
+
delimiterRe.lastIndex = i;
|
|
61
|
+
const match = sql.match(delimiterRe);
|
|
62
|
+
if (match) {
|
|
63
|
+
delimiter = match[1];
|
|
64
|
+
i += match[0].length;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let delimiterFound = false;
|
|
69
|
+
while (i < sql.length) {
|
|
70
|
+
char = sql[i];
|
|
71
|
+
|
|
72
|
+
if (token) {
|
|
73
|
+
if (!escaped && begins(token.end))
|
|
74
|
+
token = null;
|
|
75
|
+
else {
|
|
76
|
+
escaped = !escaped && token.escape(char);
|
|
77
|
+
i++;
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
delimiterFound = begins(delimiter);
|
|
81
|
+
if (delimiterFound) break;
|
|
82
|
+
|
|
83
|
+
const tok = tokenIndex.get(char);
|
|
84
|
+
if (tok && begins(tok.start))
|
|
85
|
+
token = tok;
|
|
86
|
+
else
|
|
87
|
+
i++;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let len = i - stmtStart;
|
|
92
|
+
if (delimiterFound) len -= delimiter.length;
|
|
93
|
+
const stmt = sql.substr(stmtStart, len);
|
|
94
|
+
|
|
95
|
+
if (!/^\s*$/.test(stmt))
|
|
96
|
+
stmts.push(stmt);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return stmts;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const tokens = {
|
|
103
|
+
string: {
|
|
104
|
+
start: '\'',
|
|
105
|
+
end: '\'',
|
|
106
|
+
escape: char => char == '\'' || char == '\\'
|
|
107
|
+
},
|
|
108
|
+
quotedString: {
|
|
109
|
+
start: '"',
|
|
110
|
+
end: '"',
|
|
111
|
+
escape: char => char == '"' || char == '\\'
|
|
112
|
+
},
|
|
113
|
+
id: {
|
|
114
|
+
start: '`',
|
|
115
|
+
end: '`',
|
|
116
|
+
escape: char => char == '`'
|
|
117
|
+
},
|
|
118
|
+
multiComment: {
|
|
119
|
+
start: '/*',
|
|
120
|
+
end: '*/',
|
|
121
|
+
escape: () => false
|
|
122
|
+
},
|
|
123
|
+
singleComment: {
|
|
124
|
+
start: '-- ',
|
|
125
|
+
end: '\n',
|
|
126
|
+
escape: () => false
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const tokenIndex = new Map();
|
|
131
|
+
for (const tokenId in tokens) {
|
|
132
|
+
const token = tokens[tokenId];
|
|
133
|
+
tokenIndex.set(token.start[0], token);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = {
|
|
137
|
+
queryFromFile,
|
|
138
|
+
multiQuery,
|
|
139
|
+
querySplit,
|
|
140
|
+
tokens
|
|
141
|
+
};
|
package/lib/docker.js
CHANGED
|
@@ -1,133 +1,133 @@
|
|
|
1
|
-
const spawn = require('child_process').spawn;
|
|
2
|
-
const execFile = require('child_process').execFile;
|
|
3
|
-
const camelToSnake = require('./util').camelToSnake;
|
|
4
|
-
|
|
5
|
-
const docker = {
|
|
6
|
-
async run(image, commandArgs, options, execOptions) {
|
|
7
|
-
const args = commandArgs
|
|
8
|
-
? [image].concat(commandArgs)
|
|
9
|
-
: image;
|
|
10
|
-
const execMode = options.detach ? 'exec' : 'spawn';
|
|
11
|
-
|
|
12
|
-
const child = await this.command('run',
|
|
13
|
-
args,
|
|
14
|
-
options,
|
|
15
|
-
execMode,
|
|
16
|
-
execOptions
|
|
17
|
-
);
|
|
18
|
-
return options.detach
|
|
19
|
-
? new Container(child.stdout.trim())
|
|
20
|
-
: child;
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
async build(url, options, execOptions) {
|
|
24
|
-
return await this.command('build',
|
|
25
|
-
url,
|
|
26
|
-
options,
|
|
27
|
-
'spawn',
|
|
28
|
-
execOptions
|
|
29
|
-
);
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
async start(id, options) {
|
|
33
|
-
const ct = new Container(id);
|
|
34
|
-
await ct.start(options);
|
|
35
|
-
return ct;
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
async stop(id, options) {
|
|
39
|
-
const ct = new Container(id);
|
|
40
|
-
return await ct.stop(options);
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
async rm(id, options) {
|
|
44
|
-
const ct = new Container(id);
|
|
45
|
-
return await ct.rm(options);
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
async inspect(id, options) {
|
|
49
|
-
const ct = new Container(id);
|
|
50
|
-
return await ct.inspect(options);
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
async command(command, args, options, execMode, execOptions) {
|
|
54
|
-
const execArgs = [command];
|
|
55
|
-
|
|
56
|
-
if (options)
|
|
57
|
-
for (const option in options) {
|
|
58
|
-
execArgs.push(`--${camelToSnake(option)}`);
|
|
59
|
-
if (typeof options[option] !== 'boolean')
|
|
60
|
-
execArgs.push(options[option]);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (Array.isArray(args))
|
|
64
|
-
Array.prototype.push.apply(execArgs, args);
|
|
65
|
-
else if (args)
|
|
66
|
-
execArgs.push(args);
|
|
67
|
-
|
|
68
|
-
return await new Promise((resolve, reject) => {
|
|
69
|
-
if (execMode == 'spawn') {
|
|
70
|
-
if (execOptions === true)
|
|
71
|
-
execOptions = {
|
|
72
|
-
stdio: [
|
|
73
|
-
process.stdin,
|
|
74
|
-
process.stdout,
|
|
75
|
-
process.stderr
|
|
76
|
-
]
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const child = spawn('docker', execArgs, execOptions || undefined);
|
|
80
|
-
child.on('exit', code => {
|
|
81
|
-
if (code !== 0) {
|
|
82
|
-
const quotedArgs = execArgs
|
|
83
|
-
.map(x => /\s/g.test(x) ? `"${x}"` : x)
|
|
84
|
-
.join(' ');
|
|
85
|
-
reject(new Error(`Docker exit code ${code}: 'docker ${quotedArgs}'`));
|
|
86
|
-
} else
|
|
87
|
-
resolve(code);
|
|
88
|
-
});
|
|
89
|
-
} else {
|
|
90
|
-
execFile('docker', execArgs, (err, stdout, stderr) => {
|
|
91
|
-
if (err)
|
|
92
|
-
reject(err);
|
|
93
|
-
else
|
|
94
|
-
resolve({stdout, stderr});
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
class Container {
|
|
102
|
-
constructor(id) {
|
|
103
|
-
if (!id)
|
|
104
|
-
throw new Error('Container id argument is required');
|
|
105
|
-
this.id = id;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async start(options) {
|
|
109
|
-
await docker.command('start', this.id, options);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async stop(options) {
|
|
113
|
-
await docker.command('stop', this.id, options);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async rm(options) {
|
|
117
|
-
await docker.command('rm', this.id, options);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async inspect(options) {
|
|
121
|
-
const child = await docker.command('inspect', this.id, options);
|
|
122
|
-
return JSON.parse(child.stdout);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async exec(options, command, commandArgs, execMode, execOptions) {
|
|
126
|
-
let args = [this.id, command];
|
|
127
|
-
if (commandArgs) args = args.concat(commandArgs);
|
|
128
|
-
await docker.command('exec', args, options, execMode, execOptions);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = docker;
|
|
133
|
-
module.exports.Container = Container;
|
|
1
|
+
const spawn = require('child_process').spawn;
|
|
2
|
+
const execFile = require('child_process').execFile;
|
|
3
|
+
const camelToSnake = require('./util').camelToSnake;
|
|
4
|
+
|
|
5
|
+
const docker = {
|
|
6
|
+
async run(image, commandArgs, options, execOptions) {
|
|
7
|
+
const args = commandArgs
|
|
8
|
+
? [image].concat(commandArgs)
|
|
9
|
+
: image;
|
|
10
|
+
const execMode = options.detach ? 'exec' : 'spawn';
|
|
11
|
+
|
|
12
|
+
const child = await this.command('run',
|
|
13
|
+
args,
|
|
14
|
+
options,
|
|
15
|
+
execMode,
|
|
16
|
+
execOptions
|
|
17
|
+
);
|
|
18
|
+
return options.detach
|
|
19
|
+
? new Container(child.stdout.trim())
|
|
20
|
+
: child;
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async build(url, options, execOptions) {
|
|
24
|
+
return await this.command('build',
|
|
25
|
+
url,
|
|
26
|
+
options,
|
|
27
|
+
'spawn',
|
|
28
|
+
execOptions
|
|
29
|
+
);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
async start(id, options) {
|
|
33
|
+
const ct = new Container(id);
|
|
34
|
+
await ct.start(options);
|
|
35
|
+
return ct;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async stop(id, options) {
|
|
39
|
+
const ct = new Container(id);
|
|
40
|
+
return await ct.stop(options);
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async rm(id, options) {
|
|
44
|
+
const ct = new Container(id);
|
|
45
|
+
return await ct.rm(options);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
async inspect(id, options) {
|
|
49
|
+
const ct = new Container(id);
|
|
50
|
+
return await ct.inspect(options);
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
async command(command, args, options, execMode, execOptions) {
|
|
54
|
+
const execArgs = [command];
|
|
55
|
+
|
|
56
|
+
if (options)
|
|
57
|
+
for (const option in options) {
|
|
58
|
+
execArgs.push(`--${camelToSnake(option)}`);
|
|
59
|
+
if (typeof options[option] !== 'boolean')
|
|
60
|
+
execArgs.push(options[option]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (Array.isArray(args))
|
|
64
|
+
Array.prototype.push.apply(execArgs, args);
|
|
65
|
+
else if (args)
|
|
66
|
+
execArgs.push(args);
|
|
67
|
+
|
|
68
|
+
return await new Promise((resolve, reject) => {
|
|
69
|
+
if (execMode == 'spawn') {
|
|
70
|
+
if (execOptions === true)
|
|
71
|
+
execOptions = {
|
|
72
|
+
stdio: [
|
|
73
|
+
process.stdin,
|
|
74
|
+
process.stdout,
|
|
75
|
+
process.stderr
|
|
76
|
+
]
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const child = spawn('docker', execArgs, execOptions || undefined);
|
|
80
|
+
child.on('exit', code => {
|
|
81
|
+
if (code !== 0) {
|
|
82
|
+
const quotedArgs = execArgs
|
|
83
|
+
.map(x => /\s/g.test(x) ? `"${x}"` : x)
|
|
84
|
+
.join(' ');
|
|
85
|
+
reject(new Error(`Docker exit code ${code}: 'docker ${quotedArgs}'`));
|
|
86
|
+
} else
|
|
87
|
+
resolve(code);
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
execFile('docker', execArgs, (err, stdout, stderr) => {
|
|
91
|
+
if (err)
|
|
92
|
+
reject(err);
|
|
93
|
+
else
|
|
94
|
+
resolve({stdout, stderr});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
class Container {
|
|
102
|
+
constructor(id) {
|
|
103
|
+
if (!id)
|
|
104
|
+
throw new Error('Container id argument is required');
|
|
105
|
+
this.id = id;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async start(options) {
|
|
109
|
+
await docker.command('start', this.id, options);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async stop(options) {
|
|
113
|
+
await docker.command('stop', this.id, options);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async rm(options) {
|
|
117
|
+
await docker.command('rm', this.id, options);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async inspect(options) {
|
|
121
|
+
const child = await docker.command('inspect', this.id, options);
|
|
122
|
+
return JSON.parse(child.stdout);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async exec(options, command, commandArgs, execMode, execOptions) {
|
|
126
|
+
let args = [this.id, command];
|
|
127
|
+
if (commandArgs) args = args.concat(commandArgs);
|
|
128
|
+
await docker.command('exec', args, options, execMode, execOptions);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = docker;
|
|
133
|
+
module.exports.Container = Container;
|