diff --git a/backups/app/__main__.py b/backups/app/__main__.py index c340221..535d616 100644 --- a/backups/app/__main__.py +++ b/backups/app/__main__.py @@ -13,22 +13,21 @@ sys.excepthook = except_hook # Define parser parser = argparse.ArgumentParser( description='Backup directories and Docker volumes.') -parser.add_argument('-s', '--spec', action='append', dest='specs', - help='Spec to back up. If not specified, all specs in ' - 'in provided files are processed.') +parser.add_argument('-f', '--file', action='append', dest='file', + help='File containing spec definitions.') parser.add_argument('-j', '--json', action='store_const', const=True, default=False, help='Print out the parsed specs as JSON ' 'and exit') -parser.add_argument('file', nargs='+', - help='A YAML file containg specs.') +parser.add_argument('spec', nargs='*', + help='The specs to process. Defaults to all.') # Parse arguments args = parser.parse_args() specs = sum([parse_specs_file(path) for path in args.file], []) # Filter specs if needed -if args.specs: - specs = filter(lambda s: s.name in args.specs, specs) +if args.spec: + specs = filter(lambda s: s.name in args.spec, specs) # Dump parsed data as json if args.json: diff --git a/backups/app/specs/parser.py b/backups/app/specs/parser.py index d490721..fab362a 100644 --- a/backups/app/specs/parser.py +++ b/backups/app/specs/parser.py @@ -39,7 +39,7 @@ def parse_specs_file(path: Path) -> List[Spec]: "volume": False, "notify": { "title": "Backup Notification", - "events": ["success"] + "events": ["failure"] } } @@ -51,7 +51,9 @@ def parse_specs_file(path: Path) -> List[Spec]: if "specs" not in data: raise MissingKeyError("specs") - # TODO check if only specs section exists + # Allow for default notify settings + if "notify" in data: + spec_skel["notify"] = data["notify"] specs = [] # Check format for each spec diff --git a/backups/app/specs/specs.py b/backups/app/specs/specs.py index 3f64283..bca52fc 100644 --- a/backups/app/specs/specs.py +++ b/backups/app/specs/specs.py @@ -8,7 +8,7 @@ class Spec: self.destination = Path(destination) self.limit = limit self.title = title - self.events = ["success"] if events is None else events + self.events = [] if events is None else events def to_dict(self): return { @@ -24,6 +24,13 @@ class Spec: def backup(self): raise NotImplementedError() + def remove_redundant(self): + tarballs = self.destination.glob('*.tar.gz') + + if len(tarballs) >= self.limit: + for path in tarballs[self.limit - 1:]: + path.unlink() + def notify(status_code): if status_code: if "failure" not in self.events: @@ -79,7 +86,6 @@ class Spec: for name, info in data["specs"].items()] - class DirSpec(Spec): def __init__(self, name, source, destination, limit, title, events=None): super().__init__(name, destination, limit, title, events) @@ -87,14 +93,8 @@ class DirSpec(Spec): self.source = Path(source) def backup(self): - tarballs = self.destination.glob('*.tar.gz') + self.remove_redundant() - # Remove redundant tarballs - if len(tarballs) >= self.limit: - for path in tarballs[self.limit - 1:]: - path.unlink() - - # Create new tarball status_code = os.system( "tar -C '{}' -czf '{}' -- .".format( self.source, @@ -116,4 +116,28 @@ class DirSpec(Spec): ) class VolumeSpec(Spec): - pass + def __init__(self, name, volume, destination, limit, title, events=None): + super().__init__(name, destination, limit, title, events) + + self.volume = volume + + def backup(self): + status_code = os.system( + "docker run --rm -v '{}:/from' -v '{}:/to' alpine:latest " + "tar -C /from -czf '/to/{}' -- .".format( + self.volume, + self.destination, + self.get_filename() + ) + ) + + @staticmethod + def from_dict(name, data): + return VolumeSpec( + name, + data["source"], + data["destination"], + data["limit"], + data["notify"]["title"], + data["notify"]["events"] + ) diff --git a/backups/backups.yaml.example b/backups/backups.yaml.example index 812608e..68a203b 100644 --- a/backups/backups.yaml.example +++ b/backups/backups.yaml.example @@ -1,11 +1,13 @@ +notify: + title: "title" + events: + - 'random' + specs: test-spec: source: '/some/path' destination: '/some/other/path' limit: 7 - notify: - events: - - 'failure' test-2: source: '/path/to'