@ps-aux/nodebup 0.7.1 → 0.8.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,9 @@ 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
+
20
+ var _Zipper = require("../../tools/compression/Zipper");
19
21
 
20
22
  var _dec, _dec2, _dec3, _class, _class2, _temp;
21
23
 
@@ -35,16 +37,17 @@ const parseConnectionUrl = url => {
35
37
  };
36
38
  };
37
39
 
38
- 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]), _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 {
39
41
  constructor( // private gpg: Gpg,
40
42
  // private ssh: SshKeyManager,
41
43
  fs, // private fsSyncer: FsSyncer,
42
44
  log, storageBackendProvider, // @inject(AppConfig_) private cfg: Config,
43
- sh) {
45
+ sh, zip) {
44
46
  this.fs = fs;
45
47
  this.log = log;
46
48
  this.storageBackendProvider = storageBackendProvider;
47
49
  this.sh = sh;
50
+ this.zip = zip;
48
51
 
49
52
  _defineProperty(this, "now", () => {
50
53
  const d = new Date();
@@ -54,6 +57,8 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
54
57
 
55
58
  _defineProperty(this, "getVersion", version => version || PgBackupController.defaultPgVersion);
56
59
 
60
+ _defineProperty(this, "outFileName", 'backup.sql');
61
+
57
62
  _defineProperty(this, "backup", ({
58
63
  pgUrl,
59
64
  pgVersion
@@ -68,15 +73,15 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
68
73
  const outputDir = _Path.AbsPath.from(dir);
69
74
 
70
75
  this.log.info('Dumping database to a file');
71
- 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)
72
78
 
73
79
  const b = this.sh.execAndReturnBuffer(`docker run --network host ` + `postgres:${version} ` + `bash -c '${bashCmds.join(' && ')}'`);
74
- const outFileName = PgBackupController.outFileName;
75
- const dumpOut = outputDir.resolve(outFileName);
80
+ const dumpOut = outputDir.resolve(this.outFileName);
76
81
  this.fs.writeFile(dumpOut, b);
77
82
  this.log.info('Compressing');
78
83
  const zipOutputName = `pg-backup-${this.now()}.zip`;
79
- this.sh.exec(`cd ${outputDir.str()}; zip ${zipOutputName} ${outFileName}`);
84
+ this.zip.zipDir(outputDir, outputDir.resolve(zipOutputName));
80
85
  this.fs.rmFile(dumpOut);
81
86
  this.log.info('Uploading');
82
87
  storage.store(_Path.AbsPath.from(dir));
@@ -95,16 +100,19 @@ let PgBackupController = (_dec = (0, _inversify.injectable)(), _dec2 = Reflect.m
95
100
  this.fs.inTmpDir('pg-restore', dirStr => {
96
101
  const dir = _Path.AbsPath.from(dirStr);
97
102
 
98
- storage.restore(dir);
99
- const zipFile = this.fs.listFiles(dir)[0]; //
103
+ storage.restore(dir); // TODO check if the dir contains the with the expected name
104
+ // TODO add e2e test for docker
100
105
 
101
- this.sh.exec(`unzip ${zipFile.str()} -d ${dir.str()}`);
106
+ const zipFile = this.fs.listFiles(dir)[0];
107
+ this.zip.unzipDir(zipFile, dir);
102
108
  this.fs.rmFile(zipFile);
103
- const outFile = this.fs.listFiles(dir)[0];
104
- this.sh.exec(`docker run --network host ` + `-v "${outFile.str()}":/pg/import.sql -w /pg ` + `postgres:${version} ` + `psql ${pgUrl} -v ON_ERROR_STOP=0 -f import.sql`);
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
+
112
+ this.sh.exec(`docker run --network host -i ` + `postgres:${version} ` + `psql ${pgUrl} -v ON_ERROR_STOP=0 < ${outFile.str()}`);
105
113
  });
106
114
  });
107
115
  }
108
116
 
109
- }, _defineProperty(_class2, "defaultPgVersion", '14.2'), _defineProperty(_class2, "outFileName", 'out.sql'), _temp)) || _class) || _class) || _class);
117
+ }, _defineProperty(_class2, "defaultPgVersion", '14.2'), _temp)) || _class) || _class) || _class);
110
118
  exports.PgBackupController = PgBackupController;
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
  }),
@@ -94,6 +105,10 @@ const restic = (0, _nclif.cmdGroup)({
94
105
  'init-repo': (0, _nclif.cmd)({
95
106
  options: singleStorageOptions,
96
107
  run: (_, c) => c.get(_ResticController.ResticController).initRepo()
108
+ }),
109
+ snapshots: (0, _nclif.cmd)({
110
+ options: singleStorageOptions,
111
+ run: (_, c, p) => c.get(_ResticController.ResticController).listSnapshots(p.stdout)
97
112
  })
98
113
  }
99
114
  });
@@ -23,22 +23,24 @@ 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
 
40
40
  var _PgBackupController = require("../bup/pg/PgBackupController");
41
41
 
42
+ var _Zipper = require("../tools/compression/Zipper");
43
+
42
44
  const createContext = (cfg, inp) => {
43
45
  const c = new _inversify.Container();
44
46
  c.bind(_ContextSymbols.AppConfig_).toConstantValue(cfg);
@@ -47,7 +49,7 @@ const createContext = (cfg, inp) => {
47
49
  c.bind(_ContextSymbols.Log_).toConstantValue(log);
48
50
  c.bind(_AppLogger.AppLogger).toConstantValue(log);
49
51
  c.bind(_Fs.Fs).toConstantValue(new _Fs.Fs(cfg.pwd, log));
50
- 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];
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];
51
53
  self.forEach(s => c.bind(s).toSelf());
52
54
  return c;
53
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,50 @@ class ResticClient {
35
34
  });
36
35
  });
37
36
 
38
- _defineProperty(this, "backup", (cwd, from) => {
37
+ _defineProperty(this, "backup", (cwd, from, tags = []) => {
39
38
  this.log.debug(`Running backup for repo=${this.url}`);
40
- this.shell.exec(`restic backup ${from.str()}`, {
39
+ let cmd = `restic backup ${from.str()}`;
40
+ tags.forEach(t => {
41
+ cmd += ` --tag=${t}`;
42
+ });
43
+ this.shell.exec(cmd, {
41
44
  cwd: cwd.str(),
42
45
  env: this.env()
43
46
  });
44
47
  });
45
48
 
46
- _defineProperty(this, "restore", to => {
49
+ _defineProperty(this, "restore", (to, snapshotId = 'latest') => {
47
50
  this.log.debug('Running restore for repo=', this.url);
48
- this.shell.exec(`restic restore latest --target ${to.str()}`, {
51
+ this.shell.exec(`restic restore ${snapshotId} --target ${to.str()}`, {
52
+ env: this.env()
53
+ });
54
+ });
55
+
56
+ _defineProperty(this, "forget", () => {
57
+ this.log.debug(`Pruning repo=${this.url}`);
58
+ const cfg = {
59
+ hourly: 12,
60
+ daily: 7,
61
+ weekly: 8,
62
+ monthly: 24
63
+ };
64
+ this.shell.exec(`restic forget --prune ` + `--tag '' ` + // Ignore the tagged snapshots
65
+ `--keep-hourly ${cfg.hourly} --keep-daily ${cfg.daily} ` + `--keep-weekly ${cfg.weekly} --keep-monthly ${cfg.monthly}`, {
66
+ env: this.env()
67
+ });
68
+ });
69
+
70
+ _defineProperty(this, "snapshots", () => {
71
+ this.log.debug(`Listing snapshots of repo=${this.url}`);
72
+ const out = this.shell.execAndReturnString(`restic snapshots --json`, {
49
73
  env: this.env()
50
74
  });
75
+ const res = JSON.parse(out);
76
+ return res.map(r => ({
77
+ id: r.id,
78
+ time: new Date(r.time),
79
+ tags: r.tags
80
+ }));
51
81
  });
52
82
 
53
83
  _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,29 @@ 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));
40
50
  });
41
51
  }
42
52
 
@@ -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;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Zipper = void 0;
7
+
8
+ var _admZip = _interopRequireDefault(require("adm-zip"));
9
+
10
+ var _inversify = require("inversify");
11
+
12
+ var _AppLogger = require("../../log/AppLogger");
13
+
14
+ var _dec, _dec2, _dec3, _class;
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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 Zipper = (_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 Zipper {
21
+ constructor(log) {
22
+ this.log = log;
23
+
24
+ _defineProperty(this, "zipDir", (dir, to) => {
25
+ this.log.debug(`Zipping ${dir} to ${to}`);
26
+ const z = new _admZip.default();
27
+ z.addLocalFolder(dir.str());
28
+ z.writeZip(to.str());
29
+ });
30
+
31
+ _defineProperty(this, "unzipDir", (zipFile, toDir) => {
32
+ this.log.debug(`Unzipping ${zipFile} to ${toDir}`);
33
+ const z = new _admZip.default(zipFile.str());
34
+ z.extractAllTo(toDir.str());
35
+ });
36
+ }
37
+
38
+ }) || _class) || _class) || _class);
39
+ exports.Zipper = Zipper;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ var _Zipper = require("./Zipper");
4
+
5
+ var _Path = require("../../fs/path/Path");
6
+
7
+ var _testHelper = require("../../../test/testHelper");
8
+
9
+ var _AppLogger = require("../../log/AppLogger");
10
+
11
+ it('zip', () => {
12
+ const z = new _Zipper.Zipper(new _AppLogger.AppLogger());
13
+
14
+ const out = _Path.AbsPath.from(__dirname).resolve('../../test-data/out.zip');
15
+
16
+ const dir = _Path.AbsPath.from(__dirname).resolve('../../../test/foo');
17
+
18
+ z.zipDir(dir, out);
19
+
20
+ const extDir = _Path.AbsPath.from(__dirname).resolve('../../test-data/foo-out');
21
+
22
+ z.unzipDir(out, extDir);
23
+ (0, _testHelper.expectDirsToBeTheSame)(dir.str(), extDir.str());
24
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ps-aux/nodebup",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "",
5
5
  "module": "lib/index.js",
6
6
  "main": "lib/index.js",
@@ -80,6 +80,7 @@
80
80
  "@hapi/joi": "^17.1.1",
81
81
  "@ps-aux/nclif": "^0.0.7-alpha.1",
82
82
  "@types/hapi__joi": "^17.1.8",
83
+ "adm-zip": "^0.5.9",
83
84
  "axios": "^0.24.0",
84
85
  "handlebars": "^4.7.7",
85
86
  "ini": "^2.0.0",
@@ -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;