@ps-aux/nodebup 0.9.1 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,7 +26,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
26
26
  const parseConnectionUrl = url => {
27
27
  var _url$match;
28
28
 
29
- const regex = /postgres:\/\/(?<username>.*):(?<password>.*)@(?<host>.*):(?<port>\d*)$/;
29
+ // TODO what if there are query params in the end?
30
+ const regex = /postgres:\/\/(?<username>.*):(?<password>.*)@(?<host>.*):(?<port>\d*)(\/(?<database>.*))?$/;
30
31
  const match = (_url$match = url.match(regex)) === null || _url$match === void 0 ? void 0 : _url$match.groups;
31
32
  if (!match || !match.username || !match.password || !match.host || !match.port) throw new Error(`The Postgres connection URL does not match required regex: ${regex.toString()}`);
32
33
  return {
@@ -59,7 +60,7 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
59
60
 
60
61
  _defineProperty(this, "outFileName", 'backup.sql');
61
62
 
62
- _defineProperty(this, "backup", ({
63
+ _defineProperty(this, "backup", async ({
63
64
  pgUrl,
64
65
  pgVersion
65
66
  }) => {
@@ -69,16 +70,20 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
69
70
  this.log.info(`Backing up Postgres database, version=${version}`);
70
71
  const connParams = parseConnectionUrl(pgUrl);
71
72
  const pass = connParams.password;
72
- this.fs.inTmpDir('pg-backup', dir => {
73
+ await this.fs.inTmpDir('pg-backup', async dir => {
73
74
  const outputDir = _Path.AbsPath.from(dir);
74
75
 
75
76
  this.log.info('Dumping database to a file');
76
77
  const bashCmds = [`echo "*:*:*:*:${pass}" > ~/.pgpass`, `chmod 400 ~/.pgpass`, `pg_dumpall -d ${pgUrl}`]; // Don't forget that this itself might be run in docker
77
78
  // therefore volume mounts are not usable (will apply to the location at host)
78
79
 
79
- const b = this.sh.execAndReturnBuffer(`docker run --network host ` + `postgres:${version} ` + `bash -c '${bashCmds.join(' && ')}'`);
80
80
  const dumpOut = outputDir.resolve(this.outFileName);
81
- this.fs.writeFile(dumpOut, b);
81
+ const f = this.fs.writeStream(dumpOut);
82
+ await this.sh.asyncExec(`docker run --rm --network host ` + `postgres:${version} ` + `bash -c '${bashCmds.join(' && ')}'`, // f.write
83
+ data => {
84
+ f.write(data);
85
+ });
86
+ f.end();
82
87
  this.log.info('Compressing');
83
88
  const zipOutputName = `pg-backup-${this.now()}.zip`;
84
89
  this.zip.zipDir(outputDir, outputDir.resolve(zipOutputName));
@@ -88,7 +93,7 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
88
93
  });
89
94
  });
90
95
 
91
- _defineProperty(this, "restore", ({
96
+ _defineProperty(this, "restore", async ({
92
97
  pgUrl,
93
98
  pgVersion
94
99
  }) => {
@@ -97,7 +102,7 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
97
102
 
98
103
  parseConnectionUrl(pgUrl);
99
104
  this.log.info(`Restoring Postgres database, version=${version}`);
100
- this.fs.inTmpDir('pg-restore', dirStr => {
105
+ await this.fs.inTmpDir('pg-restore', dirStr => {
101
106
  const dir = _Path.AbsPath.from(dirStr);
102
107
 
103
108
  storage.restore(dir); // TODO check if the dir contains the with the expected name
package/lib/fs/Fs.js CHANGED
@@ -37,6 +37,11 @@ let Fs = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:
37
37
  _fs.default.writeFileSync(path.str(), content);
38
38
  });
39
39
 
40
+ _defineProperty(this, "writeStream", path => {
41
+ this.log.debug('Writing into file', path);
42
+ return _fs.default.createWriteStream(path.str());
43
+ });
44
+
40
45
  _defineProperty(this, "isFile", path => !this.isDir(path));
41
46
 
42
47
  _defineProperty(this, "ensureIsFile", p => {
@@ -59,11 +64,11 @@ let Fs = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:
59
64
  return _fs.default.readdirSync(path.str()).map(f => path.resolve(f));
60
65
  });
61
66
 
62
- _defineProperty(this, "inTmpDir", (name, withDir) => {
67
+ _defineProperty(this, "inTmpDir", async (name, withDir) => {
63
68
  const dir = this.mkTmpDir(name);
64
69
 
65
70
  try {
66
- withDir(dir);
71
+ await withDir(dir);
67
72
  } finally {
68
73
  this.rmDir(_Path.AbsPath.from(dir));
69
74
  }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var _Fs = require("./Fs");
4
+
5
+ var _Path = require("./path/Path");
6
+
7
+ var _AppLogger = require("../log/AppLogger");
8
+
9
+ it.skip('withTmpDir', async () => {
10
+ const fs = new _Fs.Fs(_Path.AbsPath.from(__dirname), new _AppLogger.AppLogger());
11
+ await fs.inTmpDir('foo', async () => {
12
+ console.log('before');
13
+ const wait = new Promise((res, rej) => {
14
+ setTimeout(res, 1000);
15
+ });
16
+ await wait;
17
+ console.log('after');
18
+ });
19
+ console.log('done');
20
+ });
@@ -35,7 +35,7 @@ class ResticClient {
35
35
  });
36
36
 
37
37
  _defineProperty(this, "runCmd", cmd => {
38
- return this.shell.execAndReturnBuffer(`restic ${cmd}`, {
38
+ return this.shell.execAndReturnString(`restic ${cmd}`, {
39
39
  env: this.env()
40
40
  });
41
41
  });
@@ -11,13 +11,16 @@ var _inversify = require("inversify");
11
11
 
12
12
  var _AppLogger = require("../../log/AppLogger");
13
13
 
14
+ var _child_process = require("child_process");
15
+
14
16
  var _dec, _dec2, _dec3, _class;
15
17
 
16
18
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
17
19
 
18
20
  // TODO copy pasted from my other project
21
+ // TODO don't log the full command as it contains secrets
19
22
  let Shell = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger]), _dec(_class = _dec2(_class = _dec3(_class = class Shell {
20
- constructor(log) {
23
+ constructor(log = (0, _AppLogger.logger)('shell')) {
21
24
  this.log = log;
22
25
 
23
26
  _defineProperty(this, "exec", (cmd, opts = {}) => {
@@ -38,19 +41,31 @@ let Shell = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("desi
38
41
  });
39
42
 
40
43
  _defineProperty(this, "execAndReturnString", (cmd, ops = {}) => {
41
- this.log.debug(cmd, '[stdout consumed]');
44
+ // this.log.debug(cmd, '[stdout consumed]')
42
45
  return (0, _shellCmd.shellCmd)(cmd, {
43
46
  returnStdout: 'string',
44
47
  ...ops
45
48
  });
46
49
  });
47
50
 
48
- _defineProperty(this, "execAndReturnBuffer", (cmd, ops = {}) => {
49
- this.log.debug(cmd, '[stdout consumed]');
50
- return (0, _shellCmd.shellCmd)(cmd, {
51
- returnStdout: 'buffer',
52
- ...ops
51
+ _defineProperty(this, "asyncExec", (cmd, onStdout, ops = {}) => {
52
+ let onDone;
53
+ let onError;
54
+ const p = new Promise((res, rej) => {
55
+ onDone = res;
56
+ onError = rej;
57
+ });
58
+ const r = (0, _child_process.spawn)(cmd, {
59
+ shell: true,
60
+ cwd: ops.cwd,
61
+ env: ops.env
62
+ });
63
+ r.stdout.on('data', onStdout);
64
+ r.stderr.on('data', data => console.error(data.toString()));
65
+ r.on('exit', status => {
66
+ if (status === 0) onDone();else onError(new Error('Exited with non zero return code: ' + status));
53
67
  });
68
+ return p;
54
69
  });
55
70
  }
56
71
 
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ var _Shell = require("./Shell");
4
+
5
+ const bigStdOutCme = () => {
6
+ const times = 5_00_000;
7
+ return `bash -c 'for i in {1..${times}}; do echo "Looong data"; done; echo Done'`;
8
+ }; // Not to be run on CI
9
+
10
+
11
+ it.skip('execAndReturnStream', async () => {
12
+ const sh = new _Shell.Shell(); // The output is too big for the exec buffer
13
+
14
+ expect(() => sh.execAndReturnString(bigStdOutCme())).toThrow('spawnSync /bin/sh ENOBUFS'); //
15
+
16
+ let out = '';
17
+ await sh.asyncExec(bigStdOutCme(), data => {
18
+ out = data.toString().trim();
19
+ });
20
+ expect(out).toEndWith('Done');
21
+ }, 5000_000);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ps-aux/nodebup",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "",
5
5
  "module": "lib/index.js",
6
6
  "main": "lib/index.js",