@verdnatura/myt 1.8.6 → 2.0.2
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/README.md +80 -52
- package/assets/myt.default.yml +7 -0
- package/assets/structure.sql +1 -1
- package/{server/Dockerfile.client → docker/client/Dockerfile} +3 -3
- package/docker/server/Dockerfile +37 -0
- package/docker/server/Dockerfile.base +6 -0
- package/docker/server/Dockerfile.myt +35 -0
- package/docker/server/docker-init.sh +36 -0
- package/{server → docker/server}/docker-start.sh +1 -1
- package/lib/command.js +14 -6
- package/lib/docker.js +60 -34
- package/lib/dumper.js +11 -9
- package/lib/exporter-engine.js +4 -4
- package/lib/server.js +2 -8
- package/myt-apply.js +203 -0
- package/myt-build.js +283 -0
- package/myt-clean.js +15 -11
- package/myt-create.js +19 -11
- package/myt-dump.js +41 -36
- package/myt-fixtures.js +6 -6
- package/myt-init.js +5 -3
- package/myt-pull.js +12 -11
- package/myt-push.js +99 -96
- package/myt-run.js +28 -144
- package/myt-start.js +4 -4
- package/myt-version.js +13 -13
- package/myt.js +285 -149
- package/package.json +4 -3
- package/prebuilts/README.md +15 -0
- package/prebuilts/nodegit-v0.28.0-alpha.36-node-v127-linux-x64.tar.gz +0 -0
- package/template/.dockerignore +5 -0
- package/template/myt.config.yml +1 -4
- package/template/package.json +1 -1
- package/template/realms/.keep +0 -0
- package/template/remotes/docker.ini +1 -1
- package/template/remotes/local.ini +1 -1
- package/template/remotes/socket.ini +3 -0
- package/template/structure/.dump/structure.sql +32 -0
- package/server/Dockerfile.base +0 -1
- package/server/Dockerfile.dump +0 -16
- package/server/Dockerfile.server +0 -16
- package/server/docker-import.sh +0 -10
- package/server/docker-init.sh +0 -24
- /package/{server → docker/client}/docker-dump.sh +0 -0
- /package/{server → docker/client}/docker-fixtures.sh +0 -0
- /package/{server → docker/server}/docker.cnf +0 -0
- /package/template/{dump/Dockerfile.base → docker/Dockerfile} +0 -0
- /package/template/{dump/fixtures.after.sql → fixtures/after.sql} +0 -0
- /package/template/{dump/fixtures.before.sql → fixtures/before.sql} +0 -0
- /package/template/{dump/dump.after.sql → structure/after.sql} +0 -0
- /package/template/{dump/dump.before.sql → structure/before.sql} +0 -0
package/myt-run.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
const Myt = require('./myt');
|
|
2
2
|
const Command = require('./lib/command');
|
|
3
|
-
const Push = require('./myt-push');
|
|
4
3
|
const docker = require('./lib/docker');
|
|
5
|
-
const fs = require('fs-extra');
|
|
6
|
-
const path = require('path');
|
|
7
4
|
const Server = require('./lib/server');
|
|
8
|
-
const
|
|
9
|
-
const SqlString = require('sqlstring');
|
|
5
|
+
const Build = require('./myt-build');
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* Builds the database image and runs a container. It only rebuilds the image
|
|
@@ -23,12 +19,12 @@ class Run extends Command {
|
|
|
23
19
|
persist: 'Whether to not use tmpfs mount for MySQL data',
|
|
24
20
|
keep: 'Keep container on failure',
|
|
25
21
|
realm: 'Name of fixture realm to use',
|
|
26
|
-
|
|
22
|
+
ip: 'Bind to container IP instead of localhost'
|
|
27
23
|
},
|
|
28
24
|
operand: 'realm'
|
|
29
25
|
};
|
|
30
26
|
|
|
31
|
-
static
|
|
27
|
+
static args = {
|
|
32
28
|
alias: {
|
|
33
29
|
network: 'n',
|
|
34
30
|
random: 'r',
|
|
@@ -37,84 +33,48 @@ class Run extends Command {
|
|
|
37
33
|
realm: 'm',
|
|
38
34
|
ip: 'i'
|
|
39
35
|
},
|
|
36
|
+
string: [
|
|
37
|
+
'network',
|
|
38
|
+
'realm'
|
|
39
|
+
],
|
|
40
40
|
boolean: [
|
|
41
41
|
'ci',
|
|
42
42
|
'random',
|
|
43
43
|
'persist',
|
|
44
|
-
'keep'
|
|
44
|
+
'keep',
|
|
45
|
+
'ip'
|
|
45
46
|
]
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
static reporter = {
|
|
49
50
|
buildingImage: 'Building container image.',
|
|
50
51
|
runningContainer: 'Running container.',
|
|
51
|
-
mockingDate: 'Mocking date functions.',
|
|
52
|
-
applyingFixtures: 'Applying fixtures.',
|
|
53
|
-
applyingRealms: 'Applying realm fixtures.',
|
|
54
|
-
creatingTriggers: 'Creating triggers.',
|
|
55
52
|
waitingDb: function(dbConfig) {
|
|
56
|
-
console.log(`Waiting for
|
|
53
|
+
console.log(`Waiting for database: ${dbConfig.host}:${dbConfig.port}`);
|
|
57
54
|
}
|
|
58
55
|
};
|
|
59
56
|
|
|
60
|
-
async
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (!await fs.pathExists(`${dumpDataDir}/structure.sql`))
|
|
66
|
-
throw new Error('To run local database you have to create a dump first');
|
|
67
|
-
|
|
68
|
-
// Build base image
|
|
69
|
-
|
|
70
|
-
this.emit('buildingImage');
|
|
71
|
-
|
|
72
|
-
let basePath = dumpDir;
|
|
73
|
-
let baseDockerfile = path.join(dumpDir, 'Dockerfile');
|
|
74
|
-
|
|
75
|
-
if (!await fs.pathExists(baseDockerfile)) {
|
|
76
|
-
basePath = serverDir;
|
|
77
|
-
baseDockerfile = path.join(serverDir, 'Dockerfile.base');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
await docker.build(basePath, {
|
|
81
|
-
tag: 'myt/base',
|
|
82
|
-
file: baseDockerfile
|
|
83
|
-
}, opts.debug);
|
|
84
|
-
|
|
85
|
-
// Build server image
|
|
86
|
-
|
|
87
|
-
await docker.build(serverDir, {
|
|
88
|
-
tag: 'myt/server',
|
|
89
|
-
file: path.join(serverDir, 'Dockerfile.server')
|
|
90
|
-
}, opts.debug);
|
|
91
|
-
|
|
92
|
-
// Build dump image
|
|
93
|
-
|
|
94
|
-
const dumpContext = path.join(opts.mytDir, 'dump');
|
|
95
|
-
await docker.build(dumpContext, {
|
|
96
|
-
tag: opts.code,
|
|
97
|
-
file: path.join(serverDir, 'Dockerfile.dump')
|
|
98
|
-
}, opts.debug);
|
|
99
|
-
|
|
100
|
-
// Run container
|
|
57
|
+
async _run(myt, ctx, cfg, opts) {
|
|
58
|
+
const tag = await myt.run(Build, {
|
|
59
|
+
realm: opts.realm
|
|
60
|
+
});
|
|
101
61
|
|
|
102
62
|
this.emit('runningContainer');
|
|
103
63
|
|
|
104
64
|
const isRandom = opts.random;
|
|
105
|
-
const dbConfig =
|
|
65
|
+
const dbConfig = ctx.dbConfig;
|
|
106
66
|
|
|
107
|
-
|
|
67
|
+
const runOptions = {};
|
|
108
68
|
|
|
109
69
|
if (isRandom)
|
|
110
|
-
runOptions
|
|
70
|
+
Object.assign(runOptions, {publish: '3306'});
|
|
111
71
|
else {
|
|
112
|
-
runOptions
|
|
113
|
-
name:
|
|
72
|
+
Object.assign(runOptions, {
|
|
73
|
+
name: cfg.code,
|
|
114
74
|
publish: `3306:${dbConfig.port}`
|
|
115
|
-
};
|
|
75
|
+
});
|
|
116
76
|
try {
|
|
117
|
-
const server = new Server(new docker.Container(
|
|
77
|
+
const server = new Server(new docker.Container(cfg.code));
|
|
118
78
|
await server.rm();
|
|
119
79
|
} catch (e) {}
|
|
120
80
|
}
|
|
@@ -122,13 +82,15 @@ class Run extends Command {
|
|
|
122
82
|
const {network} = opts;
|
|
123
83
|
if (opts.network)
|
|
124
84
|
runOptions.network = network;
|
|
85
|
+
|
|
125
86
|
if (!opts.persist)
|
|
126
87
|
runOptions.tmpfs = '/var/lib/mysql';
|
|
127
88
|
|
|
128
|
-
Object.assign(runOptions,
|
|
89
|
+
Object.assign(runOptions, {
|
|
129
90
|
detach: true
|
|
130
91
|
});
|
|
131
|
-
|
|
92
|
+
|
|
93
|
+
const ct = await docker.run(tag, null, runOptions, undefined, cfg.debug);
|
|
132
94
|
|
|
133
95
|
try {
|
|
134
96
|
const server = new Server(ct, dbConfig);
|
|
@@ -146,15 +108,15 @@ class Run extends Command {
|
|
|
146
108
|
if (network) {
|
|
147
109
|
host = network != 'host'
|
|
148
110
|
? ctNetworks[network].IPAddress
|
|
149
|
-
: localhost
|
|
111
|
+
: localhost;
|
|
150
112
|
} else {
|
|
151
113
|
host = netSettings.IPAddress
|
|
152
|
-
?? ctNetworks.bridge?.IPAddress
|
|
114
|
+
?? ctNetworks.bridge?.IPAddress;
|
|
153
115
|
}
|
|
154
116
|
port = 3306;
|
|
155
117
|
} else {
|
|
156
118
|
host = localhost;
|
|
157
|
-
port = netSettings.Ports['3306/tcp'][0].HostPort
|
|
119
|
+
port = netSettings.Ports['3306/tcp'][0].HostPort;
|
|
158
120
|
}
|
|
159
121
|
|
|
160
122
|
if (!host)
|
|
@@ -168,76 +130,6 @@ class Run extends Command {
|
|
|
168
130
|
|
|
169
131
|
this.emit('waitingDb', dbConfig);
|
|
170
132
|
await server.wait();
|
|
171
|
-
const conn = await myt.createConnection();
|
|
172
|
-
|
|
173
|
-
// Mock date functions
|
|
174
|
-
|
|
175
|
-
this.emit('mockingDate');
|
|
176
|
-
const mockDateScript = path.join(dumpDir, 'mockDate.sql');
|
|
177
|
-
|
|
178
|
-
if (opts.mockDate) {
|
|
179
|
-
if (!await fs.pathExists(mockDateScript))
|
|
180
|
-
throw new Error(`Date mock enabled but mock script does not exist: ${mockDateScript}`);
|
|
181
|
-
|
|
182
|
-
let sql = await fs.readFile(mockDateScript, 'utf8');
|
|
183
|
-
sql = sql.replace(/@mockDate/g, SqlString.escape(opts.mockDate));
|
|
184
|
-
await connExt.multiQuery(conn, sql);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Apply changes
|
|
188
|
-
|
|
189
|
-
const hasTriggers = await fs.exists(`${dumpDataDir}/triggers.sql`);
|
|
190
|
-
|
|
191
|
-
Object.assign(opts, {
|
|
192
|
-
triggers: !hasTriggers,
|
|
193
|
-
commit: true,
|
|
194
|
-
dbConfig
|
|
195
|
-
});
|
|
196
|
-
await myt.run(Push, opts);
|
|
197
|
-
|
|
198
|
-
// Apply fixtures
|
|
199
|
-
|
|
200
|
-
this.emit('applyingFixtures');
|
|
201
|
-
const fixturesFiles = [
|
|
202
|
-
'fixtures.before',
|
|
203
|
-
'.fixtures',
|
|
204
|
-
'fixtures.after',
|
|
205
|
-
'fixtures.local'
|
|
206
|
-
]
|
|
207
|
-
for (const file of fixturesFiles) {
|
|
208
|
-
if (!await fs.exists(`${dumpDir}/${file}.sql`)) continue;
|
|
209
|
-
await execFile(`dump/${file}`)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Apply realms
|
|
213
|
-
|
|
214
|
-
if(opts.realm) {
|
|
215
|
-
this.emit('applyingRealms');
|
|
216
|
-
const realmDir = `realms/${opts.realm}`;
|
|
217
|
-
let realmFiles = await fs.readdir(`${dumpDir}/${realmDir}`);
|
|
218
|
-
realmFiles = realmFiles.map(file => path.parse(file).name);
|
|
219
|
-
for (const file of realmFiles) {
|
|
220
|
-
await execFile(`${realmDir}/${file}`)
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Create triggers
|
|
225
|
-
|
|
226
|
-
if (!hasTriggers) {
|
|
227
|
-
this.emit('creatingTriggers');
|
|
228
|
-
|
|
229
|
-
for (const schema of opts.schemas) {
|
|
230
|
-
const triggersPath = `${opts.routinesDir}/${schema}/triggers`;
|
|
231
|
-
if (!await fs.pathExists(triggersPath))
|
|
232
|
-
continue;
|
|
233
|
-
|
|
234
|
-
const triggersDir = await fs.readdir(triggersPath);
|
|
235
|
-
for (const triggerFile of triggersDir)
|
|
236
|
-
await connExt.queryFromFile(conn, `${triggersPath}/${triggerFile}`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
await conn.end();
|
|
241
133
|
return server;
|
|
242
134
|
} catch (err) {
|
|
243
135
|
try {
|
|
@@ -245,14 +137,6 @@ class Run extends Command {
|
|
|
245
137
|
} catch (e) {}
|
|
246
138
|
throw err;
|
|
247
139
|
}
|
|
248
|
-
|
|
249
|
-
async function execFile(path){
|
|
250
|
-
await ct.exec(null, 'docker-import.sh',
|
|
251
|
-
[`/workspace/${path}` ],
|
|
252
|
-
'spawn',
|
|
253
|
-
true
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
140
|
}
|
|
257
141
|
}
|
|
258
142
|
|
package/myt-start.js
CHANGED
|
@@ -19,8 +19,8 @@ class Start extends Command {
|
|
|
19
19
|
startingContainer: 'Starting container.'
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
async
|
|
23
|
-
const ct = new Container(
|
|
22
|
+
async _run(myt, ctx, cfg, opts) {
|
|
23
|
+
const ct = new Container(cfg.code);
|
|
24
24
|
let status;
|
|
25
25
|
let exists;
|
|
26
26
|
let server;
|
|
@@ -31,7 +31,7 @@ class Start extends Command {
|
|
|
31
31
|
});
|
|
32
32
|
exists = true;
|
|
33
33
|
} catch (err) {
|
|
34
|
-
server = await myt.run(Run
|
|
34
|
+
server = await myt.run(Run);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
if (exists) {
|
|
@@ -41,7 +41,7 @@ class Start extends Command {
|
|
|
41
41
|
case 'exited':
|
|
42
42
|
this.emit('startingContainer');
|
|
43
43
|
await ct.start();
|
|
44
|
-
server = new Server(ct,
|
|
44
|
+
server = new Server(ct, ctx.dbConfig);
|
|
45
45
|
await server.wait();
|
|
46
46
|
break;
|
|
47
47
|
default:
|
package/myt-version.js
CHANGED
|
@@ -16,7 +16,7 @@ class Version extends Command {
|
|
|
16
16
|
operand: 'name'
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
static
|
|
19
|
+
static args = {
|
|
20
20
|
alias: {
|
|
21
21
|
name: 'n',
|
|
22
22
|
deprecate: 'p'
|
|
@@ -46,7 +46,7 @@ class Version extends Command {
|
|
|
46
46
|
deprecate: 'Generating SQL for deprecated objects deletion.'
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
async
|
|
49
|
+
async _run(myt, ctx, cfg, opts) {
|
|
50
50
|
let newVersionDir;
|
|
51
51
|
|
|
52
52
|
// Fetch last version number
|
|
@@ -61,7 +61,7 @@ class Version extends Command {
|
|
|
61
61
|
FROM version
|
|
62
62
|
WHERE code = ?
|
|
63
63
|
FOR UPDATE`,
|
|
64
|
-
[
|
|
64
|
+
[cfg.code]
|
|
65
65
|
);
|
|
66
66
|
const number = row && row.number;
|
|
67
67
|
const lastNumber = row && row.lastNumber;
|
|
@@ -78,7 +78,7 @@ class Version extends Command {
|
|
|
78
78
|
|
|
79
79
|
const versionDigits = number
|
|
80
80
|
? number.length
|
|
81
|
-
:
|
|
81
|
+
: cfg.versionDigits;
|
|
82
82
|
|
|
83
83
|
newVersion = String(newVersion).padStart(versionDigits, '0');
|
|
84
84
|
|
|
@@ -87,7 +87,7 @@ class Version extends Command {
|
|
|
87
87
|
let versionName = opts.name;
|
|
88
88
|
|
|
89
89
|
const versionNames = new Set();
|
|
90
|
-
const versionDirs = await fs.readdir(
|
|
90
|
+
const versionDirs = await fs.readdir(ctx.versionsDir);
|
|
91
91
|
for (const versionDir of versionDirs) {
|
|
92
92
|
const version = myt.parseVersionDir(versionDir);
|
|
93
93
|
if (!version) continue;
|
|
@@ -117,7 +117,7 @@ class Version extends Command {
|
|
|
117
117
|
// Create version
|
|
118
118
|
|
|
119
119
|
const versionFolder = `${newVersion}-${versionName}`;
|
|
120
|
-
newVersionDir = `${
|
|
120
|
+
newVersionDir = `${ctx.versionsDir}/${versionFolder}`;
|
|
121
121
|
|
|
122
122
|
await conn.query(
|
|
123
123
|
`INSERT INTO version
|
|
@@ -125,13 +125,13 @@ class Version extends Command {
|
|
|
125
125
|
lastNumber = ?
|
|
126
126
|
ON DUPLICATE KEY UPDATE
|
|
127
127
|
lastNumber = VALUES(lastNumber)`,
|
|
128
|
-
[
|
|
128
|
+
[cfg.code, newVersion]
|
|
129
129
|
);
|
|
130
130
|
await fs.mkdir(newVersionDir);
|
|
131
131
|
|
|
132
132
|
if (opts.deprecate) {
|
|
133
133
|
this.emit('deprecate');
|
|
134
|
-
await deprecate(conn,
|
|
134
|
+
await deprecate(conn, cfg, newVersionDir);
|
|
135
135
|
} else
|
|
136
136
|
await fs.writeFile(
|
|
137
137
|
`${newVersionDir}/00-firstScript.sql`,
|
|
@@ -150,12 +150,12 @@ class Version extends Command {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
async function deprecate(conn,
|
|
153
|
+
async function deprecate(conn, cfg, newVersionDir) {
|
|
154
154
|
const now = new Date();
|
|
155
|
-
const minDeprecDate = new Date(now.getTime() -
|
|
156
|
-
const deprecMarkRegex =
|
|
157
|
-
const deprecCommentRegex =
|
|
158
|
-
const deprecDateRegex =
|
|
155
|
+
const minDeprecDate = new Date(now.getTime() - cfg.deprecRetentionPeriod * 24 * 60 * 60 * 1000);
|
|
156
|
+
const deprecMarkRegex = cfg.deprecMarkRegex;
|
|
157
|
+
const deprecCommentRegex = cfg.deprecCommentRegex;
|
|
158
|
+
const deprecDateRegex = cfg.deprecDateRegex;
|
|
159
159
|
const filePath = `${newVersionDir}/00-deprecate.sql`;
|
|
160
160
|
|
|
161
161
|
// Generate the drops of the primary keys
|