def status(config, containers): """Outputs the backup config for the compose setup""" logger.info("Status for compose project '%s'", containers.project_name) logger.info("Repository: '%s'", config.repository) logger.info("Backup currently running?: %s", containers.backup_process_running) logger.info("Checking docker availability") utils.list_containers() if containers.stale_backup_process_containers: utils.remove_containers(containers.stale_backup_process_containers) # Check if repository is initialized with restic snapshots if not restic.is_initialized(config.repository): logger.info( "Could not get repository info. Attempting to initialize it.") result = restic.init_repo(config.repository) if result == 0: logger.info("Successfully initialized repository: %s", config.repository) else: logger.error("Failed to initialize repository") logger.info("%s Detected Config %s", "-" * 25, "-" * 25) # Start making snapshots backup_containers = containers.containers_for_backup() for container in backup_containers: logger.info('service: %s', container.service_name) if container.volume_backup_enabled: for mount in container.filter_mounts(): logger.info(' - volume: %s', mount.source) if container.database_backup_enabled: instance = container.instance ping = instance.ping() logger.info(' - %s (is_ready=%s)', instance.container_type, ping == 0) if ping != 0: logger.error("Database '%s' in service %s cannot be reached", instance.container_type, container.service_name) if len(backup_containers) == 0: logger.info( "No containers in the project has 'restic-compose-backup.*' label") logger.info("-" * 67)
def __init__(self): all_containers = utils.list_containers() self.containers = [] self.this_container = None self.backup_process_container = None self.stale_backup_process_containers = [] # Find the container we are running in. # If we don't have this information we cannot continue for container_data in all_containers: if container_data.get('Id').startswith(os.environ['HOSTNAME']): self.this_container = Container(container_data) if not self.this_container: raise ValueError("Cannot find metadata for backup container") # Gather all running containers in the current compose setup for container_data in all_containers: container = Container(container_data) # Gather stale backup process containers if (self.this_container.image == container.image and not container.is_running and container.is_backup_process_container): self.stale_backup_process_containers.append(container) # We only care about running containers after this point if not container.is_running: continue # Detect running backup process container if container.is_backup_process_container: self.backup_process_container = container # --- Determine what containers should be evaludated # If not swarm mode we need to filter in compose project if not config.swarm_mode: if container.project_name != self.this_container.project_name: continue # Containers started manually are not included if container.is_oneoff: continue # Do not include the backup process container if container == self.backup_process_container: continue self.containers.append(container)
def test_list_containers(self): """Test a basic container list""" containers = [ { 'service': 'web', 'labels': { 'moo': 1, }, 'mounts': [{ 'Source': 'moo', 'Destination': 'moo', 'Type': 'bind', }] }, { 'service': 'mysql', }, { 'service': 'postgres', }, ] with mock.patch(list_containers_func, fixtures.containers(containers=containers)): test = utils.list_containers()
def status(config, containers): """Outputs the backup config for the compose setup""" logger.info("Status for compose project '%s'", containers.project_name) logger.info("Repository: '%s'", config.repository) logger.info("Backup currently running?: %s", containers.backup_process_running) logger.info("Include project name in backup path?: %s", utils.is_true(config.include_project_name)) logger.debug("Exclude bind mounts from backups?: %s", utils.is_true(config.exclude_bind_mounts)) logger.info("Checking docker availability") utils.list_containers() if containers.stale_backup_process_containers: utils.remove_containers(containers.stale_backup_process_containers) # Check if repository is initialized with restic snapshots if not restic.is_initialized(config.repository): logger.info("Could not get repository info. Attempting to initialize it.") result = restic.init_repo(config.repository) if result == 0: logger.info("Successfully initialized repository: %s", config.repository) else: logger.error("Failed to initialize repository") logger.info("%s Detected Config %s", "-" * 25, "-" * 25) # Start making snapshots backup_containers = containers.containers_for_backup() for container in backup_containers: logger.info('service: %s', container.service_name) if container.minecraft_backup_enabled: instance = container.instance ping = instance.ping() logger.info( ' - %s (is_ready=%s):', instance.container_type, ping == 0 ) for mount in container.filter_mounts(): source = container.get_volume_backup_destination(mount, '/minecraft') logger.info( ' - volume: %s -> %s', mount.source, source, ) excludes_file = os.path.join(source, "excludes.txt") logger.debug( 'excludes_file location: %s', excludes_file ) if os.path.isfile(excludes_file): logger.info( ' excluding: %s', utils.join_file_content(excludes_file) ) if container.volume_backup_enabled: for mount in container.filter_mounts(): source = container.get_volume_backup_destination(mount, '/volumes') logger.info( ' - volume: %s -> %s', mount.source, source, ) excludes_file = os.path.join(source, "excludes.txt") logger.debug( 'excludes_file location: %s', excludes_file ) if os.path.isfile(excludes_file): logger.info( ' excluding: %s', utils.join_file_content(excludes_file) ) if container.database_backup_enabled: instance = container.instance ping = instance.ping() logger.info( ' - %s (is_ready=%s) -> %s', instance.container_type, ping == 0, instance.backup_destination_path(), ) if ping != 0: logger.error("Database '%s' in service %s cannot be reached", instance.container_type, container.service_name) if len(backup_containers) == 0: logger.info("No containers in the project has 'restic-compose-backup.*' label") logger.info("-" * 67)