diff --git a/cmd/backup/script.go b/cmd/backup/script.go index 287eaaf..a61f1d5 100644 --- a/cmd/backup/script.go +++ b/cmd/backup/script.go @@ -395,6 +395,26 @@ func (s *script) stopContainersAndServices() (func() error, error) { return noop, nil } + if isDockerSwarm { + for _, container := range containersToStop { + if swarmServiceID, ok := container.Labels["com.docker.swarm.service.id"]; ok { + parentService, _, err := s.cli.ServiceInspectWithRaw(context.Background(), swarmServiceID, types.ServiceInspectOptions{}) + if err != nil { + return noop, fmt.Errorf("(*script).stopContainersAndServices: error querying for parent service with ID %s: %w", swarmServiceID, err) + } + for label := range parentService.Spec.Labels { + if label == "docker-volume-backup.stop-during-backup" { + return noop, fmt.Errorf( + "(*script).stopContainersAndServices: container %s is labeled to stop but has parent service %s which is also labeled, cannot continue", + container.Names[0], + parentService.Spec.Name, + ) + } + } + } + } + } + s.logger.Info( fmt.Sprintf( "Stopping %d out of %d running container(s) and scaling down %d out of %d active service(s) as they were labeled %s.", diff --git a/test/collision/docker-compose.yml b/test/collision/docker-compose.yml new file mode 100644 index 0000000..cd47a15 --- /dev/null +++ b/test/collision/docker-compose.yml @@ -0,0 +1,28 @@ +# Copyright 2020-2021 - Offen Authors +# SPDX-License-Identifier: Unlicense + +version: '3.8' + +services: + backup: + image: offen/docker-volume-backup:${TEST_VERSION:-canary} + environment: + BACKUP_FILENAME: test.tar.gz + volumes: + - offen_data:/backup/offen_data:ro + - ${LOCAL_DIR:-./local}:/archive + - /var/run/docker.sock:/var/run/docker.sock + + offen: + image: offen/offen:latest + labels: + - docker-volume-backup.stop-during-backup=true + deploy: + labels: + - docker-volume-backup.stop-during-backup=true + replicas: 2 + volumes: + - offen_data:/var/opt/offen + +volumes: + offen_data: diff --git a/test/collision/run.sh b/test/collision/run.sh new file mode 100755 index 0000000..8948feb --- /dev/null +++ b/test/collision/run.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +set -e + +cd $(dirname $0) +. ../util.sh +current_test=$(basename $(pwd)) + +export LOCAL_DIR=$(mktemp -d) + +docker swarm init + +docker stack deploy --compose-file=docker-compose.yml test_stack + +while [ -z $(docker ps -q -f name=backup) ]; do + info "Backup container not ready yet. Retrying." + sleep 1 +done + +sleep 20 + +set +e +docker exec $(docker ps -q -f name=backup) backup +if [ $? = "0" ]; then + fail "Expected script to exit with error code." +fi + +if [ -f "${LOCAL_DIR}/test.tar.gz" ]; then + fail "Found backup file that should not have been created." +fi + +expect_running_containers "3" + +pass "Script did not perform backup as there was a label collision."