@ps-aux/nodebup 0.7.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;