Swarm mode check fails on non-standard Info responses (#376)

* Swarm mode check fails on non-standard Info responses

* Add unit test

* Remove balena tests, add note to docs
This commit is contained in:
Frederik Ring 2024-02-27 22:12:36 +01:00 committed by GitHub
parent 6c8b0ccce5
commit 5abfe5bb39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 102 additions and 3 deletions

View File

@ -81,6 +81,16 @@ func awaitContainerCountForService(cli *client.Client, serviceID string, count i
}
}
func isSwarm(c interface {
Info(context.Context) (types.Info, error)
}) (bool, error) {
info, err := c.Info(context.Background())
if err != nil {
return false, errwrap.Wrap(err, "error getting docker info")
}
return info.Swarm.LocalNodeState != "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive, nil
}
// stopContainersAndServices stops all Docker containers that are marked as to being
// stopped during the backup and returns a function that can be called to
// restart everything that has been stopped.
@ -89,11 +99,10 @@ func (s *script) stopContainersAndServices() (func() error, error) {
return noop, nil
}
dockerInfo, err := s.cli.Info(context.Background())
isDockerSwarm, err := isSwarm(s.cli)
if err != nil {
return noop, errwrap.Wrap(err, "error getting docker info")
return noop, errwrap.Wrap(err, "error determining swarm state")
}
isDockerSwarm := dockerInfo.Swarm.LocalNodeState != "inactive"
labelValue := s.c.BackupStopDuringBackupLabel
if s.c.BackupStopContainerLabel != "" {

View File

@ -0,0 +1,85 @@
package main
import (
"context"
"errors"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
)
type mockInfoClient struct {
result types.Info
err error
}
func (m *mockInfoClient) Info(context.Context) (types.Info, error) {
return m.result, m.err
}
func TestIsSwarm(t *testing.T) {
tests := []struct {
name string
client *mockInfoClient
expected bool
expectError bool
}{
{
"swarm",
&mockInfoClient{
result: types.Info{
Swarm: swarm.Info{
LocalNodeState: swarm.LocalNodeStateActive,
},
},
},
true,
false,
},
{
"compose",
&mockInfoClient{
result: types.Info{
Swarm: swarm.Info{
LocalNodeState: swarm.LocalNodeStateInactive,
},
},
},
false,
false,
},
{
"balena",
&mockInfoClient{
result: types.Info{
Swarm: swarm.Info{
LocalNodeState: "",
},
},
},
false,
false,
},
{
"error",
&mockInfoClient{
err: errors.New("the dinosaurs escaped"),
},
false,
true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result, err := isSwarm(test.client)
if (err != nil) != test.expectError {
t.Errorf("Unexpected error value %v", err)
}
if test.expected != result {
t.Errorf("Expected %v, got %v", test.expected, result)
}
})
}
}

View File

@ -100,6 +100,11 @@ docker pull ghcr.io/offen/docker-volume-backup:v2
Documentation references Docker Hub, but all examples will work using ghcr.io just as well.
### Supported Engines
This tool is developed and tested against the Docker CE engine exclusively.
While it may work against different implementations (e.g. Balena Engine), there are no guarantees about support for non-Docker engines.
## Differences to `jareware/docker-volume-backup`
This image is heavily inspired by `jareware/docker-volume-backup`. We decided to publish this image as a simpler and more lightweight alternative because of the following requirements: