From d2d5c0aa0f197b3ca48324f01d5e2dedfc3d09f6 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 18 Apr 2019 03:50:24 +0200 Subject: [PATCH] Make Container class compatible with new json format --- restic_volume_backup/containers.py | 149 +++++++++++++++++------------ 1 file changed, 86 insertions(+), 63 deletions(-) diff --git a/restic_volume_backup/containers.py b/restic_volume_backup/containers.py index 5e1b172..117cacc 100644 --- a/restic_volume_backup/containers.py +++ b/restic_volume_backup/containers.py @@ -13,15 +13,93 @@ class Container: """Represents a docker container""" def __init__(self, data): - self.id = data.get('Id') - self.state = data.get('State') - self.image = data.get('Image') - self.labels = data.get('Labels', {}) - self.names = data.get('Names', []) - self.mounts = [Mount(mnt, container=self) for mnt in data.get('Mounts')] + self._data = data + self.id = data['Id'] + self.name = data['Name'] - self.include = self._parse_pattern(self.labels.get('restic-volume-backup.include')) - self.exclude = self._parse_pattern(self.labels.get('restic-volume-backup.exclude')) + self._state = data.get('State') + self._config = data.get('Config') + self._mounts = [Mount(mnt, container=self) for mnt in data.get('Mounts')] + + if not self._state: + raise ValueError('Container meta missing State') + if self._config is None: + raise ValueError('Container meta missing Config') + + self._labels = self._config.get('Labels') + if self._labels is None: + raise ValueError('Container mtea missing Config->Labels') + + self._include = self._parse_pattern(self.get_label('restic-volume-backup.include')) + self._exclude = self._parse_pattern(self.get_label('restic-volume-backup.exclude')) + + @property + def image(self): + """Image name""" + return self.get_config('Image') + + @property + def backup_enabled(self) -> bool: + """Is backup enabled for this container?""" + return self.get_label('restic-volume-backup.enabled') == 'True' + + @property + def is_backup_process_container(self) -> bool: + """Is this container the running backup process?""" + return self.get_label('restic-volume-backup.backup_process') == 'True' + + @property + def is_running(self) -> bool: + """Is the container running?""" + return self._state.get('Running', False) + + @property + def service_name(self) ->str: + """Name of the container/service""" + return self.get_label('com.docker.compose.service', default='') + + @property + def project_name(self) -> str: + """Name of the compose setup""" + return self.get_label('com.docker.compose.project', default='') + + @property + def is_oneoff(self) -> bool: + """Was this container started with run command?""" + return self.get_label('com.docker.compose.oneoff', default='False') == 'True' + + def get_config(self, name): + """Get value from config dict""" + return self._config.get(name) + + def get_label(self, name, default=None): + """Get a label by name""" + return self._labels.get(name, None) + + def filter_mounts(self): + """Get all mounts for this container matching include/exclude filters""" + filtered = [] + if self._include: + for mount in self._mounts: + for pattern in self._include: + if pattern in mount.source: + break + else: + continue + + filtered.append(mount) + + elif self._exclude: + for mount in self._mounts: + for pattern in self._exclude: + if pattern in mount.source: + break + else: + filtered.append(mount) + else: + return self._mounts + + return filtered def _parse_pattern(self, value): if not value: @@ -36,61 +114,6 @@ class Container: return value.split(',') - @property - def backup_enabled(self): - """Is backup enabled for this container?""" - return self.labels.get('restic-volume-backup.enabled') == 'True' - - @property - def is_backup_process_container(self): - """Is this container the running backup process?""" - return self.labels.get('restic-volume-backup.backup_process') == 'True' - - @property - def is_running(self): - """Is the container running?""" - return self.state == 'running' - - @property - def service_name(self): - """Name of the container/service""" - return self.labels.get('com.docker.compose.service', '') - - @property - def project_name(self): - """Name of the compose setup""" - return self.labels.get('com.docker.compose.project', {}) - - @property - def is_oneoff(self): - """Was this container started with run command?""" - return self.labels.get('com.docker.compose.oneoff', 'False') == 'True' - - def filter_mounts(self): - """Get all mounts for this container matching include/exclude filters""" - filtered = [] - if self.include: - for mount in self.mounts: - for pattern in self.include: - if pattern in mount.source: - break - else: - continue - - filtered.append(mount) - - elif self.exclude: - for mount in self.mounts: - for pattern in self.exclude: - if pattern in mount.source: - break - else: - filtered.append(mount) - else: - return self.mounts - - return filtered - def to_dict(self): return { 'Id': self.id,