Added documentation
continuous-integration/drone the build failed Details

pull/15/head
Jef Roosens 2021-04-25 19:26:12 +02:00
parent d513a03c4a
commit ecfa6fe7b7
Signed by: Jef Roosens
GPG Key ID: B580B976584B5F30
4 changed files with 83 additions and 44 deletions

View File

@ -1,3 +1,4 @@
"""The main entrypoint of the program."""
import argparse import argparse
import sys import sys
from parser import read_specs_file from parser import read_specs_file
@ -5,55 +6,62 @@ from parser import read_specs_file
# This just displays the error type and message, not the stack trace # This just displays the error type and message, not the stack trace
def except_hook(ext_type, value, traceback): def except_hook(ext_type, value, traceback):
"""
Make errors not show the stracktrace to stdout.
Todo:
* Replace this with proper error handling
"""
sys.stderr.write("{}: {}\n".format(ext_type.__name__, value)) sys.stderr.write("{}: {}\n".format(ext_type.__name__, value))
# sys.excepthook = except_hook # sys.excepthook = except_hook
# Define parser if __name__ == "__main__":
parser = argparse.ArgumentParser( # Define parser
description="Backup directories and Docker volumes." parser = argparse.ArgumentParser(
) description="Backup directories and Docker volumes."
parser.add_argument( )
"-f", parser.add_argument(
"--file", "-f",
action="append", "--file",
dest="file", action="append",
required=True, dest="file",
help="File containing spec definitions.", required=True,
) help="File containing spec definitions.",
parser.add_argument( )
"-j", parser.add_argument(
"--json", "-j",
action="store_const", "--json",
const=True, action="store_const",
default=False, const=True,
help="Print out the parsed specs as JSON and exit", default=False,
) help="Print out the parsed specs as JSON and exit",
parser.add_argument( )
"spec", nargs="*", help="The specs to process. Defaults to all." parser.add_argument(
) "spec", nargs="*", help="The specs to process. Defaults to all."
)
# Parse arguments # Parse arguments
args = parser.parse_args() args = parser.parse_args()
specs = sum([read_specs_file(path) for path in args.file], []) specs = sum((read_specs_file(path) for path in args.file), [])
# Filter specs if needed # Filter specs if needed
if args.spec: if args.spec:
specs = list(filter(lambda s: s.name in args.spec, specs)) specs = list(filter(lambda s: s.name in args.spec, specs))
# Dump parsed data as json # Dump parsed data as json
if args.json: if args.json:
import json import json
print(json.dumps([spec.to_dict() for spec in specs], indent=4)) # TODO replace this with error handling system
print(json.dumps([spec.to_dict() for spec in specs], indent=4))
else: elif not specs:
# Run the backups # TODO replace this with error handling system
if not specs: print("No specs, exiting.")
print("No specs, exiting.") sys.exit(0)
sys.exit(0)
for spec in specs: for spec in specs:
spec.backup() spec.backup()

View File

@ -1,4 +1,7 @@
"""Parent module for the various spec types."""
from .spec import Spec from .spec import Spec
from .directory import DirectorySpec from .directory import DirectorySpec
from .volume import VolumeSpec from .volume import VolumeSpec
from .container import ContainerSpec from .container import ContainerSpec
__all__ = ["Spec", "DirectorySpec", "VolumeSpec", "ContainerSpec"]

View File

@ -1,3 +1,4 @@
"""Module defining a Container-based spec."""
from .spec import Spec from .spec import Spec
from typing import Union from typing import Union
from pathlib import Path from pathlib import Path
@ -6,11 +7,10 @@ import subprocess
class ContainerSpec(Spec): class ContainerSpec(Spec):
""" """Spec for backing up via a container."""
A spec for backing up via a container.
"""
_SKEL = {"container": None, "command": None, "mountpoint": "/from"} _SKEL = {"container": None, "command": None, "mountpoint": "/from"}
"""The skeleton for the ContainerSpec config."""
def __init__( def __init__(
self, self,
@ -23,6 +23,22 @@ class ContainerSpec(Spec):
mountpoint: str, mountpoint: str,
notify=None, notify=None,
): ):
"""
Create a new ContainerSpec object.
Args:
name: name of the spec (used as an identifier)
container: the Docker container to back up
destination: where to store the backups (gets created if
non-existent)
limit: max amount of backups to keep
command: command to run inside the container. This command should
perform a specified backup and output this data to stdout. This
output then gets piped to a backup file.
extension: the extension of the backup files.
mountpoint:
notify: notifier object (may be None)
"""
super().__init__(name, destination, limit, extension, notify) super().__init__(name, destination, limit, extension, notify)
self.container = container self.container = container

View File

@ -60,7 +60,19 @@ class Spec:
self.extension = extension self.extension = extension
@classmethod @classmethod
def skeleton(cls): def skeleton(cls: "Spec") -> Dict:
"""
Return the skeleton for the given class.
It works by inspecting the inheritance tree and merging the skeleton
for each of the parents.
Args:
cls: the class to get the skeleton for
Returns:
a dictionary containing the skeleton
"""
return skeleton.merge( return skeleton.merge(
*[val._SKEL for val in reversed(inspect.getmro(cls)[:-1])] *[val._SKEL for val in reversed(inspect.getmro(cls)[:-1])]
) )