mirror of
https://github.com/offen/docker-volume-backup.git
synced 2026-04-21 16:12:40 +02:00
Bump github.com/docker/cli from 28.5.2+incompatible to 29.0.2+incompatible (#676)
* Bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 28.5.2+incompatible to 29.0.2+incompatible. - [Commits](https://github.com/docker/cli/compare/v28.5.2...v29.0.2) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-version: 29.0.2+incompatible dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * github.com/docker/docker has been superseded by moby packages * Fix usage of new filter API * Base test env off Docker 29 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Frederik Ring <frederik.ring@gmail.com>
This commit is contained in:
@@ -16,9 +16,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/cosiner/argv"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/moby/moby/api/pkg/stdcopy"
|
||||
"github.com/moby/moby/client"
|
||||
"github.com/offen/docker-volume-backup/internal/errwrap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@@ -36,7 +35,7 @@ func (s *script) exec(containerRef string, command string, user string) ([]byte,
|
||||
fmt.Sprintf("COMMAND_RUNTIME_ARCHIVE_FILEPATH=%s", s.file),
|
||||
}
|
||||
|
||||
execID, err := s.cli.ContainerExecCreate(context.Background(), containerRef, container.ExecOptions{
|
||||
execID, err := s.cli.ExecCreate(context.Background(), containerRef, client.ExecCreateOptions{
|
||||
Cmd: args[0],
|
||||
AttachStdin: true,
|
||||
AttachStderr: true,
|
||||
@@ -47,7 +46,7 @@ func (s *script) exec(containerRef string, command string, user string) ([]byte,
|
||||
return nil, nil, errwrap.Wrap(err, "error creating container exec")
|
||||
}
|
||||
|
||||
resp, err := s.cli.ContainerExecAttach(context.Background(), execID.ID, container.ExecStartOptions{})
|
||||
resp, err := s.cli.ExecAttach(context.Background(), execID.ID, client.ExecAttachOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, errwrap.Wrap(err, "error attaching container exec")
|
||||
}
|
||||
@@ -82,7 +81,7 @@ func (s *script) exec(containerRef string, command string, user string) ([]byte,
|
||||
return nil, nil, errwrap.Wrap(err, "error reading stderr")
|
||||
}
|
||||
|
||||
res, err := s.cli.ContainerExecInspect(context.Background(), execID.ID)
|
||||
res, err := s.cli.ExecInspect(context.Background(), execID.ID, client.ExecInspectOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, errwrap.Wrap(err, "error inspecting container exec")
|
||||
}
|
||||
@@ -95,54 +94,45 @@ func (s *script) exec(containerRef string, command string, user string) ([]byte,
|
||||
}
|
||||
|
||||
func (s *script) runLabeledCommands(label string) error {
|
||||
f := []filters.KeyValuePair{
|
||||
{Key: "label", Value: label},
|
||||
}
|
||||
f := client.Filters{}
|
||||
f.Add("label", label)
|
||||
if s.c.ExecLabel != "" {
|
||||
f = append(f, filters.KeyValuePair{
|
||||
Key: "label",
|
||||
Value: fmt.Sprintf("docker-volume-backup.exec-label=%s", s.c.ExecLabel),
|
||||
})
|
||||
f.Add("label", fmt.Sprintf("docker-volume-backup.exec-label=%s", s.c.ExecLabel))
|
||||
}
|
||||
containersWithCommand, err := s.cli.ContainerList(context.Background(), container.ListOptions{
|
||||
Filters: filters.NewArgs(f...),
|
||||
containersWithCommandResult, err := s.cli.ContainerList(context.Background(), client.ContainerListOptions{
|
||||
Filters: f,
|
||||
})
|
||||
if err != nil {
|
||||
return errwrap.Wrap(err, "error querying for containers")
|
||||
}
|
||||
containersWithCommand := containersWithCommandResult.Items
|
||||
|
||||
var hasDeprecatedContainers bool
|
||||
if label == "docker-volume-backup.archive-pre" {
|
||||
f[0] = filters.KeyValuePair{
|
||||
Key: "label",
|
||||
Value: "docker-volume-backup.exec-pre",
|
||||
}
|
||||
deprecatedContainers, err := s.cli.ContainerList(context.Background(), container.ListOptions{
|
||||
Filters: filters.NewArgs(f...),
|
||||
f = client.Filters{}.Add("label", "docker-volume-backup.exec-pre")
|
||||
deprecatedContainers, err := s.cli.ContainerList(context.Background(), client.ContainerListOptions{
|
||||
Filters: f,
|
||||
})
|
||||
if err != nil {
|
||||
return errwrap.Wrap(err, "error querying for containers")
|
||||
}
|
||||
if len(deprecatedContainers) != 0 {
|
||||
if len(deprecatedContainers.Items) != 0 {
|
||||
hasDeprecatedContainers = true
|
||||
containersWithCommand = append(containersWithCommand, deprecatedContainers...)
|
||||
containersWithCommand = append(containersWithCommand, deprecatedContainers.Items...)
|
||||
}
|
||||
}
|
||||
|
||||
if label == "docker-volume-backup.archive-post" {
|
||||
f[0] = filters.KeyValuePair{
|
||||
Key: "label",
|
||||
Value: "docker-volume-backup.exec-post",
|
||||
}
|
||||
deprecatedContainers, err := s.cli.ContainerList(context.Background(), container.ListOptions{
|
||||
Filters: filters.NewArgs(f...),
|
||||
f = client.Filters{}.Add("label", "docker-volume-backup.exec-post")
|
||||
deprecatedContainers, err := s.cli.ContainerList(context.Background(), client.ContainerListOptions{
|
||||
Filters: f,
|
||||
})
|
||||
if err != nil {
|
||||
return errwrap.Wrap(err, "error querying for containers")
|
||||
}
|
||||
if len(deprecatedContainers) != 0 {
|
||||
if len(deprecatedContainers.Items) != 0 {
|
||||
hasDeprecatedContainers = true
|
||||
containersWithCommand = append(containersWithCommand, deprecatedContainers...)
|
||||
containersWithCommand = append(containersWithCommand, deprecatedContainers.Items...)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
"github.com/offen/docker-volume-backup/internal/storage/ssh"
|
||||
"github.com/offen/docker-volume-backup/internal/storage/webdav"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/leekchan/timeutil"
|
||||
"github.com/moby/moby/client"
|
||||
"github.com/nicholas-fedor/shoutrrr"
|
||||
"github.com/nicholas-fedor/shoutrrr/pkg/router"
|
||||
)
|
||||
@@ -109,7 +109,7 @@ func (s *script) init() error {
|
||||
_, err := os.Stat("/var/run/docker.sock")
|
||||
_, dockerHostSet := os.LookupEnv("DOCKER_HOST")
|
||||
if !os.IsNotExist(err) || dockerHostSet {
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
cli, err := client.New(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
return errwrap.Wrap(err, "failed to create docker client")
|
||||
}
|
||||
|
||||
@@ -13,19 +13,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/command/service/progress"
|
||||
ctr "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
"github.com/moby/moby/client"
|
||||
"github.com/offen/docker-volume-backup/internal/errwrap"
|
||||
)
|
||||
|
||||
func scaleService(cli *client.Client, serviceID string, replicas uint64) ([]string, error) {
|
||||
service, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, swarm.ServiceInspectOptions{})
|
||||
result, err := cli.ServiceInspect(context.Background(), serviceID, client.ServiceInspectOptions{})
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrap(err, fmt.Sprintf("error inspecting service %s", serviceID))
|
||||
}
|
||||
service := result.Service
|
||||
serviceMode := &service.Spec.Mode
|
||||
switch {
|
||||
case serviceMode.Replicated != nil:
|
||||
@@ -34,7 +32,7 @@ func scaleService(cli *client.Client, serviceID string, replicas uint64) ([]stri
|
||||
return nil, errwrap.Wrap(nil, fmt.Sprintf("service to be scaled %s has to be in replicated mode", service.Spec.Name))
|
||||
}
|
||||
|
||||
response, err := cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, swarm.ServiceUpdateOptions{})
|
||||
response, err := cli.ServiceUpdate(context.Background(), service.ID, client.ServiceUpdateOptions{Version: service.Version, Spec: service.Spec})
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrap(err, "error updating service")
|
||||
}
|
||||
@@ -65,16 +63,13 @@ func awaitContainerCountForService(cli *client.Client, serviceID string, count i
|
||||
),
|
||||
)
|
||||
case <-poll.C:
|
||||
containers, err := cli.ContainerList(context.Background(), ctr.ListOptions{
|
||||
Filters: filters.NewArgs(filters.KeyValuePair{
|
||||
Key: "label",
|
||||
Value: fmt.Sprintf("com.docker.swarm.service.id=%s", serviceID),
|
||||
}),
|
||||
containers, err := cli.ContainerList(context.Background(), client.ContainerListOptions{
|
||||
Filters: client.Filters{}.Add("label", fmt.Sprintf("com.docker.swarm.service.id=%s", serviceID)),
|
||||
})
|
||||
if err != nil {
|
||||
return errwrap.Wrap(err, "error listing containers")
|
||||
}
|
||||
if len(containers) == count {
|
||||
if len(containers.Items) == count {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -82,13 +77,13 @@ func awaitContainerCountForService(cli *client.Client, serviceID string, count i
|
||||
}
|
||||
|
||||
func isSwarm(c interface {
|
||||
Info(context.Context) (system.Info, error)
|
||||
Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error)
|
||||
}) (bool, error) {
|
||||
info, err := c.Info(context.Background())
|
||||
result, err := c.Info(context.Background(), client.InfoOptions{})
|
||||
if err != nil {
|
||||
return false, errwrap.Wrap(err, "error getting docker info")
|
||||
}
|
||||
return info.Swarm.LocalNodeState != "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.ControlAvailable, nil
|
||||
return result.Info.Swarm.LocalNodeState != "" && result.Info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && result.Info.Swarm.ControlAvailable, nil
|
||||
}
|
||||
|
||||
func hasLabel(labels map[string]string, key, value string) bool {
|
||||
@@ -113,7 +108,6 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
if s.cli == nil {
|
||||
return noop, nil
|
||||
}
|
||||
|
||||
isDockerSwarm, err := isSwarm(s.cli)
|
||||
if err != nil {
|
||||
return noop, errwrap.Wrap(err, "error determining swarm state")
|
||||
@@ -143,13 +137,13 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
s.c.BackupStopDuringBackupNoRestartLabel,
|
||||
)
|
||||
|
||||
allContainers, err := s.cli.ContainerList(context.Background(), ctr.ListOptions{})
|
||||
allContainers, err := s.cli.ContainerList(context.Background(), client.ContainerListOptions{})
|
||||
if err != nil {
|
||||
return noop, errwrap.Wrap(err, "error querying for containers")
|
||||
}
|
||||
|
||||
var containersToStop []handledContainer
|
||||
for _, c := range allContainers {
|
||||
for _, c := range allContainers.Items {
|
||||
hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, labelValue, s.c.BackupStopDuringBackupNoRestartLabel)
|
||||
if err != nil {
|
||||
return noop, errwrap.Wrap(err, "error querying for containers to stop")
|
||||
@@ -168,7 +162,8 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
var allServices []swarm.Service
|
||||
var servicesToScaleDown []handledSwarmService
|
||||
if isDockerSwarm {
|
||||
allServices, err = s.cli.ServiceList(context.Background(), swarm.ServiceListOptions{Status: true})
|
||||
result, err := s.cli.ServiceList(context.Background(), client.ServiceListOptions{Status: true})
|
||||
allServices := result.Items
|
||||
if err != nil {
|
||||
return noop, errwrap.Wrap(err, "error querying for services")
|
||||
}
|
||||
@@ -205,18 +200,18 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
if isDockerSwarm {
|
||||
for _, container := range containersToStop {
|
||||
if swarmServiceID, ok := container.summary.Labels["com.docker.swarm.service.id"]; ok {
|
||||
parentService, _, err := s.cli.ServiceInspectWithRaw(context.Background(), swarmServiceID, swarm.ServiceInspectOptions{})
|
||||
parentService, err := s.cli.ServiceInspect(context.Background(), swarmServiceID, client.ServiceInspectOptions{})
|
||||
if err != nil {
|
||||
return noop, errwrap.Wrap(err, fmt.Sprintf("error querying for parent service with ID %s", swarmServiceID))
|
||||
}
|
||||
for label := range parentService.Spec.Labels {
|
||||
for label := range parentService.Service.Spec.Labels {
|
||||
if label == "docker-volume-backup.stop-during-backup" {
|
||||
return noop, errwrap.Wrap(
|
||||
nil,
|
||||
fmt.Sprintf(
|
||||
"container %s is labeled to stop but has parent service %s which is also labeled, cannot continue",
|
||||
container.summary.Names[0],
|
||||
parentService.Spec.Name,
|
||||
parentService.Service.Spec.Name,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -229,7 +224,7 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
fmt.Sprintf(
|
||||
"Stopping %d out of %d running container(s) as they were labeled %s or %s.",
|
||||
len(containersToStop),
|
||||
len(allContainers),
|
||||
len(allContainers.Items),
|
||||
stopDuringBackupLabel,
|
||||
stopDuringBackupNoRestartLabel,
|
||||
),
|
||||
@@ -249,7 +244,7 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
var stoppedContainers []handledContainer
|
||||
var stopErrors []error
|
||||
for _, container := range containersToStop {
|
||||
if err := s.cli.ContainerStop(context.Background(), container.summary.ID, ctr.StopOptions{}); err != nil {
|
||||
if _, err := s.cli.ContainerStop(context.Background(), container.summary.ID, client.ContainerStopOptions{}); err != nil {
|
||||
stopErrors = append(stopErrors, err)
|
||||
} else {
|
||||
stoppedContainers = append(stoppedContainers, container)
|
||||
@@ -286,7 +281,7 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
}
|
||||
|
||||
s.stats.Containers = ContainersStats{
|
||||
All: uint(len(allContainers)),
|
||||
All: uint(len(allContainers.Items)),
|
||||
ToStop: uint(len(containersToStop)),
|
||||
Stopped: uint(len(stoppedContainers)),
|
||||
StopErrors: uint(len(stopErrors)),
|
||||
@@ -328,7 +323,8 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
// in case a container was part of a swarm service, the service requires to
|
||||
// be force updated instead of restarting the container as it would otherwise
|
||||
// remain in a "completed" state
|
||||
service, _, err := s.cli.ServiceInspectWithRaw(context.Background(), swarmServiceID, swarm.ServiceInspectOptions{})
|
||||
result, err := s.cli.ServiceInspect(context.Background(), swarmServiceID, client.ServiceInspectOptions{})
|
||||
service := result.Service
|
||||
if err != nil {
|
||||
restartErrors = append(
|
||||
restartErrors,
|
||||
@@ -339,14 +335,14 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
||||
service.Spec.TaskTemplate.ForceUpdate += 1
|
||||
if _, err := s.cli.ServiceUpdate(
|
||||
context.Background(), service.ID,
|
||||
service.Version, service.Spec, swarm.ServiceUpdateOptions{},
|
||||
client.ServiceUpdateOptions{Spec: service.Spec, Version: service.Version},
|
||||
); err != nil {
|
||||
restartErrors = append(restartErrors, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.cli.ContainerStart(context.Background(), container.summary.ID, ctr.StartOptions{}); err != nil {
|
||||
if _, err := s.cli.ContainerStart(context.Background(), container.summary.ID, client.ContainerStartOptions{}); err != nil {
|
||||
restartErrors = append(restartErrors, err)
|
||||
} else {
|
||||
restartedContainers = append(restartedContainers, container)
|
||||
|
||||
@@ -5,16 +5,17 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
"github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/client"
|
||||
)
|
||||
|
||||
type mockInfoClient struct {
|
||||
result system.Info
|
||||
result client.SystemInfoResult
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *mockInfoClient) Info(context.Context) (system.Info, error) {
|
||||
func (m *mockInfoClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) {
|
||||
return m.result, m.err
|
||||
}
|
||||
|
||||
@@ -28,10 +29,12 @@ func TestIsSwarm(t *testing.T) {
|
||||
{
|
||||
"swarm",
|
||||
&mockInfoClient{
|
||||
result: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: swarm.LocalNodeStateActive,
|
||||
ControlAvailable: true,
|
||||
result: client.SystemInfoResult{
|
||||
Info: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: swarm.LocalNodeStateActive,
|
||||
ControlAvailable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -41,9 +44,11 @@ func TestIsSwarm(t *testing.T) {
|
||||
{
|
||||
"worker",
|
||||
&mockInfoClient{
|
||||
result: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: swarm.LocalNodeStateActive,
|
||||
result: client.SystemInfoResult{
|
||||
Info: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: swarm.LocalNodeStateActive,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -53,9 +58,11 @@ func TestIsSwarm(t *testing.T) {
|
||||
{
|
||||
"compose",
|
||||
&mockInfoClient{
|
||||
result: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: swarm.LocalNodeStateInactive,
|
||||
result: client.SystemInfoResult{
|
||||
Info: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: swarm.LocalNodeStateInactive,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -65,9 +72,11 @@ func TestIsSwarm(t *testing.T) {
|
||||
{
|
||||
"balena",
|
||||
&mockInfoClient{
|
||||
result: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: "",
|
||||
result: client.SystemInfoResult{
|
||||
Info: system.Info{
|
||||
Swarm: swarm.Info{
|
||||
LocalNodeState: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ctr "github.com/docker/docker/api/types/container"
|
||||
ctr "github.com/moby/moby/api/types/container"
|
||||
"github.com/offen/docker-volume-backup/internal/errwrap"
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user