Ran black formatter

master
Jef Roosens 2021-01-15 14:14:25 +01:00
parent 4cb97897a7
commit 75b5b5b316
3 changed files with 52 additions and 63 deletions

View File

@ -7,19 +7,32 @@ from specs import parse_specs_file
def except_hook(ext_type, value, traceback): def except_hook(ext_type, value, traceback):
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 # Define parser
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Backup directories and Docker volumes.') description="Backup directories and Docker volumes."
parser.add_argument('-f', '--file', action='append', dest='file', )
help='File containing spec definitions.') parser.add_argument(
parser.add_argument('-j', '--json', action='store_const', const=True, "-f",
default=False, help='Print out the parsed specs as JSON ' "--file",
'and exit') action="append",
parser.add_argument('spec', nargs='*', dest="file",
help='The specs to process. Defaults to all.') 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(
"spec", nargs="*", help="The specs to process. Defaults to all."
)
# Parse arguments # Parse arguments
args = parser.parse_args() args = parser.parse_args()
@ -32,6 +45,7 @@ if args.spec:
# 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)) print(json.dumps([spec.to_dict() for spec in specs], indent=4))
else: else:

View File

@ -37,10 +37,7 @@ def parse_specs_file(path: Path) -> List[Spec]:
"destination": None, "destination": None,
"limit": None, "limit": None,
"volume": False, "volume": False,
"notify": { "notify": {"title": "Backup Notification", "events": ["failure"]},
"title": "Backup Notification",
"events": ["failure"]
}
} }
# Read YAML file # Read YAML file
@ -58,9 +55,11 @@ def parse_specs_file(path: Path) -> List[Spec]:
specs = [] specs = []
# Check format for each spec # Check format for each spec
for key in data["specs"]: for key in data["specs"]:
specs.append(Spec.from_dict(key, combine_with_skeleton( specs.append(
data["specs"][key], spec_skel) Spec.from_dict(
)) key, combine_with_skeleton(data["specs"][key], spec_skel)
)
)
return specs return specs
@ -95,20 +94,3 @@ def combine_with_skeleton(data: Dict, skel: Dict) -> Dict:
data[key] = combine_with_skeleton(data[key], value) data[key] = combine_with_skeleton(data[key], value)
return data return data
# Test cases
if __name__ == "__main__":
d1 = {
"a": 5
}
s1 = {
"a": 7,
"b": 2
}
r1 = {
"a": 5,
"b": 2
}
assert combine_with_skeleton(d1, s1) == r1

View File

@ -1,4 +1,3 @@
from pathlib import Path
from datetime import datetime from datetime import datetime
import requests import requests
import os import os
@ -9,32 +8,32 @@ class Spec:
__SKELETON = {} __SKELETON = {}
def __init__(self, name, destination, limit, title, events=None): def __init__(self, name, destination, limit, title, events=None):
self.name = name self.name = name
self.destination = Path(destination) self.destination = Path(destination)
self.limit = limit self.limit = limit
self.title = title self.title = title
self.events = [] if events is None else events self.events = [] if events is None else events
def to_dict(self): def to_dict(self):
return { return {
"name": self.name, "name": self.name,
"destination": str(self.destination), "destination": str(self.destination),
"limit": self.limit, "limit": self.limit,
"notify": { "notify": {"title": self.title, "events": self.events},
"title": self.title,
"events": self.events
}
} }
def backup(self): def backup(self):
raise NotImplementedError() raise NotImplementedError()
def remove_redundant(self): def remove_redundant(self):
tarballs = sorted(self.destination.glob('*.tar.gz'), tarballs = sorted(
key=os.path.getmtime, reverse=True) self.destination.glob("*.tar.gz"),
key=os.path.getmtime,
reverse=True,
)
if len(tarballs) >= self.limit: if len(tarballs) >= self.limit:
for path in tarballs[self.limit - 1:]: for path in tarballs[self.limit - 1 :]:
path.unlink() path.unlink()
def notify(self, status_code): def notify(self, status_code):
@ -59,21 +58,16 @@ class Spec:
return return
url = "https://maker.ifttt.com/trigger/{}/with/key/{}".format( url = "https://maker.ifttt.com/trigger/{}/with/key/{}".format(
"phone_notifications", "phone_notifications", key
key
) )
data = { data = {"value1": self.title, "value2": message}
"value1": self.title,
"value2": message
}
requests.post(url, data=data) requests.post(url, data=data)
def get_filename(self): def get_filename(self):
return '{}_{}.tar.gz'.format( return "{}_{}.tar.gz".format(
self.name, self.name, datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
) )
@staticmethod @staticmethod
@ -85,11 +79,12 @@ class Spec:
@staticmethod @staticmethod
def from_file(path: str): def from_file(path: str):
with open(path, 'r') as yaml_file: with open(path, "r") as yaml_file:
data = yaml.load(yaml_file, Loader=yaml.Loader) data = yaml.load(yaml_file, Loader=yaml.Loader)
return [Spec.from_dict(name, info) return [
for name, info in data["specs"].items()] Spec.from_dict(name, info) for name, info in data["specs"].items()
]
class DirSpec(Spec): class DirSpec(Spec):
@ -103,8 +98,7 @@ class DirSpec(Spec):
status_code = os.system( status_code = os.system(
"tar -C '{}' -czf '{}' -- .".format( "tar -C '{}' -czf '{}' -- .".format(
self.source, self.source, self.destination / self.get_filename()
self.destination / self.get_filename()
) )
) )
@ -118,9 +112,10 @@ class DirSpec(Spec):
data["destination"], data["destination"],
data["limit"], data["limit"],
data["notify"]["title"], data["notify"]["title"],
data["notify"]["events"] data["notify"]["events"],
) )
class VolumeSpec(Spec): class VolumeSpec(Spec):
def __init__(self, name, volume, destination, limit, title, events=None): def __init__(self, name, volume, destination, limit, title, events=None):
super().__init__(name, destination, limit, title, events) super().__init__(name, destination, limit, title, events)
@ -131,9 +126,7 @@ class VolumeSpec(Spec):
status_code = os.system( status_code = os.system(
"docker run --rm -v '{}:/from' -v '{}:/to' alpine:latest " "docker run --rm -v '{}:/from' -v '{}:/to' alpine:latest "
"tar -C /from -czf '/to/{}' -- .".format( "tar -C /from -czf '/to/{}' -- .".format(
self.volume, self.volume, self.destination, self.get_filename()
self.destination,
self.get_filename()
) )
) )
@ -145,5 +138,5 @@ class VolumeSpec(Spec):
data["destination"], data["destination"],
data["limit"], data["limit"],
data["notify"]["title"], data["notify"]["title"],
data["notify"]["events"] data["notify"]["events"],
) )