92 lines
2.6 KiB
Python
92 lines
2.6 KiB
Python
|
import dataclasses
|
||
|
import datetime
|
||
|
import os
|
||
|
import pathlib
|
||
|
import sys
|
||
|
from typing import List
|
||
|
from typing import Optional
|
||
|
|
||
|
import plumbum.cmd
|
||
|
import plumbum.machines
|
||
|
|
||
|
|
||
|
@dataclasses.dataclass
|
||
|
class Config:
|
||
|
repo_path: pathlib.Path
|
||
|
archive_path: List[str]
|
||
|
check: bool = True
|
||
|
compact: bool = True
|
||
|
repo_init: bool = True
|
||
|
repo_init_append_only: bool = False
|
||
|
repo_init_quota: Optional[str] = None
|
||
|
repo_init_encryption: str = ""
|
||
|
repo_init_overwrite_key: bool = False
|
||
|
repo_key_file: pathlib.Path = pathlib.Path("/keys")
|
||
|
repo_passphrase: Optional[str] = None
|
||
|
repo_passphrase_file: Optional[pathlib.Path] = None
|
||
|
prune: bool = False
|
||
|
prune_interval: Optional[datetime.timedelta] = None
|
||
|
prune_secondly: Optional[int] = None
|
||
|
prune_minutely: Optional[int] = None
|
||
|
prune_hourly: Optional[int] = None
|
||
|
prune_daily: Optional[int] = None
|
||
|
prune_weekly: Optional[int] = None
|
||
|
prune_monthly: Optional[int] = None
|
||
|
prune_yearly: Optional[int] = None
|
||
|
archive_name: Optional[str] = None
|
||
|
archive_comment: Optional[str] = None
|
||
|
archive_exclude_pattern: Optional[str] = None
|
||
|
archive_exclude_caches: bool = False
|
||
|
archive_exclude_if_present: Optional[str] = None
|
||
|
archive_keep_exclude_tags: bool = False
|
||
|
|
||
|
@classmethod
|
||
|
def build(cls):
|
||
|
parameters = {}
|
||
|
for conf, field in cls.__dataclass_fields__.items():
|
||
|
env = f"BORGDRONE_{conf.upper()}"
|
||
|
if env in os.environ:
|
||
|
if field.type == bool:
|
||
|
parameters[conf] = cls._parse_bool(env, os.environ[env])
|
||
|
|
||
|
return cls(**parameters)
|
||
|
|
||
|
@staticmethod
|
||
|
def _parse_bool(env: str, value: str) -> bool:
|
||
|
if value.lower().strip() == "true":
|
||
|
return True
|
||
|
elif value.lower().strip() == "false":
|
||
|
return False
|
||
|
else:
|
||
|
raise RuntimeError(
|
||
|
f"Environment variable {env} contains an unexpected value '{value}', expected one of: 'true', 'false'"
|
||
|
)
|
||
|
|
||
|
|
||
|
def check_version(borg: plumbum.machines.LocalCommand):
|
||
|
version = borg["--version"]().partition(" ")[-1].strip()
|
||
|
|
||
|
if int(version.partition(".")[0]) < 2:
|
||
|
raise RuntimeError("BorgDrone requires BorgBackup version 2.0 or higher")
|
||
|
|
||
|
print(f"Using BorgBackup {version} from {borg.executable}", file=sys.stderr)
|
||
|
|
||
|
|
||
|
def main() -> int:
|
||
|
borg = plumbum.cmd.borg
|
||
|
code = 0
|
||
|
|
||
|
try:
|
||
|
check_version(borg)
|
||
|
|
||
|
config = Config.build()
|
||
|
except RuntimeError as err:
|
||
|
print(f"FATAL: {err}", file=sys.stderr)
|
||
|
code = 1
|
||
|
|
||
|
return code
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
sys.exit(main())
|