diff --git a/configuration.ini.example b/configuration.ini.example new file mode 100644 index 0000000..f9d3f4f --- /dev/null +++ b/configuration.ini.example @@ -0,0 +1,9 @@ +[backandup] +bindincludepattern=list of fixed strings +bindexcludepattern=list of fixed strings + +[restic] +remotehost= +remoteuser= +repository= +passwordfile= \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..1412651 --- /dev/null +++ b/main.py @@ -0,0 +1,77 @@ +import docker +import restic +import yaml +import configparser + + +bindingIncludePattern = None +bindingExcludePattern = None +remoteHost = None +remoteUser = None +repository = None +passwordFile = None + + +def read_config_file(filepath: str = "configuration.ini"): + parser = configparser.ConfigParser() + parser.read(filepath) + global bindingIncludePattern + global bindingExcludePattern + global remoteHost + global remoteUser + global repository + global passwordFile + bindingIncludePattern = parser["backandup"]["bindingincludepattern"] + bindingExcludePattern = parser["backandup"]["bindingexcludepattern"] + remoteHost = parser["restic"]["remotehost"] + remoteUser = parser["restic"]["remoteuser"] + repository = parser["restic"]["repository"] + passwordFile = parser["restic"]["passwordfile"] + + +def do_backup(dirpath: str, tags: str = None): + repoString = f"sftp:{remoteUser}@{remoteHost}:/{repository}" + restic.repository = repoString + restic.password_file = passwordFile + if tags is None: + restic.backup(paths=[dirpath]) + else: + restic.backup(paths=[dirpath], tags=[]) + + +def backup_ct_binds(ct: docker.models.containers.Container, includepattern: str|list = None, + excludepattern: str|list = None): + if ct.attrs['HostConfig']['Binds'] is None: + print("Nothing to backup") + return 0 + if type(includepattern) is str: + includepattern = [includepattern] + if type(excludepattern) is str: + excludepattern = [excludepattern] + if type(includepattern) is None: + includepattern = ["NOPATTERNTOINCLUDEXXXXXX"] + if type(excludepattern) is None: + excludepattern = ["NOPATTERNTOEXCLUDEXXXXXX"] + for BindMount in ct.attrs['HostConfig']['Binds']: + BindPath = BindMount.split(":")[0] + # Si on matche au moins 1 pattern d'inclusion ET aucun pattern d'exclusion + if any(x in BindPath for x in includepattern) and not any(x in BindPath for x in excludepattern): + do_backup(BindPath) + return 0 + + +def stop_backup_restart_container(ct: docker.models.containers.Container): + dorestart = False + if ct.attrs['State']['Status'] == 'running': + dorestart = True + ct.stop() + backup_ct_binds(ct, bindingIncludePattern, bindingExcludePattern) + if dorestart: + ct.start() + return 0 + +# Press the green button in the gutter to run the script. +if __name__ == '__main__': + dockerhost = docker.from_env() + for container in dockerhost.containers.list(all=True): + stop_backup_restart_container(container)