@ps-aux/nodebup 0.9.1 → 0.9.3

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.
@@ -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",