initial python package
This commit is contained in:
1
backup/__init__.py
Normal file
1
backup/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .main import main
|
||||||
65
backup/main.py
Executable file
65
backup/main.py
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Iterable, Set
|
||||||
|
|
||||||
|
import click
|
||||||
|
import docker
|
||||||
|
import restic
|
||||||
|
from docker.models.containers import Container
|
||||||
|
|
||||||
|
client = docker.from_env()
|
||||||
|
|
||||||
|
def stop_containers(names: Iterable[str]) -> Set[Container]:
|
||||||
|
names = set(names)
|
||||||
|
stopped_containers = set()
|
||||||
|
for con in client.containers.list():
|
||||||
|
if con.name in names:
|
||||||
|
stopped_containers.add(con)
|
||||||
|
try:
|
||||||
|
con.stop()
|
||||||
|
except:
|
||||||
|
print('Error')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print(f'Stopped [{con.short_id}] {con.name}')
|
||||||
|
return stopped_containers
|
||||||
|
|
||||||
|
|
||||||
|
def start_containers(containers: Iterable[Container]):
|
||||||
|
for con in containers:
|
||||||
|
try:
|
||||||
|
con.start()
|
||||||
|
except:
|
||||||
|
print(f'Error starting: [{con.short_id}] {con.name}')
|
||||||
|
else:
|
||||||
|
print(f'Started: [{con.short_id}] {con.name}')
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.argument('src', type=click.Path(exists=True, file_okay=False, readable=True, resolve_path=True, path_type=Path))
|
||||||
|
@click.option('-ds', '--docker-stop', type=click.STRING,
|
||||||
|
help='Comma-delimited list of the container names to stop before running the backup')
|
||||||
|
def main(src: Path, docker_stop: str = None):
|
||||||
|
print(type(src).__name__, src)
|
||||||
|
|
||||||
|
if docker_stop is not None:
|
||||||
|
cons = stop_containers(docker_stop.split(','))
|
||||||
|
else:
|
||||||
|
cons = set()
|
||||||
|
|
||||||
|
pw_file = Path('/run/secrets/restic-pw').resolve()
|
||||||
|
restic.password_file = pw_file.as_posix()
|
||||||
|
|
||||||
|
restic.backup(
|
||||||
|
paths=[''],
|
||||||
|
dry_run=True
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f'{len(restic.snapshots())} snapshots found in the repo')
|
||||||
|
|
||||||
|
start_containers(cons)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
13
pyproject.toml
Normal file
13
pyproject.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "file-backups"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "With restic and Docker"
|
||||||
|
license = {file="LICENSE"}
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
backup = "backup:main"
|
||||||
6
requirements.txt
Normal file
6
requirements.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
docker
|
||||||
|
resticpy
|
||||||
|
click
|
||||||
|
rich
|
||||||
|
|
||||||
|
ipython
|
||||||
Reference in New Issue
Block a user