@ps-aux/nodebup 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,7 +59,7 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
59
59
 
60
60
  _defineProperty(this, "outFileName", 'backup.sql');
61
61
 
62
- _defineProperty(this, "backup", ({
62
+ _defineProperty(this, "backup", async ({
63
63
  pgUrl,
64
64
  pgVersion
65
65
  }) => {
@@ -69,16 +69,20 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
69
69
  this.log.info(`Backing up Postgres database, version=${version}`);
70
70
  const connParams = parseConnectionUrl(pgUrl);
71
71
  const pass = connParams.password;
72
- this.fs.inTmpDir('pg-backup', dir => {
72
+ await this.fs.inTmpDir('pg-backup', async dir => {
73
73
  const outputDir = _Path.AbsPath.from(dir);
74
74
 
75
75
  this.log.info('Dumping database to a file');
76
76
  const bashCmds = [`echo "*:*:*:*:${pass}" > ~/.pgpass`, `chmod 400 ~/.pgpass`, `pg_dumpall -d ${pgUrl}`]; // Don't forget that this itself might be run in docker
77
77
  // therefore volume mounts are not usable (will apply to the location at host)
78
78
 
79
- const b = this.sh.execAndReturnBuffer(`docker run --network host ` + `postgres:${version} ` + `bash -c '${bashCmds.join(' && ')}'`);
80
79
  const dumpOut = outputDir.resolve(this.outFileName);
81
- this.fs.writeFile(dumpOut, b);
80
+ const f = this.fs.writeStream(dumpOut);
81
+ await this.sh.asyncExec(`docker run --rm --network host ` + `postgres:${version} ` + `bash -c '${bashCmds.join(' && ')}'`, // f.write
82
+ data => {
83
+ f.write(data);
84
+ });
85
+ f.end();
82
86
  this.log.info('Compressing');
83
87
  const zipOutputName = `pg-backup-${this.now()}.zip`;
84
88
  this.zip.zipDir(outputDir, outputDir.resolve(zipOutputName));
@@ -88,7 +92,7 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
88
92
  });
89
93
  });
90
94
 
91
- _defineProperty(this, "restore", ({
95
+ _defineProperty(this, "restore", async ({
92
96
  pgUrl,
93
97
  pgVersion
94
98
  }) => {
@@ -97,7 +101,7 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
97
101
 
98
102
  parseConnectionUrl(pgUrl);
99
103
  this.log.info(`Restoring Postgres database, version=${version}`);
100
- this.fs.inTmpDir('pg-restore', dirStr => {
104
+ await this.fs.inTmpDir('pg-restore', dirStr => {
101
105
  const dir = _Path.AbsPath.from(dirStr);
102
106
 
103
107
  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.2",
4
4
  "description": "",
5
5
  "module": "lib/index.js",
6
6
  "main": "lib/index.js",