@ps-aux/nodebup 0.7.3 → 0.9.0

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.
@@ -23,7 +23,7 @@ var _Path = require("../../fs/path/Path");
23
23
 
24
24
  var _config = require("../../config");
25
25
 
26
- var _StorageBackendProvider = require("../../storage/StorageBackendProvider");
26
+ var _BackupStorageProvider = require("../../storage/BackupStorageProvider");
27
27
 
28
28
  var _dec, _dec2, _dec3, _dec4, _class;
29
29
 
@@ -31,7 +31,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
31
31
 
32
32
  let AggregateBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = function (target, key) {
33
33
  return (0, _inversify.inject)(_ContextSymbols.AppConfig_)(target, undefined, 6);
34
- }, _dec3 = Reflect.metadata("design:type", Function), _dec4 = Reflect.metadata("design:paramtypes", [typeof _Gpg.Gpg === "undefined" ? Object : _Gpg.Gpg, typeof _SshKeyManager.SshKeyManager === "undefined" ? Object : _SshKeyManager.SshKeyManager, typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _FsSyncer.FsSyncer === "undefined" ? Object : _FsSyncer.FsSyncer, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _StorageBackendProvider.StorageBackendProvider === "undefined" ? Object : _StorageBackendProvider.StorageBackendProvider, typeof _config.Config === "undefined" ? Object : _config.Config]), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = class AggregateBackupController {
34
+ }, _dec3 = Reflect.metadata("design:type", Function), _dec4 = Reflect.metadata("design:paramtypes", [typeof _Gpg.Gpg === "undefined" ? Object : _Gpg.Gpg, typeof _SshKeyManager.SshKeyManager === "undefined" ? Object : _SshKeyManager.SshKeyManager, typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _FsSyncer.FsSyncer === "undefined" ? Object : _FsSyncer.FsSyncer, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _BackupStorageProvider.BackupStorageProvider === "undefined" ? Object : _BackupStorageProvider.BackupStorageProvider, typeof _config.Config === "undefined" ? Object : _config.Config]), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = class AggregateBackupController {
35
35
  constructor(gpg, ssh, fs, fsSyncer, log, storageProvider, cfg) {
36
36
  this.gpg = gpg;
37
37
  this.ssh = ssh;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DirBackupController = void 0;
7
+
8
+ var _inversify = require("inversify");
9
+
10
+ var _AppLogger = require("../../log/AppLogger");
11
+
12
+ var _Path = require("../../fs/path/Path");
13
+
14
+ var _BackupStorageProvider = require("../../storage/BackupStorageProvider");
15
+
16
+ var _dec, _dec2, _dec3, _class;
17
+
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; }
19
+
20
+ let DirBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _BackupStorageProvider.BackupStorageProvider === "undefined" ? Object : _BackupStorageProvider.BackupStorageProvider]), _dec(_class = _dec2(_class = _dec3(_class = class DirBackupController {
21
+ constructor(log, storageProvider) {
22
+ this.log = log;
23
+ this.storageProvider = storageProvider;
24
+
25
+ _defineProperty(this, "backup", inp => {
26
+ const storage = this.storageProvider.provide();
27
+
28
+ const path = _Path.AbsPath.from(inp.path);
29
+
30
+ this.log.info(`Backing up from ${path} to '${storage}'`);
31
+ storage.store(path);
32
+ });
33
+
34
+ _defineProperty(this, "restore", inp => {
35
+ const storage = this.storageProvider.provide();
36
+
37
+ const path = _Path.AbsPath.from(inp.path);
38
+
39
+ this.log.info(`Restoring from '${storage}' to ${path}`);
40
+ storage.restore(path);
41
+ });
42
+ }
43
+
44
+ }) || _class) || _class) || _class);
45
+ exports.DirBackupController = DirBackupController;
@@ -15,7 +15,7 @@ var _Shell = require("../../tools/shell/Shell");
15
15
 
16
16
  var _Path = require("../../fs/path/Path");
17
17
 
18
- var _StorageBackendProvider = require("../../storage/StorageBackendProvider");
18
+ var _BackupStorageProvider = require("../../storage/BackupStorageProvider");
19
19
 
20
20
  var _Zipper = require("../../tools/compression/Zipper");
21
21
 
@@ -37,7 +37,7 @@ const parseConnectionUrl = url => {
37
37
  };
38
38
  };
39
39
 
40
- let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _StorageBackendProvider.StorageBackendProvider === "undefined" ? Object : _StorageBackendProvider.StorageBackendProvider, typeof _Shell.Shell === "undefined" ? Object : _Shell.Shell, typeof _Zipper.Zipper === "undefined" ? Object : _Zipper.Zipper]), _dec(_class = _dec2(_class = _dec3(_class = (_temp = _class2 = class PgBackupController {
40
+ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _BackupStorageProvider.BackupStorageProvider === "undefined" ? Object : _BackupStorageProvider.BackupStorageProvider, typeof _Shell.Shell === "undefined" ? Object : _Shell.Shell, typeof _Zipper.Zipper === "undefined" ? Object : _Zipper.Zipper]), _dec(_class = _dec2(_class = _dec3(_class = (_temp = _class2 = class PgBackupController {
41
41
  constructor( // private gpg: Gpg,
42
42
  // private ssh: SshKeyManager,
43
43
  fs, // private fsSyncer: FsSyncer,
@@ -73,7 +73,8 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
73
73
  const outputDir = _Path.AbsPath.from(dir);
74
74
 
75
75
  this.log.info('Dumping database to a file');
76
- const bashCmds = [`echo "*:*:*:*:${pass}" > ~/.pgpass`, `chmod 400 ~/.pgpass`, `pg_dumpall -d ${pgUrl}`]; // TODO improve sh logging to avoid showing secrets
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
+ // therefore volume mounts are not usable (will apply to the location at host)
77
78
 
78
79
  const b = this.sh.execAndReturnBuffer(`docker run --network host ` + `postgres:${version} ` + `bash -c '${bashCmds.join(' && ')}'`);
79
80
  const dumpOut = outputDir.resolve(this.outFileName);
@@ -100,11 +101,14 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
100
101
  const dir = _Path.AbsPath.from(dirStr);
101
102
 
102
103
  storage.restore(dir); // TODO check if the dir contains the with the expected name
104
+ // TODO add e2e test for docker
103
105
 
104
106
  const zipFile = this.fs.listFiles(dir)[0];
105
107
  this.zip.unzipDir(zipFile, dir);
106
108
  this.fs.rmFile(zipFile);
107
- const outFile = this.fs.listFiles(dir)[0];
109
+ const outFile = this.fs.listFiles(dir)[0]; // Don't forget that this itself might be run in docker
110
+ // therefore volume mounts are not usable (will apply to the location at host)
111
+
108
112
  this.sh.exec(`docker run --network host -i ` + `postgres:${version} ` + `psql ${pgUrl} -v ON_ERROR_STOP=0 < ${outFile.str()}`);
109
113
  });
110
114
  });
package/lib/cli/app.js CHANGED
@@ -17,7 +17,7 @@ var _AggregateBackupController = require("../bup/aggregate/AggregateBackupContro
17
17
 
18
18
  var _ResticController = require("../storage/restic/ResticController");
19
19
 
20
- var _DataBackupController = require("../bup/dir/DataBackupController");
20
+ var _DirBackupController = require("../bup/dir/DirBackupController");
21
21
 
22
22
  var _PgBackupController = require("../bup/pg/PgBackupController");
23
23
 
@@ -43,27 +43,38 @@ const singleStorageOptions = [storageNameOpt, {
43
43
  convertCase: true,
44
44
  fromConfig: 'storage.credentials'
45
45
  }];
46
+ const backupTagOption = {
47
+ name: 'backup-tag',
48
+ convertCase: true
49
+ };
50
+ const backupOptions = [backupTagOption];
51
+ const restoreOptions = [backupTagOption, {
52
+ name: 'backup-snapshot-id',
53
+ convertCase: true
54
+ }];
46
55
 
47
56
  const createApp = () => _nclif.CliApp.of({
48
57
  commands: {
49
- data: (0, _nclif.cmdGroup)({
58
+ dir: (0, _nclif.cmdGroup)({
50
59
  options: singleStorageOptions,
51
60
  commands: {
52
61
  backup: (0, _nclif.cmd)({
53
62
  description: 'Backup a dir to the given storage',
63
+ options: backupOptions,
54
64
  positionals: [{
55
65
  name: 'path',
56
66
  required: true
57
67
  }],
58
- run: (cmd, c) => c.get(_DataBackupController.DataBackupController).storage(cmd).backup()
68
+ run: (cmd, c) => c.get(_DirBackupController.DirBackupController).backup(cmd)
59
69
  }),
60
70
  restore: (0, _nclif.cmd)({
61
71
  description: 'Restore the storage to the given dir',
72
+ options: restoreOptions,
62
73
  positionals: [{
63
74
  name: 'path',
64
75
  required: true
65
76
  }],
66
- run: (cmd, c) => c.get(_DataBackupController.DataBackupController).storage(cmd).restore()
77
+ run: (cmd, c) => c.get(_DirBackupController.DirBackupController).restore(cmd)
67
78
  })
68
79
  }
69
80
  }),
@@ -90,10 +101,22 @@ const createApp = () => _nclif.CliApp.of({
90
101
 
91
102
  exports.createApp = createApp;
92
103
  const restic = (0, _nclif.cmdGroup)({
104
+ options: singleStorageOptions,
93
105
  commands: {
94
106
  'init-repo': (0, _nclif.cmd)({
95
- options: singleStorageOptions,
96
107
  run: (_, c) => c.get(_ResticController.ResticController).initRepo()
108
+ }),
109
+ snapshots: (0, _nclif.cmd)({
110
+ run: (_, c, p) => c.get(_ResticController.ResticController).listSnapshots(p.stdout)
111
+ }),
112
+ cmd: (0, _nclif.cmd)({
113
+ positionals: [{
114
+ name: 'cmd',
115
+ required: true
116
+ }],
117
+ run: ({
118
+ cmd
119
+ }, c, p) => c.get(_ResticController.ResticController).runResticCmd(cmd, p.stdout)
97
120
  })
98
121
  }
99
122
  });
@@ -111,9 +134,11 @@ const pg = (0, _nclif.cmdGroup)({
111
134
  }],
112
135
  commands: {
113
136
  backup: (0, _nclif.cmd)({
137
+ options: backupOptions,
114
138
  run: (inp, c) => c.get(_PgBackupController.PgBackupController).backup(inp)
115
139
  }),
116
140
  restore: (0, _nclif.cmd)({
141
+ options: restoreOptions,
117
142
  run: (inp, c) => c.get(_PgBackupController.PgBackupController).restore(inp)
118
143
  })
119
144
  }
@@ -23,17 +23,17 @@ var _AggregateBackupController = require("../bup/aggregate/AggregateBackupContro
23
23
 
24
24
  var _AppLogger = require("../log/AppLogger");
25
25
 
26
- var _StorageBackendProvider = require("../storage/StorageBackendProvider");
26
+ var _BackupStorageProvider = require("../storage/BackupStorageProvider");
27
27
 
28
- var _ResticClientFactory = require("../storage/restic/ResticClientFactory");
28
+ var _ResticFactory = require("../storage/restic/ResticFactory");
29
29
 
30
30
  var _ResticController = require("../storage/restic/ResticController");
31
31
 
32
32
  var _B2CredentialsProvider = require("../storage/b2/B2CredentialsProvider");
33
33
 
34
- var _RCloneClientFactory = require("../storage/rclone/RCloneClientFactory");
34
+ var _RCloneFactory = require("../storage/rclone/RCloneFactory");
35
35
 
36
- var _DataBackupController = require("../bup/dir/DataBackupController");
36
+ var _DirBackupController = require("../bup/dir/DirBackupController");
37
37
 
38
38
  var _StorageConfigProvider = require("../storage/StorageConfigProvider");
39
39
 
@@ -49,7 +49,7 @@ const createContext = (cfg, inp) => {
49
49
  c.bind(_ContextSymbols.Log_).toConstantValue(log);
50
50
  c.bind(_AppLogger.AppLogger).toConstantValue(log);
51
51
  c.bind(_Fs.Fs).toConstantValue(new _Fs.Fs(cfg.pwd, log));
52
- const self = [_Gpg.Gpg, _Shell.Shell, _FsSyncer.FsSyncer, _SshKeyManager.SshKeyManager, _StorageBackendProvider.StorageBackendProvider, _StorageConfigProvider.StorageConfigProvider, _ResticClientFactory.ResticClientFactory, _AggregateBackupController.AggregateBackupController, _ResticController.ResticController, _B2CredentialsProvider.B2CredentialsProvider, _RCloneClientFactory.RCloneClientFactory, _DataBackupController.DataBackupController, _PgBackupController.PgBackupController, _Zipper.Zipper];
52
+ const self = [_Gpg.Gpg, _Shell.Shell, _FsSyncer.FsSyncer, _SshKeyManager.SshKeyManager, _BackupStorageProvider.BackupStorageProvider, _StorageConfigProvider.StorageConfigProvider, _ResticFactory.ResticFactory, _AggregateBackupController.AggregateBackupController, _ResticController.ResticController, _B2CredentialsProvider.B2CredentialsProvider, _RCloneFactory.RCloneFactory, _DirBackupController.DirBackupController, _PgBackupController.PgBackupController, _Zipper.Zipper];
53
53
  self.forEach(s => c.bind(s).toSelf());
54
54
  return c;
55
55
  };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.AppLogger = void 0;
6
+ exports.logger = exports.AppLogger = void 0;
7
7
 
8
8
  var _ConsoleLogger = require("./ConsoleLogger");
9
9
 
@@ -26,5 +26,10 @@ let AppLogger = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("
26
26
  if (mute) this.log.setEnabled(false);
27
27
  }
28
28
 
29
- }) || _class) || _class) || _class);
30
- exports.AppLogger = AppLogger;
29
+ }) || _class) || _class) || _class); // TODO make use of the name for logging
30
+
31
+ exports.AppLogger = AppLogger;
32
+
33
+ const logger = name => new AppLogger();
34
+
35
+ exports.logger = logger;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.BackupStorage = void 0;
7
+
8
+ 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; }
9
+
10
+ class BackupStorage {
11
+ constructor(backend, props) {
12
+ this.backend = backend;
13
+ this.props = props;
14
+
15
+ _defineProperty(this, "store", from => {
16
+ const {
17
+ tag
18
+ } = this.props;
19
+ const tags = tag ? [tag] : undefined;
20
+ this.backend.backup(from, tags);
21
+ });
22
+
23
+ _defineProperty(this, "restore", to => {
24
+ const {
25
+ snapshotId
26
+ } = this.props;
27
+ if (snapshotId) this.backend.restoreSnapshot(to, snapshotId);else this.backend.restoreLatest(to);
28
+ });
29
+ }
30
+
31
+ }
32
+
33
+ exports.BackupStorage = BackupStorage;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.BackupStorageProvider = void 0;
7
+
8
+ var _inversify = require("inversify");
9
+
10
+ var _types = require("./types");
11
+
12
+ var _ResticFactory = require("./restic/ResticFactory");
13
+
14
+ var _RCloneFactory = require("./rclone/RCloneFactory");
15
+
16
+ var _StorageConfigProvider = require("./StorageConfigProvider");
17
+
18
+ var _BackupStorage = require("./BackupStorage");
19
+
20
+ var _dec, _dec2, _dec3, _class;
21
+
22
+ 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; }
23
+
24
+ let BackupStorageProvider = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _ResticFactory.ResticFactory === "undefined" ? Object : _ResticFactory.ResticFactory, typeof _RCloneFactory.RCloneFactory === "undefined" ? Object : _RCloneFactory.RCloneFactory, typeof _StorageConfigProvider.StorageConfigProvider === "undefined" ? Object : _StorageConfigProvider.StorageConfigProvider]), _dec(_class = _dec2(_class = _dec3(_class = class BackupStorageProvider {
25
+ constructor(resticFac, rcloneFac, cfgProvider) {
26
+ this.resticFac = resticFac;
27
+ this.rcloneFac = rcloneFac;
28
+ this.cfgProvider = cfgProvider;
29
+
30
+ _defineProperty(this, "provide", () => {
31
+ const cfg = this.cfgProvider.provide();
32
+ const back = this.getBackend(cfg);
33
+ return new _BackupStorage.BackupStorage(back, cfg.backup);
34
+ });
35
+
36
+ _defineProperty(this, "getBackend", cfg => {
37
+ switch (cfg.type) {
38
+ case _types.StorageType.Restic:
39
+ return this.resticFac.createBackupBackend(cfg);
40
+
41
+ case _types.StorageType.RClone:
42
+ return this.rcloneFac.createBackupBackend(cfg);
43
+ }
44
+
45
+ throw new Error(`Unsupported storage type ${cfg.type}`);
46
+ });
47
+ }
48
+
49
+ }) || _class) || _class) || _class);
50
+ exports.BackupStorageProvider = BackupStorageProvider;
@@ -52,7 +52,12 @@ let StorageConfigProvider = (_dec = (0, _inversify.injectable)(), _dec2 = functi
52
52
  res.repo = 'local:' + this.fs.expandStrPath(path);
53
53
  }
54
54
 
55
- return res;
55
+ return { ...res,
56
+ backup: {
57
+ tag: this.inputs.backupTag,
58
+ snapshotId: this.inputs.backupSnapshotId
59
+ }
60
+ };
56
61
  });
57
62
 
58
63
  _defineProperty(this, "getByCliConfig", inp => {
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.RCloneClientFactory = void 0;
6
+ exports.RCloneFactory = void 0;
7
7
 
8
8
  var _inversify = require("inversify");
9
9
 
@@ -17,6 +17,8 @@ var _RcloneClient = require("./RcloneClient");
17
17
 
18
18
  var _B2CredentialsProvider = require("../b2/B2CredentialsProvider");
19
19
 
20
+ var _RcloneBackupBackend = require("./RcloneBackupBackend");
21
+
20
22
  var _dec, _dec2, _dec3, _class;
21
23
 
22
24
  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; }
@@ -32,14 +34,16 @@ const parseRepoUrl = url => {
32
34
  };
33
35
  };
34
36
 
35
- let RCloneClientFactory = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _Shell.Shell === "undefined" ? Object : _Shell.Shell, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _B2CredentialsProvider.B2CredentialsProvider === "undefined" ? Object : _B2CredentialsProvider.B2CredentialsProvider]), _dec(_class = _dec2(_class = _dec3(_class = class RCloneClientFactory {
37
+ let RCloneFactory = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _Shell.Shell === "undefined" ? Object : _Shell.Shell, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _B2CredentialsProvider.B2CredentialsProvider === "undefined" ? Object : _B2CredentialsProvider.B2CredentialsProvider]), _dec(_class = _dec2(_class = _dec3(_class = class RCloneFactory {
36
38
  constructor(sh, log, fs, b2) {
37
39
  this.sh = sh;
38
40
  this.log = log;
39
41
  this.fs = fs;
40
42
  this.b2 = b2;
41
43
 
42
- _defineProperty(this, "create", cfg => {
44
+ _defineProperty(this, "createBackupBackend", cfg => new _RcloneBackupBackend.RcloneBackupBackend(this.createClient(cfg)));
45
+
46
+ _defineProperty(this, "createClient", cfg => {
43
47
  const {
44
48
  type,
45
49
  location
@@ -66,4 +70,4 @@ let RCloneClientFactory = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.
66
70
  }
67
71
 
68
72
  }) || _class) || _class) || _class);
69
- exports.RCloneClientFactory = RCloneClientFactory;
73
+ exports.RCloneFactory = RCloneFactory;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RcloneBackupBackend = void 0;
7
+
8
+ var _AppLogger = require("../../log/AppLogger");
9
+
10
+ var _nclif = require("@ps-aux/nclif");
11
+
12
+ 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; }
13
+
14
+ class RcloneBackupBackend {
15
+ constructor(rclone) {
16
+ this.rclone = rclone;
17
+
18
+ _defineProperty(this, "log", (0, _AppLogger.logger)(RcloneBackupBackend.name));
19
+
20
+ _defineProperty(this, "backup", (from, tags) => {
21
+ if (tags) throw new _nclif.InvalidInputError(`Rclone does not support tags`);
22
+ this.log.info('Performing backup', {
23
+ from
24
+ });
25
+ this.rclone.backup(from);
26
+ });
27
+
28
+ _defineProperty(this, "restoreLatest", to => {
29
+ this.log.info('Restoring', {
30
+ to
31
+ });
32
+ this.rclone.restore(to);
33
+ });
34
+
35
+ _defineProperty(this, "restoreSnapshot", (to, snapshotId) => {
36
+ throw new _nclif.InvalidInputError(`Rclone does not support snaphosts`);
37
+ });
38
+ }
39
+
40
+ }
41
+
42
+ exports.RcloneBackupBackend = RcloneBackupBackend;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ResticBackupBackend = void 0;
7
+
8
+ var _Path = require("../../fs/path/Path");
9
+
10
+ var _AppLogger = require("../../log/AppLogger");
11
+
12
+ 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; }
13
+
14
+ class ResticBackupBackend {
15
+ constructor(restic) {
16
+ this.restic = restic;
17
+
18
+ _defineProperty(this, "log", (0, _AppLogger.logger)(ResticBackupBackend.name));
19
+
20
+ _defineProperty(this, "backup", (from, tags = []) => {
21
+ this.log.info(`Performing backup from=${from}, tags=${tags}`);
22
+ this.restic.backup(from, _Path.RelativePath.from('.'), tags);
23
+ this.restic.forget();
24
+ });
25
+
26
+ _defineProperty(this, "restoreLatest", to => {
27
+ this.log.info(`Restoring latest snapshot to=${to}`);
28
+ this.restic.restore(to);
29
+ });
30
+
31
+ _defineProperty(this, "restoreSnapshot", (to, snapshotId) => {
32
+ this.log.info(`Restoring snapshot '${snapshotId}'`, {
33
+ to
34
+ });
35
+ this.restic.restore(to, snapshotId);
36
+ });
37
+ }
38
+
39
+ }
40
+
41
+ exports.ResticBackupBackend = ResticBackupBackend;
@@ -14,12 +14,11 @@ const normalizeUrl = url => {
14
14
 
15
15
  return url;
16
16
  };
17
+
17
18
  /**
18
19
  * Tested with: restic 0.9.6 compiled with go1.12.12 on linux/amd64
19
20
  * TODO forwarding stdout to the logger
20
21
  */
21
-
22
-
23
22
  class ResticClient {
24
23
  constructor(cfg, shell, log) {
25
24
  this.cfg = cfg;
@@ -35,19 +34,56 @@ class ResticClient {
35
34
  });
36
35
  });
37
36
 
38
- _defineProperty(this, "backup", (cwd, from) => {
37
+ _defineProperty(this, "runCmd", cmd => {
38
+ return this.shell.execAndReturnBuffer(`restic ${cmd}`, {
39
+ env: this.env()
40
+ });
41
+ });
42
+
43
+ _defineProperty(this, "backup", (cwd, from, tags = []) => {
39
44
  this.log.debug(`Running backup for repo=${this.url}`);
40
- this.shell.exec(`restic backup ${from.str()}`, {
45
+ let cmd = `restic backup ${from.str()}`;
46
+ tags.forEach(t => {
47
+ cmd += ` --tag=${t}`;
48
+ });
49
+ this.shell.exec(cmd, {
41
50
  cwd: cwd.str(),
42
51
  env: this.env()
43
52
  });
44
53
  });
45
54
 
46
- _defineProperty(this, "restore", to => {
55
+ _defineProperty(this, "restore", (to, snapshotId = 'latest') => {
47
56
  this.log.debug('Running restore for repo=', this.url);
48
- this.shell.exec(`restic restore latest --target ${to.str()}`, {
57
+ this.shell.exec(`restic restore ${snapshotId} --target ${to.str()}`, {
58
+ env: this.env()
59
+ });
60
+ });
61
+
62
+ _defineProperty(this, "forget", () => {
63
+ this.log.debug(`Pruning repo=${this.url}`);
64
+ const cfg = {
65
+ hourly: 12,
66
+ daily: 7,
67
+ weekly: 8,
68
+ monthly: 24
69
+ };
70
+ this.shell.exec(`restic forget --prune ` + `--tag '' ` + // Ignore the tagged snapshots
71
+ `--keep-hourly ${cfg.hourly} --keep-daily ${cfg.daily} ` + `--keep-weekly ${cfg.weekly} --keep-monthly ${cfg.monthly}`, {
72
+ env: this.env()
73
+ });
74
+ });
75
+
76
+ _defineProperty(this, "snapshots", () => {
77
+ this.log.debug(`Listing snapshots of repo=${this.url}`);
78
+ const out = this.shell.execAndReturnString(`restic snapshots --json`, {
49
79
  env: this.env()
50
80
  });
81
+ const res = JSON.parse(out);
82
+ return res.map(r => ({
83
+ id: r.id,
84
+ time: new Date(r.time),
85
+ tags: r.tags
86
+ }));
51
87
  });
52
88
 
53
89
  _defineProperty(this, "env", () => ({
@@ -34,8 +34,21 @@ describe('ResticClient', () => {
34
34
  it('create repo', () => {
35
35
  sut.prepareRepo();
36
36
  });
37
- it('push data', () => {
38
- sut.backup(_Path.AbsPath.from(backupDir), _Path.RelativePath.from('.'));
37
+ it('push data & forget', () => {
38
+ const from = _Path.AbsPath.from(backupDir);
39
+
40
+ const to = _Path.RelativePath.from('.');
41
+
42
+ sut.backup(from, to);
43
+ sut.backup(from, to, ['foo', 'bar']);
44
+ sut.forget();
45
+ sut.backup(from, to);
46
+ const res = sut.snapshots();
47
+ expect(res).toBeArrayOfSize(3);
48
+ const tagged = res[1];
49
+ expect(tagged.id).toBeDefined();
50
+ expect(tagged.time).toBeDate();
51
+ expect(tagged.tags).toEqual(['foo', 'bar']);
39
52
  });
40
53
  it('restore data', () => {
41
54
  sut.restore(_Path.AbsPath.from(restoreDir));
@@ -11,7 +11,7 @@ var _ContextSymbols = require("../../ctx/ContextSymbols");
11
11
 
12
12
  var _config = require("../../config");
13
13
 
14
- var _ResticClientFactory = require("./ResticClientFactory");
14
+ var _ResticFactory = require("./ResticFactory");
15
15
 
16
16
  var _AppLogger = require("../../log/AppLogger");
17
17
 
@@ -24,19 +24,34 @@ var _dec, _dec2, _dec3, _dec4, _class;
24
24
  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; }
25
25
 
26
26
  let ResticController = (_dec = (0, _inversify.injectable)(), _dec2 = function (target, key) {
27
- return (0, _inversify.inject)(_ContextSymbols.AppConfig_)(target, undefined, 2);
28
- }, _dec3 = Reflect.metadata("design:type", Function), _dec4 = Reflect.metadata("design:paramtypes", [typeof _ResticClientFactory.ResticClientFactory === "undefined" ? Object : _ResticClientFactory.ResticClientFactory, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _config.Config === "undefined" ? Object : _config.Config, typeof _StorageConfigProvider.StorageConfigProvider === "undefined" ? Object : _StorageConfigProvider.StorageConfigProvider]), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = class ResticController {
29
- constructor(restFact, log, cfg, storageConfigProvider) {
27
+ return (0, _inversify.inject)(_ContextSymbols.AppConfig_)(target, undefined, 1);
28
+ }, _dec3 = Reflect.metadata("design:type", Function), _dec4 = Reflect.metadata("design:paramtypes", [typeof _ResticFactory.ResticFactory === "undefined" ? Object : _ResticFactory.ResticFactory, typeof _config.Config === "undefined" ? Object : _config.Config, typeof _StorageConfigProvider.StorageConfigProvider === "undefined" ? Object : _StorageConfigProvider.StorageConfigProvider]), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = class ResticController {
29
+ constructor(restFact, cfg, storageConfigProvider) {
30
30
  this.restFact = restFact;
31
- this.log = log;
32
31
  this.cfg = cfg;
33
32
  this.storageConfigProvider = storageConfigProvider;
34
33
 
35
- _defineProperty(this, "initRepo", () => {
34
+ _defineProperty(this, "log", (0, _AppLogger.logger)(ResticController.name));
35
+
36
+ _defineProperty(this, "client", () => {
36
37
  const props = this.storageConfigProvider.provide();
37
38
  if (props.type !== _types.StorageType.Restic) throw new Error('Storage is not Restic storage');
38
39
  this.log.info('Initializing repo', props.repo);
39
- this.restFact.create(props).prepareRepo();
40
+ return this.restFact.createClient(props);
41
+ });
42
+
43
+ _defineProperty(this, "initRepo", () => {
44
+ this.client().prepareRepo();
45
+ });
46
+
47
+ _defineProperty(this, "listSnapshots", print => {
48
+ const res = this.client().snapshots();
49
+ print(JSON.stringify(res, null, 4));
50
+ });
51
+
52
+ _defineProperty(this, "runResticCmd", (cmd, print) => {
53
+ const res = this.client().runCmd(cmd);
54
+ print(res.toString());
40
55
  });
41
56
  }
42
57
 
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ResticClientFactory = void 0;
6
+ exports.ResticFactory = void 0;
7
7
 
8
8
  var _inversify = require("inversify");
9
9
 
@@ -17,18 +17,22 @@ var _Fs = require("../../fs/Fs");
17
17
 
18
18
  var _B2CredentialsProvider = require("../b2/B2CredentialsProvider");
19
19
 
20
+ var _ResticBackupBackend = require("./ResticBackupBackend");
21
+
20
22
  var _dec, _dec2, _dec3, _class;
21
23
 
22
24
  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; }
23
25
 
24
- let ResticClientFactory = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _Shell.Shell === "undefined" ? Object : _Shell.Shell, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _B2CredentialsProvider.B2CredentialsProvider === "undefined" ? Object : _B2CredentialsProvider.B2CredentialsProvider]), _dec(_class = _dec2(_class = _dec3(_class = class ResticClientFactory {
26
+ let ResticFactory = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _Shell.Shell === "undefined" ? Object : _Shell.Shell, typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _Fs.Fs === "undefined" ? Object : _Fs.Fs, typeof _B2CredentialsProvider.B2CredentialsProvider === "undefined" ? Object : _B2CredentialsProvider.B2CredentialsProvider]), _dec(_class = _dec2(_class = _dec3(_class = class ResticFactory {
25
27
  constructor(sh, log, fs, b2) {
26
28
  this.sh = sh;
27
29
  this.log = log;
28
30
  this.fs = fs;
29
31
  this.b2 = b2;
30
32
 
31
- _defineProperty(this, "create", cfg => {
33
+ _defineProperty(this, "createBackupBackend", cfg => new _ResticBackupBackend.ResticBackupBackend(this.createClient(cfg)));
34
+
35
+ _defineProperty(this, "createClient", cfg => {
32
36
  if (!cfg.encryptionPassword) throw new Error(`Restic needs encryptionPassword. Repo=${cfg.repo}`);
33
37
  const props = {
34
38
  repo: {
@@ -50,4 +54,4 @@ let ResticClientFactory = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.
50
54
  }
51
55
 
52
56
  }) || _class) || _class) || _class);
53
- exports.ResticClientFactory = ResticClientFactory;
57
+ exports.ResticFactory = ResticFactory;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ps-aux/nodebup",
3
- "version": "0.7.3",
3
+ "version": "0.9.0",
4
4
  "description": "",
5
5
  "module": "lib/index.js",
6
6
  "main": "lib/index.js",
@@ -1,44 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.DataBackupController = void 0;
7
-
8
- var _inversify = require("inversify");
9
-
10
- var _AppLogger = require("../../log/AppLogger");
11
-
12
- var _Path = require("../../fs/path/Path");
13
-
14
- var _StorageBackendProvider = require("../../storage/StorageBackendProvider");
15
-
16
- var _dec, _dec2, _dec3, _class;
17
-
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; }
19
-
20
- let DataBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _AppLogger.AppLogger === "undefined" ? Object : _AppLogger.AppLogger, typeof _StorageBackendProvider.StorageBackendProvider === "undefined" ? Object : _StorageBackendProvider.StorageBackendProvider]), _dec(_class = _dec2(_class = _dec3(_class = class DataBackupController {
21
- constructor(log, storageBackendProvider) {
22
- this.log = log;
23
- this.storageBackendProvider = storageBackendProvider;
24
-
25
- _defineProperty(this, "storage", inp => {
26
- const storage = this.storageBackendProvider.provide();
27
-
28
- const path = _Path.AbsPath.from(inp.path);
29
-
30
- return {
31
- backup: () => {
32
- this.log.info(`Backing up from ${path} to '${storage}'`);
33
- storage.store(path);
34
- },
35
- restore: () => {
36
- this.log.info(`Restoring from '${storage}' to ${path}`);
37
- storage.restore(path);
38
- }
39
- };
40
- });
41
- }
42
-
43
- }) || _class) || _class) || _class);
44
- exports.DataBackupController = DataBackupController;
@@ -1,27 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.BackupClientStorageBackend = void 0;
7
-
8
- var _Path = require("../fs/path/Path");
9
-
10
- 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; }
11
-
12
- class BackupClientStorageBackend {
13
- constructor(client) {
14
- this.client = client;
15
-
16
- _defineProperty(this, "store", from => {
17
- this.client.backup(from, _Path.RelativePath.from('.'));
18
- });
19
-
20
- _defineProperty(this, "restore", to => {
21
- this.client.restore(to);
22
- });
23
- }
24
-
25
- }
26
-
27
- exports.BackupClientStorageBackend = BackupClientStorageBackend;
@@ -1,50 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.StorageBackendProvider = void 0;
7
-
8
- var _inversify = require("inversify");
9
-
10
- var _types = require("./types");
11
-
12
- var _ResticClientFactory = require("./restic/ResticClientFactory");
13
-
14
- var _BackupClientStorageBackend = require("./BackupClientStorageBackend");
15
-
16
- var _RCloneClientFactory = require("./rclone/RCloneClientFactory");
17
-
18
- var _StorageConfigProvider = require("./StorageConfigProvider");
19
-
20
- var _dec, _dec2, _dec3, _class;
21
-
22
- 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; }
23
-
24
- let StorageBackendProvider = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.metadata("design:type", Function), _dec3 = Reflect.metadata("design:paramtypes", [typeof _ResticClientFactory.ResticClientFactory === "undefined" ? Object : _ResticClientFactory.ResticClientFactory, typeof _RCloneClientFactory.RCloneClientFactory === "undefined" ? Object : _RCloneClientFactory.RCloneClientFactory, typeof _StorageConfigProvider.StorageConfigProvider === "undefined" ? Object : _StorageConfigProvider.StorageConfigProvider]), _dec(_class = _dec2(_class = _dec3(_class = class StorageBackendProvider {
25
- constructor(resticFac, rcloneFac, cfgProvider) {
26
- this.resticFac = resticFac;
27
- this.rcloneFac = rcloneFac;
28
- this.cfgProvider = cfgProvider;
29
-
30
- _defineProperty(this, "provide", () => {
31
- const s = this.cfgProvider.provide();
32
- let b = null;
33
-
34
- switch (s.type) {
35
- case _types.StorageType.Restic:
36
- b = this.resticFac.create(s);
37
- break;
38
-
39
- case _types.StorageType.RClone:
40
- b = this.rcloneFac.create(s);
41
- break;
42
- }
43
-
44
- if (!b) throw new Error(`Unsupported storage type ${s.type}`);
45
- return new _BackupClientStorageBackend.BackupClientStorageBackend(b);
46
- });
47
- }
48
-
49
- }) || _class) || _class) || _class);
50
- exports.StorageBackendProvider = StorageBackendProvider;