1414
1515class Container :
1616 """Represents a docker container"""
17+
1718 container_type = None
1819
1920 def __init__ (self , data : dict ):
2021 self ._data = data
21- self ._state = data .get (' State' )
22- self ._config = data .get (' Config' )
23- self ._mounts = [Mount (mnt , container = self ) for mnt in data .get (' Mounts' )]
22+ self ._state = data .get (" State" )
23+ self ._config = data .get (" Config" )
24+ self ._mounts = [Mount (mnt , container = self ) for mnt in data .get (" Mounts" )]
2425
2526 if not self ._state :
26- raise ValueError (' Container meta missing State' )
27+ raise ValueError (" Container meta missing State" )
2728 if self ._config is None :
28- raise ValueError (' Container meta missing Config' )
29+ raise ValueError (" Container meta missing Config" )
2930
30- self ._labels = self ._config .get (' Labels' )
31+ self ._labels = self ._config .get (" Labels" )
3132 if self ._labels is None :
32- raise ValueError (' Container meta missing Config->Labels' )
33+ raise ValueError (" Container meta missing Config->Labels" )
3334
3435 self ._include = self ._parse_pattern (self .get_label (enums .LABEL_VOLUMES_INCLUDE ))
3536 self ._exclude = self ._parse_pattern (self .get_label (enums .LABEL_VOLUMES_EXCLUDE ))
3637
3738 @property
38- def instance (self ) -> ' Container' :
39+ def instance (self ) -> " Container" :
3940 """Container: Get a service specific subclass instance"""
4041 # TODO: Do this smarter in the future (simple registry)
4142 if self .database_backup_enabled :
4243 from restic_compose_backup import containers_db
44+
4345 if self .mariadb_backup_enabled :
4446 return containers_db .MariadbContainer (self ._data )
4547 if self .mysql_backup_enabled :
@@ -52,28 +54,29 @@ def instance(self) -> 'Container':
5254 @property
5355 def id (self ) -> str :
5456 """str: The id of the container"""
55- return self ._data .get ('Id' )
57+ return self ._data .get ("Id" )
5658
5759 @property
5860 def hostname (self ) -> str :
59- """12 character hostname based on id """
60- return self .id [:12 ]
61+ """Hostname of the container """
62+ return self .get_config ( "Hostname" , default = self . id [0 :12 ])
6163
6264 @property
6365 def image (self ) -> str :
6466 """Image name"""
65- return self .get_config (' Image' )
67+ return self .get_config (" Image" )
6668
6769 @property
6870 def name (self ) -> str :
6971 """Container name"""
70- return self ._data [' Name' ].replace ('/' , '' )
72+ return self ._data [" Name" ].replace ("/" , "" )
7173
7274 @property
7375 def service_name (self ) -> str :
7476 """Name of the container/service"""
75- return self .get_label ('com.docker.compose.service' , default = '' ) or \
76- self .get_label ('com.docker.swarm.service.name' , default = '' )
77+ return self .get_label (
78+ "com.docker.compose.service" , default = ""
79+ ) or self .get_label ("com.docker.swarm.service.name" , default = "" )
7780
7881 @property
7982 def backup_process_label (self ) -> str :
@@ -83,7 +86,7 @@ def backup_process_label(self) -> str:
8386 @property
8487 def project_name (self ) -> str :
8588 """str: Name of the compose setup"""
86- return self .get_label (' com.docker.compose.project' , default = '' )
89+ return self .get_label (" com.docker.compose.project" , default = "" )
8790
8891 @property
8992 def stack_name (self ) -> str :
@@ -93,28 +96,28 @@ def stack_name(self) -> str:
9396 @property
9497 def is_oneoff (self ) -> bool :
9598 """Was this container started with run command?"""
96- return self .get_label (' com.docker.compose.oneoff' , default = ' False' ) == ' True'
99+ return self .get_label (" com.docker.compose.oneoff" , default = " False" ) == " True"
97100
98101 @property
99102 def environment (self ) -> list :
100103 """All configured env vars for the container as a list"""
101- return self .get_config (' Env' )
104+ return self .get_config (" Env" )
102105
103106 def remove (self ):
104107 self ._data .remove ()
105108
106109 def get_config_env (self , name ) -> str :
107110 """Get a config environment variable by name"""
108111 # convert to dict and fetch env var by name
109- data = {i [0 : i .find ('=' )]: i [i .find ('=' ) + 1 :] for i in self .environment }
112+ data = {i [0 : i .find ("=" )]: i [i .find ("=" ) + 1 :] for i in self .environment }
110113 return data .get (name )
111114
112115 def set_config_env (self , name , value ):
113116 """Set an environment variable"""
114117 env = self .environment
115- new_value = f' { name } ={ value } '
118+ new_value = f" { name } ={ value } "
116119 for i , entry in enumerate (env ):
117- if f' { name } =' in entry :
120+ if f" { name } =" in entry :
118121 env [i ] = new_value
119122 break
120123 else :
@@ -129,19 +132,21 @@ def volumes(self) -> dict:
129132 volumes = {}
130133 for mount in self ._mounts :
131134 volumes [mount .source ] = {
132- ' bind' : mount .destination ,
133- ' mode' : 'rw' ,
135+ " bind" : mount .destination ,
136+ " mode" : "rw" ,
134137 }
135138
136139 return volumes
137140
138141 @property
139142 def backup_enabled (self ) -> bool :
140143 """Is backup enabled for this container?"""
141- return any ([
142- self .volume_backup_enabled ,
143- self .database_backup_enabled ,
144- ])
144+ return any (
145+ [
146+ self .volume_backup_enabled ,
147+ self .database_backup_enabled ,
148+ ]
149+ )
145150
146151 @property
147152 def volume_backup_enabled (self ) -> bool :
@@ -155,50 +160,63 @@ def volume_backup_enabled(self) -> bool:
155160 @property
156161 def database_backup_enabled (self ) -> bool :
157162 """bool: Is database backup enabled in any shape or form?"""
158- return any ([
159- self .mysql_backup_enabled ,
160- self .mariadb_backup_enabled ,
161- self .postgresql_backup_enabled ,
162- ])
163+ return any (
164+ [
165+ self .mysql_backup_enabled ,
166+ self .mariadb_backup_enabled ,
167+ self .postgresql_backup_enabled ,
168+ ]
169+ )
163170
164171 @property
165172 def mysql_backup_enabled (self ) -> bool :
166173 """bool: If the ``stack-back.mysql`` label is set"""
167174 explicity_enabled = utils .is_true (self .get_label (enums .LABEL_MYSQL_ENABLED ))
168175 explicity_disabled = utils .is_false (self .get_label (enums .LABEL_MYSQL_ENABLED ))
169- automatically_enabled = utils .is_true (config .auto_backup_all ) and self .image .startswith ('mysql:' )
176+ automatically_enabled = utils .is_true (
177+ config .auto_backup_all
178+ ) and self .image .startswith ("mysql:" )
170179 return explicity_enabled or (automatically_enabled and not explicity_disabled )
171180
172181 @property
173182 def mariadb_backup_enabled (self ) -> bool :
174183 """bool: If the ``stack-back.mariadb`` label is set"""
175184 explicity_enabled = utils .is_true (self .get_label (enums .LABEL_MARIADB_ENABLED ))
176185 explicity_disabled = utils .is_false (self .get_label (enums .LABEL_MARIADB_ENABLED ))
177- automatically_enabled = utils .is_true (config .auto_backup_all ) and self .image .startswith ('mariadb:' )
186+ automatically_enabled = utils .is_true (
187+ config .auto_backup_all
188+ ) and self .image .startswith ("mariadb:" )
178189 return explicity_enabled or (automatically_enabled and not explicity_disabled )
179190
180191 @property
181192 def postgresql_backup_enabled (self ) -> bool :
182193 """bool: If the ``stack-back.postgres`` label is set"""
183194 explicity_enabled = utils .is_true (self .get_label (enums .LABEL_POSTGRES_ENABLED ))
184- explicity_disabled = utils .is_false (self .get_label (enums .LABEL_POSTGRES_ENABLED ))
185- automatically_enabled = utils .is_true (config .auto_backup_all ) and self .image .startswith ('postgres:' )
195+ explicity_disabled = utils .is_false (
196+ self .get_label (enums .LABEL_POSTGRES_ENABLED )
197+ )
198+ automatically_enabled = utils .is_true (
199+ config .auto_backup_all
200+ ) and self .image .startswith ("postgres:" )
186201 return explicity_enabled or (automatically_enabled and not explicity_disabled )
187202
188203 @property
189204 def stop_during_backup (self ) -> bool :
190205 """bool: If the ``stack-back.volumes.stop-during-backup`` label is set"""
191- return utils .is_true (self .get_label (enums .LABEL_STOP_DURING_BACKUP )) and not self .database_backup_enabled
206+ return (
207+ utils .is_true (self .get_label (enums .LABEL_STOP_DURING_BACKUP ))
208+ and not self .database_backup_enabled
209+ )
192210
193211 @property
194212 def is_backup_process_container (self ) -> bool :
195213 """Is this container the running backup process?"""
196- return self .get_label (self .backup_process_label ) == ' True'
214+ return self .get_label (self .backup_process_label ) == " True"
197215
198216 @property
199217 def is_running (self ) -> bool :
200218 """bool: Is the container running?"""
201- return self ._state .get (' Running' , False )
219+ return self ._state .get (" Running" , False )
202220
203221 def get_config (self , name , default = None ):
204222 """Get value from config dict"""
@@ -215,7 +233,11 @@ def filter_mounts(self):
215233
216234 # If exclude_bind_mounts is true, only volume mounts are kept in the list of mounts
217235 exclude_bind_mounts = utils .is_true (config .exclude_bind_mounts )
218- mounts = list (filter (lambda m : not exclude_bind_mounts or m .type == "volume" , self ._mounts ))
236+ mounts = list (
237+ filter (
238+ lambda m : not exclude_bind_mounts or m .type == "volume" , self ._mounts
239+ )
240+ )
219241
220242 if not self .volume_backup_enabled :
221243 return filtered
@@ -239,20 +261,23 @@ def filter_mounts(self):
239261 filtered .append (mount )
240262 else :
241263 for mount in mounts :
242- if self .database_backup_enabled and mount .destination in database_mounts :
264+ if (
265+ self .database_backup_enabled
266+ and mount .destination in database_mounts
267+ ):
243268 continue
244269 filtered .append (mount )
245270
246271 return filtered
247272
248- def volumes_for_backup (self , source_prefix = ' /volumes' , mode = 'ro' ):
273+ def volumes_for_backup (self , source_prefix = " /volumes" , mode = "ro" ):
249274 """Get volumes configured for backup"""
250275 mounts = self .filter_mounts ()
251276 volumes = {}
252277 for mount in mounts :
253278 volumes [mount .source ] = {
254- ' bind' : self .get_volume_backup_destination (mount , source_prefix ),
255- ' mode' : mode ,
279+ " bind" : self .get_volume_backup_destination (mount , source_prefix ),
280+ " mode" : mode ,
256281 }
257282
258283 return volumes
@@ -263,7 +288,7 @@ def get_volume_backup_destination(self, mount, source_prefix) -> str:
263288
264289 if utils .is_true (config .include_project_name ):
265290 project_name = self .project_name
266- if project_name != '' :
291+ if project_name != "" :
267292 destination /= project_name
268293
269294 destination /= self .service_name
@@ -303,7 +328,7 @@ def _parse_pattern(self, value: str) -> List[str]:
303328 if len (value ) == 0 :
304329 return None
305330
306- return value .split (',' )
331+ return value .split ("," )
307332
308333 def __eq__ (self , other ):
309334 """Compare container by id"""
@@ -324,6 +349,7 @@ def __str__(self):
324349
325350class Mount :
326351 """Represents a volume mount (volume or bind)"""
352+
327353 def __init__ (self , data , container = None ):
328354 self ._data = data
329355 self ._container = container
@@ -336,22 +362,22 @@ def container(self) -> Container:
336362 @property
337363 def type (self ) -> str :
338364 """bind/volume"""
339- return self ._data .get (' Type' )
365+ return self ._data .get (" Type" )
340366
341367 @property
342368 def name (self ) -> str :
343369 """Name of the mount"""
344- return self ._data .get (' Name' )
370+ return self ._data .get (" Name" )
345371
346372 @property
347373 def source (self ) -> str :
348374 """Source of the mount. Volume name or path"""
349- return self ._data .get (' Source' )
375+ return self ._data .get (" Source" )
350376
351377 @property
352378 def destination (self ) -> str :
353379 """Destination path for the volume mount in the container"""
354- return self ._data .get (' Destination' )
380+ return self ._data .get (" Destination" )
355381
356382 def __repr__ (self ) -> str :
357383 return str (self )
@@ -382,7 +408,7 @@ def __init__(self):
382408 # Find the container we are running in.
383409 # If we don't have this information we cannot continue
384410 for container_data in all_containers :
385- if container_data .get ('Id' ).startswith (os .environ [' HOSTNAME' ]):
411+ if container_data .get ("Id" ).startswith (os .environ [" HOSTNAME" ]):
386412 self .this_container = Container (container_data )
387413
388414 if not self .this_container :
@@ -393,9 +419,11 @@ def __init__(self):
393419 container = Container (container_data )
394420
395421 # Gather stale backup process containers
396- if (self .this_container .image == container .image
397- and not container .is_running
398- and container .is_backup_process_container ):
422+ if (
423+ self .this_container .image == container .image
424+ and not container .is_running
425+ and container .is_backup_process_container
426+ ):
399427 self .stale_backup_process_containers .append (container )
400428
401429 # We only care about running containers after this point
@@ -450,12 +478,14 @@ def containers_for_backup(self):
450478 """Obtain all containers with backup enabled"""
451479 return [container for container in self .containers if container .backup_enabled ]
452480
453- def generate_backup_mounts (self , dest_prefix = ' /volumes' ) -> dict :
481+ def generate_backup_mounts (self , dest_prefix = " /volumes" ) -> dict :
454482 """Generate mounts for backup for the entire compose setup"""
455483 mounts = {}
456484 for container in self .containers_for_backup ():
457485 if container .volume_backup_enabled :
458- mounts .update (container .volumes_for_backup (source_prefix = dest_prefix , mode = 'ro' ))
486+ mounts .update (
487+ container .volumes_for_backup (source_prefix = dest_prefix , mode = "ro" )
488+ )
459489
460490 return mounts
461491
0 commit comments